深度学习(34)—— StarGAN(2)

深度学习(34)—— StarGAN(2)

完整项目在这里:欢迎造访

文章目录

  • 深度学习(34)—— StarGAN(2)
    • 1. build model
      • (1)generator
      • (2)mapping network
      • (3)style encoder
      • (4)discriminator
    • 2. 加载数据dataloader
    • 3. train
    • 4. 训练 discriminator
      • (1)real image loss
      • (2)fake image loss
    • 5. 训练generator
      • (1) adversarial loss
      • (2) style restruction loss
      • (3) diversity sensitive loss
      • (4)cycle-consistency loss
    • 重点关注`!!!!!`
    • debug processing

使用数据集结构:

  • data
    • train
      • domian 1
        • img 1
        • img 2
      • domain 2
        • img1
        • img2
      • domain n
    • val
      • domian 1
        • img 1
        • img 2
      • domain 2
        • img1
        • img2
      • domain n

1. build model

(1)generator

在这里插入图片描述

class Generator(nn.Module):def __init__(self, img_size=256, style_dim=64, max_conv_dim=512, w_hpf=1):super().__init__()dim_in = 2**14 // img_sizeself.img_size = img_sizeself.from_rgb = nn.Conv2d(3, dim_in, 3, 1, 1) #(in_channels,out_channels,kernel_size,stride,padding)self.encode = nn.ModuleList()self.decode = nn.ModuleList()self.to_rgb = nn.Sequential(nn.InstanceNorm2d(dim_in, affine=True),nn.LeakyReLU(0.2),nn.Conv2d(dim_in, 3, 1, 1, 0))# down/up-sampling blocksrepeat_num = int(np.log2(img_size)) - 4if w_hpf > 0:repeat_num += 1for _ in range(repeat_num):dim_out = min(dim_in*2, max_conv_dim)self.encode.append(ResBlk(dim_in, dim_out, normalize=True, downsample=True))self.decode.insert(0, AdainResBlk(dim_out, dim_in, style_dim,w_hpf=w_hpf, upsample=True))  # stack-likedim_in = dim_out# bottleneck blocksfor _ in range(2):self.encode.append(ResBlk(dim_out, dim_out, normalize=True))self.decode.insert(0, AdainResBlk(dim_out, dim_out, style_dim, w_hpf=w_hpf))if w_hpf > 0:device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')self.hpf = HighPass(w_hpf, device)def forward(self, x, s, masks=None):x = self.from_rgb(x)cache = {}for block in self.encode:if (masks is not None) and (x.size(2) in [32, 64, 128]):cache[x.size(2)] = xx = block(x)for block in self.decode:x = block(x, s)if (masks is not None) and (x.size(2) in [32, 64, 128]):mask = masks[0] if x.size(2) in [32] else masks[1]mask = F.interpolate(mask, size=x.size(2), mode='bilinear')x = x + self.hpf(mask * cache[x.size(2)])return self.to_rgb(x)

在这里插入图片描述
在这里插入图片描述
encoder 和decoder各6个ResBlk

(2)mapping network

在这里插入图片描述

class MappingNetwork(nn.Module):def __init__(self, latent_dim=16, style_dim=64, num_domains=2):super().__init__()layers = []layers += [nn.Linear(latent_dim, 512)]layers += [nn.ReLU()]for _ in range(3):layers += [nn.Linear(512, 512)]layers += [nn.ReLU()]self.shared = nn.Sequential(*layers)self.unshared = nn.ModuleList()for _ in range(num_domains):self.unshared += [nn.Sequential(nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, style_dim))]def forward(self, z, y):h = self.shared(z)out = []for layer in self.unshared:out += [layer(h)]out = torch.stack(out, dim=1)  # (batch, num_domains, style_dim)idx = torch.LongTensor(range(y.size(0))).to(y.device)s = out[idx, y]  # (batch, style_dim)return s

在这里插入图片描述
在这里插入图片描述
unshared中有多个相同的分支,每个domain都有一个

(3)style encoder

在这里插入图片描述

class StyleEncoder(nn.Module):def __init__(self, img_size=256, style_dim=64, num_domains=2, max_conv_dim=512):super().__init__()dim_in = 2**14 // img_sizeblocks = []blocks += [nn.Conv2d(3, dim_in, 3, 1, 1)]repeat_num = int(np.log2(img_size)) - 2for _ in range(repeat_num):dim_out = min(dim_in*2, max_conv_dim)blocks += [ResBlk(dim_in, dim_out, downsample=True)]dim_in = dim_outblocks += [nn.LeakyReLU(0.2)]blocks += [nn.Conv2d(dim_out, dim_out, 4, 1, 0)]blocks += [nn.LeakyReLU(0.2)]self.shared = nn.Sequential(*blocks)self.unshared = nn.ModuleList()for _ in range(num_domains):self.unshared += [nn.Linear(dim_out, style_dim)]def forward(self, x, y):h = self.shared(x)h = h.view(h.size(0), -1)out = []for layer in self.unshared:out += [layer(h)]out = torch.stack(out, dim=1)  # (batch, num_domains, style_dim)idx = torch.LongTensor(range(y.size(0))).to(y.device)s = out[idx, y]  # (batch, style_dim)return s

在这里插入图片描述
在这里插入图片描述
unshared和上面的mapping network一样有两个domain所以有两个linear

(4)discriminator

class Discriminator(nn.Module):def __init__(self, img_size=256, num_domains=2, max_conv_dim=512):super().__init__()dim_in = 2**14 // img_sizeblocks = []blocks += [nn.Conv2d(3, dim_in, 3, 1, 1)]repeat_num = int(np.log2(img_size)) - 2for _ in range(repeat_num):dim_out = min(dim_in*2, max_conv_dim)blocks += [ResBlk(dim_in, dim_out, downsample=True)]dim_in = dim_outblocks += [nn.LeakyReLU(0.2)]blocks += [nn.Conv2d(dim_out, dim_out, 4, 1, 0)]blocks += [nn.LeakyReLU(0.2)]blocks += [nn.Conv2d(dim_out, num_domains, 1, 1, 0)]self.main = nn.Sequential(*blocks)def forward(self, x, y):out = self.main(x)out = out.view(out.size(0), -1)  # (batch, num_domains)idx = torch.LongTensor(range(y.size(0))).to(y.device)out = out[idx, y]  # (batch)return out

在这里插入图片描述
和style_encoder只有后面一点点不同
build完model之后就有权重加载权重,没有略过。下面打印了每个subnet的模型参数量
在这里插入图片描述

2. 加载数据dataloader

def get_train_loader(root, which='source', img_size=256,batch_size=8, prob=0.5, num_workers=4):print('Preparing DataLoader to fetch %s images ''during the training phase...' % which)crop = transforms.RandomResizedCrop(img_size, scale=[0.8, 1.0], ratio=[0.9, 1.1])rand_crop = transforms.Lambda(lambda x: crop(x) if random.random() < prob else x)transform = transforms.Compose([rand_crop,transforms.Resize([img_size, img_size]),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5]),])if which == 'source':dataset = ImageFolder(root, transform)elif which == 'reference':dataset = ReferenceDataset(root, transform)else:raise NotImplementedErrorsampler = _make_balanced_sampler(dataset.targets)return data.DataLoader(dataset=dataset,batch_size=batch_size,sampler=sampler,num_workers=num_workers,pin_memory=True,drop_last=True)

如果图片是train直接用ImageFold,如果是reference使用自定义的ReferenceDatabase

class ReferenceDataset(data.Dataset):def __init__(self, root, transform=None):self.samples, self.targets = self._make_dataset(root)self.transform = transformdef _make_dataset(self, root):domains = os.listdir(root)fnames, fnames2, labels = [], [], []for idx, domain in enumerate(sorted(domains)):class_dir = os.path.join(root, domain)cls_fnames = listdir(class_dir)fnames += cls_fnamesfnames2 += random.sample(cls_fnames, len(cls_fnames))labels += [idx] * len(cls_fnames)return list(zip(fnames, fnames2)), labelsdef __getitem__(self, index):fname, fname2 = self.samples[index]label = self.targets[index]img = Image.open(fname).convert('RGB')img2 = Image.open(fname2).convert('RGB')if self.transform is not None:img = self.transform(img)img2 = self.transform(img2)return img, img2, labeldef __len__(self):return len(self.targets)

reference 是在每个domain中选择两张图片,这两张图片有相同的label。fnames用于记录其中一张图片,fnames2记录另一张,label记录两者的标签

def get_test_loader(root, img_size=256, batch_size=32,shuffle=True, num_workers=4):print('Preparing DataLoader for the generation phase...')transform = transforms.Compose([transforms.Resize([img_size, img_size]),transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5]),])dataset = ImageFolder(root, transform)return data.DataLoader(dataset=dataset,batch_size=batch_size,shuffle=shuffle,num_workers=num_workers,pin_memory=True)

3. train

    def train(self, loaders):args = self.argsnets = self.netsnets_ema = self.nets_emaoptims = self.optims# fetch random validation images for debuggingfetcher = InputFetcher(loaders.src, loaders.ref, args.latent_dim, 'train')fetcher_val = InputFetcher(loaders.val, None, args.latent_dim, 'val')inputs_val = next(fetcher_val)# resume training if necessaryif args.resume_iter > 0:self._load_checkpoint(args.resume_iter)# remember the initial value of ds weightinitial_lambda_ds = args.lambda_dsprint('Start training...')start_time = time.time()for i in range(args.resume_iter, args.total_iters):# fetch images and labelsinputs = next(fetcher)x_real, y_org = inputs.x_src, inputs.y_srcx_ref, x_ref2, y_trg = inputs.x_ref, inputs.x_ref2, inputs.y_refz_trg, z_trg2 = inputs.z_trg, inputs.z_trg2masks = nets.fan.get_heatmap(x_real) if args.w_hpf > 0 else None# train the discriminatord_loss, d_losses_latent = compute_d_loss(nets, args, x_real, y_org, y_trg, z_trg=z_trg, masks=masks)self._reset_grad()d_loss.backward()optims.discriminator.step()d_loss, d_losses_ref = compute_d_loss(nets, args, x_real, y_org, y_trg, x_ref=x_ref, masks=masks)self._reset_grad()d_loss.backward()optims.discriminator.step()# train the generatorg_loss, g_losses_latent = compute_g_loss(nets, args, x_real, y_org, y_trg, z_trgs=[z_trg, z_trg2], masks=masks)self._reset_grad()g_loss.backward()optims.generator.step()optims.mapping_network.step()optims.style_encoder.step()g_loss, g_losses_ref = compute_g_loss(nets, args, x_real, y_org, y_trg, x_refs=[x_ref, x_ref2], masks=masks)self._reset_grad()g_loss.backward()optims.generator.step()# compute moving average of network parametersmoving_average(nets.generator, nets_ema.generator, beta=0.999)moving_average(nets.mapping_network, nets_ema.mapping_network, beta=0.999)moving_average(nets.style_encoder, nets_ema.style_encoder, beta=0.999)# decay weight for diversity sensitive lossif args.lambda_ds > 0:args.lambda_ds -= (initial_lambda_ds / args.ds_iter)# print out log infoif (i+1) % args.print_every == 0:elapsed = time.time() - start_timeelapsed = str(datetime.timedelta(seconds=elapsed))[:-7]log = "Elapsed time [%s], Iteration [%i/%i], " % (elapsed, i+1, args.total_iters)all_losses = dict()for loss, prefix in zip([d_losses_latent, d_losses_ref, g_losses_latent, g_losses_ref],['D/latent_', 'D/ref_', 'G/latent_', 'G/ref_']):for key, value in loss.items():all_losses[prefix + key] = valueall_losses['G/lambda_ds'] = args.lambda_dslog += ' '.join(['%s: [%.4f]' % (key, value) for key, value in all_losses.items()])print(log)# generate images for debuggingif (i+1) % args.sample_every == 0:os.makedirs(args.sample_dir, exist_ok=True)utils.debug_image(nets_ema, args, inputs=inputs_val, step=i+1)# save model checkpointsif (i+1) % args.save_every == 0:self._save_checkpoint(step=i+1)# compute FID and LPIPS if necessaryif (i+1) % args.eval_every == 0:calculate_metrics(nets_ema, args, i+1, mode='latent')calculate_metrics(nets_ema, args, i+1, mode='reference')

4. 训练 discriminator

def compute_d_loss(nets, args, x_real, y_org, y_trg, z_trg=None, x_ref=None, masks=None):assert (z_trg is None) != (x_ref is None)   #X_real 为原图,y_org为原图的label。y_trg 为reference的label,z_trg 为reference随机生成的向量# with real imagesx_real.requires_grad_()out = nets.discriminator(x_real, y_org)loss_real = adv_loss(out, 1)loss_reg = r1_reg(out, x_real)# with fake imageswith torch.no_grad():if z_trg is not None:s_trg = nets.mapping_network(z_trg, y_trg)else:  # x_ref is not Nones_trg = nets.style_encoder(x_ref, y_trg)x_fake = nets.generator(x_real, s_trg, masks=masks)out = nets.discriminator(x_fake, y_trg)loss_fake = adv_loss(out, 0)loss = loss_real + loss_fake + args.lambda_reg * loss_regreturn loss, Munch(real=loss_real.item(),fake=loss_fake.item(),reg=loss_reg.item())

latent 得到style 向量

(1)real image loss

  • 需要先将real image输入discriminator得到结果out(batch*domain_num)
  • 然后根据real image的label取真正label的结果(batch)
  • 使用out计算与label的BCEloss
def adv_loss(logits, target):assert target in [1, 0]targets = torch.full_like(logits, fill_value=target)loss = F.binary_cross_entropy_with_logits(logits, targets)return loss
  • 使用out计算与real image的回归loss (regression loss)
def r1_reg(d_out, x_in):# zero-centered gradient penalty for real imagesbatch_size = x_in.size(0)grad_dout = torch.autograd.grad(outputs=d_out.sum(), inputs=x_in,create_graph=True, retain_graph=True, only_inputs=True)[0] # 输入是image,属于这一类的pgrad_dout2 = grad_dout.pow(2)assert(grad_dout2.size() == x_in.size())reg = 0.5 * grad_dout2.view(batch_size, -1).sum(1).mean(0)return reg

(2)fake image loss

  • 首先需要根据上面生成的随机向量经过mapping network生成每个风格风格向量
with torch.no_grad():if z_trg is not None:s_trg = nets.mapping_network(z_trg, y_trg)else:  # x_ref is not Nones_trg = nets.style_encoder(x_ref, y_trg)
  • mapping network 的输入是随机生成的latent 向量和label,因为mapping network是多分支的,所以有几个domain在network的结尾就有几个分支,之后根据label选择这个分支的结果作为最后的风格向量s_trg。
  • 使用得到的风格向量s_trg和当前真实的图进入generator【希望real image转换为inference那样的风格】
  • generator在decoder的过程中encoder得到的向量连同风格向量s_trg一起作为decoder的输入生成属于该风格的fake image
  • 将fake image和其对应的label输入discriminator【为什么还要输入对应的label,又不是计算loss?—— 因为discriminator也是多分支的,要根据真实的label取出预测的这个分支的value
  • 因为是fake image,所以是和0做lossloss_fake = adv_loss(out, 0)

到这里我们已经计算了三个loss,分别是real image的loss, fake image 的loss 和real image得到的regeression loss,三者加权相加做为最后的discriminator的loss
loss = loss_real + loss_fake + args.lambda_reg * loss_reg


reference image 得到style 向量

latent向量:d_loss, d_losses_latent = compute_d_loss(nets, args, x_real, y_org, y_trg, z_trg=z_trg, masks=masks)
reference image:d_loss, d_losses_ref = compute_d_loss(nets, args, x_real, y_org, y_trg, x_ref=x_ref, masks=masks)

  • 【有reference的时候相当于有图像了,不需要根据latent向量经过mapping network生成风格向量,而是使用reference image经过style encoder生成属于该style的风格向量】
  • style encoder: reference image经过encoder生成一个向量,该向量再经过多分支得到style 向量,之后根据reference image的label得到最终的style 向量
  • real image 根据reference image经过style encoder生成的style向量生成fake image
  • 后面的过程和上面相同

5. 训练generator

def compute_g_loss(nets, args, x_real, y_org, y_trg, z_trgs=None, x_refs=None, masks=None):assert (z_trgs is None) != (x_refs is None)if z_trgs is not None:z_trg, z_trg2 = z_trgsif x_refs is not None:x_ref, x_ref2 = x_refs# adversarial lossif z_trgs is not None:s_trg = nets.mapping_network(z_trg, y_trg)else:s_trg = nets.style_encoder(x_ref, y_trg)x_fake = nets.generator(x_real, s_trg, masks=masks)out = nets.discriminator(x_fake, y_trg)loss_adv = adv_loss(out, 1)# style reconstruction losss_pred = nets.style_encoder(x_fake, y_trg)loss_sty = torch.mean(torch.abs(s_pred - s_trg))# diversity sensitive lossif z_trgs is not None:s_trg2 = nets.mapping_network(z_trg2, y_trg)else:s_trg2 = nets.style_encoder(x_ref2, y_trg)x_fake2 = nets.generator(x_real, s_trg2, masks=masks)x_fake2 = x_fake2.detach()loss_ds = torch.mean(torch.abs(x_fake - x_fake2))# cycle-consistency lossmasks = nets.fan.get_heatmap(x_fake) if args.w_hpf > 0 else Nones_org = nets.style_encoder(x_real, y_org)x_rec = nets.generator(x_fake, s_org, masks=masks)loss_cyc = torch.mean(torch.abs(x_rec - x_real))loss = loss_adv + args.lambda_sty * loss_sty \- args.lambda_ds * loss_ds + args.lambda_cyc * loss_cycreturn loss, Munch(adv=loss_adv.item(),sty=loss_sty.item(),ds=loss_ds.item(),cyc=loss_cyc.item())

latent 向量 生成style 向量

(1) adversarial loss

  • 将real image和style向量输入generator生成fake image
  • fake image 和 他的label经过discriminator辨别得到结果out
  • 和上面一样计算BCEloss,但是这里虽然是生成的图,但是我们希望generator生成的fake image骗过discriminator,所以这里是和1做BCEloss:loss_adv = adv_loss(out, 1)

(2) style restruction loss

  • fake image 是我们根据real image 得到的希望的style的图片。
  • 现在将fake image输入style encoder 得到这个image的style向量
  • 这个向量和前面的真实style之间做lossloss_sty = torch.mean(torch.abs(s_pred - s_trg))

(3) diversity sensitive loss

之前我们不是reference image都有两个嘛,现在排上用场了,前面我们处理的都是第一个reference,无论是latent 向量还是reference image

  • 将第二个latent向量输入mapping network得到style 向量
  • 将real image和这个style 向量输入generator生成第二个fake image
  • 计算两个fake image之间的lossloss_ds = torch.mean(torch.abs(x_fake - x_fake2))

我们希望同一张图片被转化为另一个风格都是不一样的,不是每次都是一样的,所以这个loss 我们希望是越大越好的

(4)cycle-consistency loss

  • 我们希望real image生成的指定style的fake image经过指定real style 可以返回real image’,所以这里设置了cyclegan-consistency loss
  • 根据fake image生成mask
  • 使用style encoder得到real image的style向量
  • generator根据fake image和real image的style向量生成rec_image
  • 计算real image 和 recovery image之间做lossloss_cyc = torch.mean(torch.abs(x_rec - x_real))

到这里generator的loss全部计算完,一共有四个,分别是对抗loss (loss_adv),风格loss(loss_sty),多样性loss(loss_ds),循环loss(loss_cyc),最终generator的loss为:loss = loss_adv + args.lambda_sty * loss_sty - args.lambda_ds * loss_ds + args.lambda_cyc * loss_cyc


reference image 生成style 向量

latent 向量:g_loss, g_losses_latent = compute_g_loss(nets, args, x_real, y_org, y_trg, z_trgs=[z_trg, z_trg2], masks=masks)
reference image:g_loss, g_losses_ref = compute_g_loss(nets, args, x_real, y_org, y_trg, x_refs=[x_ref, x_ref2], masks=masks)

重点关注!!!!!

  • 无论是discriminator 还是generator都有两个过程:

    1. 使用latent向量经过mapping network生成的style 向量作为最终要转化的style
    2. 使用reference image经过style encoder生成的style向量作为最终要转化的style
  • 无论latent向量还是reference image都是有两个的

debug processing

  • build_model

    • generator
    • mapping network
    • style_encoder
    • discriminator
  • data

  • train

okk,又是脑细胞死亡的一天,好饿好饿,886~
完整项目在这里:欢迎造访

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/76914.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE常用基础

. 1.oracle开机启动流程 su - oracle lsnrctl start lsnrctl status sqlplus / as sysdba startup 2、如何查看数据库版本 select * from v$version; 3.如何查看用户从那个设备连接的数据库 SELECT DISTINCT machine , terminal FROM V$SESSION; 4.如何查看表结构 selec…

css实现水平居中

代码示例 <div class"box"><div class"box1"></div> </div>1.弹性布局&#xff1a;&#xff08;推荐&#xff09; display:flex&#xff1b; 这些要添加在父级的&#xff0c;是父级的属性 //父级添加display:flex; //父级添加jus…

docker安装MinIO

简介 Minio 是一个面向对象的简单高性能存储服务。使用 Go 语言编写&#xff0c;性能高、具有跨平台性。 Minio 官网为&#xff1a;https://min.io &#xff0c;有一个中文站点&#xff0c;单内容更新不是很及时&#xff0c;建议从原始官网学习。 本文采用 Docker 安装&…

Compose:从重组谈谈页面性能优化思路,狠狠优化一笔

作者&#xff1a;晴天小庭 前言&#xff1a; 随着越来越多的人使用Compose开发项目的组件或者页面&#xff0c;关于使用Compose构建的组件卡顿的反馈也愈发增多&#xff0c;特别是LazyColumn这些重组频率较高的组件&#xff0c;因此很多人质疑Compose的性能过差&#xff0c;这…

Filebeat+ELK 部署

Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.8.10 Elasticsearch Kibana Node2节点&#xff08;2C/4G&#xff09;&#xff1a;node2/192.168.8.11 Elasticsearch Apache节点&#xff1a;apache/192.168.8.13 …

神码ai伪原创工具【php源码】

大家好&#xff0c;小编为大家解答python炫酷烟花表白源代码的问题。很多人还不知道html代码烟花特效python&#xff0c;现在让我们一起来看看吧&#xff01; 火车头采集ai伪原创插件截图&#xff1a; 目录 前言 环境准备 代码编写 效果展示 前言 Python实现浪漫的烟花特效 现在…

HTTP协议 和 HTTPS协议的区别(4点) HTTPS的缺点 HTTP如何使用SSL/TLS协议加密过程 CA证书干啥的

&#xff08;一&#xff09;HTTP协议 和 HTTPS协议的区别&#xff08;4点&#xff09;&#xff1a; 1. HTTP协议的端口号是80&#xff0c; HTTPS协议的端口号是443 2. HTTP协议使用的URL是以 http:// 开头&#xff0c;HTTPS协议使用的URL是以https://开头 3. HTTP协议和HTTP…

PHP8的运算符-PHP8知识详解

运算符是可以通过给出的一或多个值&#xff08;用编程行话来说&#xff0c;表达式&#xff09;来产生另一个值&#xff08;因而整个结构成为一个表达式&#xff09;的东西。 PHP8的运算符有很多&#xff0c;按类型分有一元运算符、二元运算符、三元运算符。 一元运算符只对一…

ruby调试

如果下载 ruby-debug-ide gem install ruby-debug-ide vscode 下载 ruby扩展 1&#xff0c; ruby 2&#xff0c;修改launch.json

FBX SDK开发快速上手指南

一段时间以来&#xff0c;我一直想制作一个 FBX Exporter 将 FBX 文件转换为我自己的格式。 整个过程不是很顺利&#xff0c;主要是FBX的官方文档不是很清楚。 另外&#xff0c;由于 FBX 格式被许多应用程序使用&#xff0c;而不仅仅是游戏引擎&#xff0c;因此提供的示例代码没…

什么是注意力机制?注意力机制的计算规则

我们观察事物时&#xff0c;之所以能够快速判断一种事物(当然允许判断是错误的)&#xff0c;是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断&#xff0c;而并非是从头到尾的观察一遍事物后&#xff0c;才能有判断结果&#xff0c;正是基于这样的理论&a…

广州银行信用卡中心:强化数字引擎安全,实现业务稳步增长

广州银行信用卡中心是全国城商行中仅有的两家信用卡专营机构之一&#xff0c;拥有从金融产品研发至销售及后期风险控制、客户服务完整业务链条&#xff0c;曾获“2016年度最佳创新信用卡银行”。 数字引擎驱动业务增长 安全左移降低开发风险 近年来&#xff0c;广州银行信用卡…

java中使用Jsoup和Itext实现将html转换为PDF

1.在build.gradle中安装所需依赖&#xff1a; implementation group: com.itextpdf, name: itextpdf, version: 5.5.13 implementation group: com.itextpdf.tool, name: xmlworker, version: 5.5.13 implementation group: org.jsoup, name: jsoup, version: 1.15.32.创建工具…

贝业新兄弟:企业级应用在供应链物流领域的实践

一、老板的需求 先简单介绍一下我们公司&#xff0c;公司全称是贝业新兄弟&#xff0c;是一家供应链物流企业。现在我们服务的客户中有很多世界 500 强&#xff0c;比如科勒、惠氏、宜家等。我们公司的信息化分为两部分&#xff0c;一部分是核心业务系统OTWB&#xff0c;它是专…

智能卡通用安全检测指南 思度文库

范围 本标准规定了智能卡类产品进行安全性检测的一般性过程和方法。 本标准适用于智能卡安全性检测评估和认证。 规范性引用文件 下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件&#xff0c;仅注日期的版本适用于本文件。凡是不注日期的引用文件&#xff0c;…

互联网宠物医院系统开发:数字化时代下宠物医疗的革新之路

随着人们对宠物关爱意识的提高&#xff0c;宠物医疗服务的需求也日益增加。传统的宠物医院存在排队等待、预约难、信息不透明等问题&#xff0c;给宠物主人带来了诸多不便。而互联网宠物医院系统的开发&#xff0c;则可以带来许多便利和好处。下面将介绍互联网宠物医院系统开发…

docker常用命令

docker常用命令 1.镜像与容器的关系2. 基本命令3. 容器操作4. 镜像操作5. 文件传输6. docker 登录与退出 1.镜像与容器的关系 镜像&#xff1a; 相当于一个类不可修改内容 容器&#xff1a; 对镜像类的实例&#xff0c;可以在环境中更新库容器可以保存为一个新的镜像再根据保存…

java+springboot+mysql法律咨询网

项目介绍&#xff1a; 使用javassmmysql开发的法律咨询网&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 用户&#xff1a;主要是前台功能使用&#xff0c;包括注册、登录&#xff1b;查看法律领域&#xff1b;法律法规&a…

基于SpringBoot+Vue的在线考试系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

推荐一款老化测试软件 Monitor.Analog

1. 数据采集模块&#xff1a; 该模块负责与下位机设备通信&#xff0c;实时采集模拟量数据。支持多种通信协议&#xff0c;如Modbus、OPC等&#xff0c;以适应不同类型的设备。数据采集模块还需要具备异常数据处理功能&#xff0c;例如数据丢失、错误数据等。 2. 数据存储模块…