本文将持续更新。

目录

  • 1. 基本GAN
    • 1.1 GAN(2014)
    • 1.2 CGAN(2015)
    • 1.3 DCGAN(2015)
    • 1.4 VAE-GAN(2016)
    • 1.5 ACGAN(2017)
    • 1.6 styleGAN(2018)
  • 2. GAN在图像生成领域的应用
    • 2.1 Pix2Pix(2017)
    • 2.2 cycleGAN(2017)
    • 2.3 starGAN(2018)
    • 2.4 SPADE(2019)

1. 基本GAN

1.1 GAN(2014)

原始GAN由生成器GGG和判别器DDD构成,生成器的目的就是将随机输入的高斯噪声映射成图像(“假图”),判别器则是判断输入图像是否来自生成器的概率,即判断输入图像是否为假图的概率。

GAN的训练是个动态的过程,是生成器GGG与判别器DDD两者之间的相互博弈过程。生成器G要生成假图骗过判别器DDD,而判别器DDD要分辨生成器GGG生成的假图。GAN的损失函数如下:


其中,GGG代表生成器, DDD代表判别器, xxx代表真实数据, pdatap_{data}pdata​代表真实数据概率密度分布,zzz代表了随机输入数据,该数据是随机高斯噪声。

从上式可以看出,从判别器DDD角度来看,判别器DDD希望能尽可能区分真实样本x和虚假样本G(z)G(z)G(z) ,因此D(x)D(x)D(x)必须尽可能大, D(G(z))D(G(z))D(G(z))尽可能小, 也就是V(D,G)V(D,G)V(D,G)整体尽可能大。从生成器GGG的角度来看,生成器GGG希望自己生成的虚假数据G(z)G(z)G(z)可以尽可能骗过判别器DDD,也就是希望 D(G(z))D(G(z))D(G(z))尽可能大,也就是V(D,G)V(D,G)V(D,G)整体尽可能小。GAN的两个模块在训练相互对抗,最后达到全局最优。图源。


训练过程的代码示例如下。

for epoch in range(opt.n_epochs):for i, (imgs, _) in enumerate(dataloader):# Adversarial ground truthsvalid = Variable(Tensor(imgs.size(0), 1).fill_(1.0), requires_grad=False)fake = Variable(Tensor(imgs.size(0), 1).fill_(0.0), requires_grad=False)# Configure inputreal_imgs = Variable(imgs.type(Tensor))# -----------------#  Train Generator# -----------------optimizer_G.zero_grad()# Sample noise as generator inputz = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim))))# Generate a batch of imagesgen_imgs = generator(z)# Loss measures generator's ability to fool the discriminatorg_loss = adversarial_loss(discriminator(gen_imgs), valid)g_loss.backward()optimizer_G.step()# ---------------------#  Train Discriminator# ---------------------optimizer_D.zero_grad()# Measure discriminator's ability to classify real from generated samplesreal_loss = adversarial_loss(discriminator(real_imgs), valid)fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake)d_loss = (real_loss + fake_loss) / 2d_loss.backward()optimizer_D.step()

1.2 CGAN(2015)

CGAN的主要贡献是在原始GAN的生成器与判别器中的输入中加入额外标签信息yyy。额外信息yyy可以是任何信息,主要是标签。因此CGAN的提出使得GAN可以利用图像与对应的标签进行训练,并在测试阶段利用给定标签生成特定图像。其损失函数如下:

在CGAN的论文中,网络架构使用的MLP(全连接网络)。在CGAN中的生成器,我们给定一个输入噪声pz(z)p_z(z)pz​(z)和额外信息yyy,之后将两者通过全连接层连接到一起,作为隐藏层输入。同样地,在判别器中输入图像xxx和 额外信息yyy也将连接到一起作为隐藏层输入。

CGAN和GAN的区别如下:

for epoch in range(opt.n_epochs):for i, (imgs, labels) in enumerate(dataloader):# define labels and gen_labbels:labels = Variable(labels.type(LongTensor))gen_labels = Variable(LongTensor(np.random.randint(0, opt.n_classes, batch_size)))# -----------------#  Train Generator# -----------------# input + genlabelsgen_imgs = generator(z, gen_labels)validity = discriminator(gen_imgs, gen_labels)# ---------------------#  Train Discriminator# ---------------------# input + labels or genlabelsvalidity_real = discriminator(real_imgs, labels)validity_fake = discriminator(gen_imgs.detach(), gen_labels)

1.3 DCGAN(2015)

DCGAN主要是在网络架构上改进了原始GAN,DCGAN的生成器与判别器都利用CNN架构替换了原始GAN的全连接网络,主要改进之处有如下几个方面:

  1. DCGAN的生成器和判别器都舍弃了CNN的池化层,判别器保留CNN的整体架构,生成器则是将卷积层替换成了反卷积层(或称转置卷积层)。
  2. 在判别器和生成器中在每一层之后都是用了BN层,有助于处理初始化不良导致的训练问题,加速模型训练,提升了训练的稳定性。
  3. 利用1*1卷积层替换到所有的全连接层。
  4. 在生成器中除输出层使用Sigmoid激活函数,其余层全部使用ReLu激活函数。
  5. 在判别器所有层都使用LeakyReLU激活函数,防止梯度稀疏。

1.4 VAE-GAN(2016)

变分自编码器VAE是由一个编码器和一个解码器组成的结构,编码器可以将数据映射到一个低维的空间分布,而解码器可以将这个分布还原回原始数据,因此解码器是很像GAN中的生成器。VAE的目的也和GAN相似,都是希望构建一个从隐变量zzz生成目标数据xxx的模型。

如果在VAE后面拼接上一个判别器D,这样的话,前两个模块就是VAE,后两个模块就是GAN:


从VAE的角度,VAE解码产生的图片往往都比较模糊,GAN中的判别器来判别图片是不是真实的,可以来帮助VAE提高真实性。从GAN的角度,原本生成器输入都是随机的,训练起来比较难,而VAE可以提供生成器输入的大概空间分布,会变得准确高效一些。因此VAE和GAN相辅相成,都可达到更优秀的效果。

1.5 ACGAN(2017)

为了提供更多的辅助信息并允许半监督学习,可以向判别器添加额外的辅助分类器,以便在原始任务以及附加任务上优化模型。这种方法的体系结构如下图所示,其中C是辅助分类器。 添加辅助分类器允许我们使用预先训练的模型(例如,在ImageNet上训练的图像分类器)。


ACGAN和CGAN的代码的区别如下,在辨别器D中增加adv层和aux层,用来计算Label:

class Discriminator(nn.Module):def __init__(self):self.conv_blocks = ...self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid())self.aux_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, opt.n_classes), nn.Softmax())def forward(self, img):out = self.conv_blocks(img)out = out.view(out.shape[0], -1)validity = self.adv_layer(out)label = self.aux_layer(out)return validity, labelfor epoch in range(opt.n_epochs):for i, (imgs, labels) in enumerate(dataloader):# -----------------#  Train Generator# -----------------# output the pred_label and add auxiliary_lossvalidity, pred_label = discriminator(gen_imgs)g_loss = 0.5 * (adversarial_loss(validity, valid) + auxiliary_loss(pred_label, gen_labels))# ---------------------#  Train Discriminator# ---------------------# Loss for real imagesreal_pred, real_aux = discriminator(real_imgs)d_real_loss = (adversarial_loss(real_pred, valid) + auxiliary_loss(real_aux, labels)) / 2# Loss for fake imagesfake_pred, fake_aux = discriminator(gen_imgs.detach())d_fake_loss = (adversarial_loss(fake_pred, fake) + auxiliary_loss(fake_aux, gen_labels)) / 2# Total discriminator lossd_loss = (d_real_loss + d_fake_loss) / 2# Calculate discriminator accuracypred = np.concatenate([real_aux.data.cpu().numpy(), fake_aux.data.cpu().numpy()], axis=0)gt = np.concatenate([labels.data.cpu().numpy(), gen_labels.data.cpu().numpy()], axis=0)d_acc = np.mean(np.argmax(pred, axis=1) == gt)

1.6 styleGAN(2018)

StyleGAN也可以算作图像生成领域的应用,但是由于它主要改变网络结构,因此我们将它归类于第一章。

StyleGAN提出了一个新的生成器结构如下:


不同于以往的GAN论文把zzz输入给生成器的输入层的做法,StyleGAN在生成器各层都注入噪音,且摒弃了输入层, 转而添加了一个从ZZZ到WWW的非线性映射网络,将输入zzz用了8层全连接层做了个非线性变换,得到www。

图中,ZZZ和WWW的维度都是512维, AAA是一个仿射变换,BBB是每个通道的高斯噪声的系数,而AdaIN则是:

图中, ys,i和yb,iy_{s,i}和y_{b,i}ys,i​和yb,i​则是www经过AAA变换之后得到的style:y=(ys,yb)y=(y_s,y_b)y=(ys​,yb​),(ys,i,yb,i)(y_{s,i},y_{b,i})(ys,i​,yb,i​)对的个数与每一层特征图的通道数相同,对应每一层归一化所需的scale和shift。

为进一步促使style局部化图像转换的控制效果,作者采用了mixing regularization。利用生成器中8层卷积的非线性变换,提前计算两个图像的变换结果w1,w2w_1,w_2w1​,w2​ ,然后在生成过程中随机取w1w_1w1​ 或者w2w_2w2​ 的值进行操作。结果如下,可以看到横轴和纵轴上的原始图像不同程度地影响了生成的图像。

2. GAN在图像生成领域的应用

2.1 Pix2Pix(2017)

Pix2Pix可以称之为用CGAN做image translation的鼻祖,先看一下他的效果:


训练大致过程如下:


我们将CGAN的结构放在下面以方便对比。可以看到,Pix2Pix采用CGAN的结构,将图片xxx作为CGAN的条件(相当于是一个”鞋“的标签),输入到GGG和DDD中。GGG的输入是x,z{x,z}x,z(其中,xxx是需要转换的图片,zzz是随机噪声),输出是生成的图片G(x,z)G(x,z)G(x,z)。DDD则需要分辨出x,G(x,z){x,G(x,z)}x,G(x,z)和x,y{x,y}x,y。


Pix2Pix使用的生成器GGG用到的是Unet结构,输入的轮廓图xxx编码再解码成真是图片,判别器D用到的是作者自己提出来的条件判别器PatchGAN。损失函数如下:

  1. CGAN损失函数:
  2. 与ground truch的loss:
  3. 最终损失:

但是,Pix2Pix的一个限制在于网络学习的是xxx到yyy之间的一对一映射。这样的一个明显的缺点就是对数据集的限制:需要大量对应的图片,例如同一个地方的黑夜和白天的图片。

代码:

for epoch in range(opt.epoch, opt.n_epochs):for i, batch in enumerate(dataloader):# Model inputs, A is labelreal_A = Variable(batch["B"].type(Tensor))real_B = Variable(batch["A"].type(Tensor))# Adversarial ground truthsvalid = Variable(Tensor(np.ones((real_A.size(0), *patch))), requires_grad=False)fake = Variable(Tensor(np.zeros((real_A.size(0), *patch))), requires_grad=False)# ------------------#  Train Generators# ------------------optimizer_G.zero_grad()# GAN lossfake_B = generator(real_A)pred_fake = discriminator(fake_B, real_A)loss_GAN = criterion_GAN(pred_fake, valid)# Pixel-wise lossloss_pixel = criterion_pixelwise(fake_B, real_B)# Total lossloss_G = loss_GAN + lambda_pixel * loss_pixelloss_G.backward()optimizer_G.step()# ---------------------#  Train Discriminator# ---------------------# same process as CGAN

2.2 cycleGAN(2017)

相比于Pix2Pix需要两个域中有相同数据的训练样本。CycleGAN的创新点在于能够在源域和目标域之间,无须建立训练数据间一对一的映射,就可实现这种迁移,效果如下:


CycleGAN由两个判别器(DxD_xDx​和DyD_yDy​)和两个生成器(GGG和FFF)组成,生成器GGG和FFF分别是XXX到YYY和YYY到XXX的映射,两个判别器DxD_xDx​和DyD_yDy​对转换后的图片进行判别。双判别器的目的是为了建立一对一的映射,避免所有的XXX都被映射到同一个YYY,例如所有男人的图像都映射到刘亦菲的图像上。起到同样作用的是cycle-consistency loss,用数据集中其他的图来检验生成器,防止GGG和FFF过拟合。


CycleGAN的训练过程如下,两张图分别表示从XXX域到YYY域的图像生成和从YYY域到XXX域的图像生成。其中Input_A表示输入的真实图像,Generated_B表示由表示由Input_A转换得到的图像,Cyclic_A表示由Input_A转换一圈得到的图像。反之亦然。图源。



损失函数包含:

  1. 对抗损失函数

    以及对偶的
  2. Cycle Consistency 损失
  3. 总损失

代码如下:

# Losses
criterion_GAN = torch.nn.MSELoss()
criterion_cycle = torch.nn.L1Loss()
criterion_identity = torch.nn.L1Loss()for epoch in range(opt.epoch, opt.n_epochs):for i, batch in enumerate(dataloader):# Set model inputreal_A = Variable(batch["A"].type(Tensor))real_B = Variable(batch["B"].type(Tensor))# Adversarial ground truthsvalid = Variable(Tensor(np.ones((real_A.size(0), *D_A.output_shape))), requires_grad=False)fake = Variable(Tensor(np.zeros((real_A.size(0), *D_A.output_shape))), requires_grad=False)# ------------------#  Train Generators# ------------------G_AB.train()G_BA.train()optimizer_G.zero_grad()# Identity lossloss_id_A = criterion_identity(G_BA(real_A), real_A)loss_id_B = criterion_identity(G_AB(real_B), real_B)loss_identity = (loss_id_A + loss_id_B) / 2# GAN lossfake_B = G_AB(real_A)loss_GAN_AB = criterion_GAN(D_B(fake_B), valid)fake_A = G_BA(real_B)loss_GAN_BA = criterion_GAN(D_A(fake_A), valid)loss_GAN = (loss_GAN_AB + loss_GAN_BA) / 2# Cycle lossrecov_A = G_BA(fake_B)loss_cycle_A = criterion_cycle(recov_A, real_A)recov_B = G_AB(fake_A)loss_cycle_B = criterion_cycle(recov_B, real_B)loss_cycle = (loss_cycle_A + loss_cycle_B) / 2# Total lossloss_G = loss_GAN + opt.lambda_cyc * loss_cycle + opt.lambda_id * loss_identityloss_G.backward()optimizer_G.step()# -----------------------#  Train Discriminator A# -----------------------optimizer_D_A.zero_grad()# Real lossloss_real = criterion_GAN(D_A(real_A), valid)# Fake loss (on batch of previously generated samples)fake_A_ = fake_A_buffer.push_and_pop(fake_A)loss_fake = criterion_GAN(D_A(fake_A_.detach()), fake)# Total lossloss_D_A = (loss_real + loss_fake) / 2loss_D_A.backward()optimizer_D_A.step()# -----------------------#  Train Discriminator B# -----------------------optimizer_D_B.zero_grad()# Real lossloss_real = criterion_GAN(D_B(real_B), valid)# Fake loss (on batch of previously generated samples)fake_B_ = fake_B_buffer.push_and_pop(fake_B)loss_fake = criterion_GAN(D_B(fake_B_.detach()), fake)# Total lossloss_D_B = (loss_real + loss_fake) / 2loss_D_B.backward()optimizer_D_B.step()loss_D = (loss_D_A + loss_D_B) / 2

2.3 starGAN(2018)

Pix2Pix模型解决了paired数据的图像翻译问题;CycleGAN解决了Unpaired数据下的图像翻译问题,但它们都是单领域的转换,而StarGAN则应用于多领域,即在同一种模型下做多个图像翻译任务,效果如下:


如下图所示,当多领域转换时,对于每一个领域转换,如果都需要重新训练一个模型去解决,这样的行为就太低效了,而StarGAN将多领域转换用统一框架实现。


由于StarGAN时在多数据集下训练,而数据集之间有可能出现虽然类别不相交,但内容相交的情况。比如CelebA数据集合RaFD数据集,前者拥有肤色,年龄的类别。而后者拥有表情的类别。但前者的图像很多也是有表情的,这就导致前一类的图像在后一类的标记是不可知的。

为了解决这个问题,在模型输入中加入了Mask,即如果来源于数据集B,那么将数据集A中的标记全部设为0,示意图如下:

starGAN使用的损失函数如下:

  1. 对抗损失
  2. D分类损失,使用真实图像在原始领域进行
  3. G分类损失,使用生成图像在目标领域进行
  4. 重建函数,与CycleGAN类似
  5. 总损失

    代码如下。表示多领域的方法主要在于加入了sampled_c。
for epoch in range(opt.epoch, opt.n_epochs):for i, (imgs, labels) in enumerate(dataloader):# Sample labels as generator inputssampled_c = Variable(Tensor(np.random.randint(0, 2, (imgs.size(0), c_dim))))# Generate fake batch of imagesfake_imgs = generator(imgs, sampled_c)# ---------------------#  Train Discriminator# ---------------------optimizer_D.zero_grad()# Real imagesreal_validity, pred_cls = discriminator(imgs)# Fake imagesfake_validity, _ = discriminator(fake_imgs.detach())# Gradient penaltygradient_penalty = compute_gradient_penalty(discriminator, imgs.data, fake_imgs.data)# Adversarial lossloss_D_adv = -torch.mean(real_validity) + torch.mean(fake_validity) + lambda_gp * gradient_penalty# Classification lossloss_D_cls = criterion_cls(pred_cls, labels)# Total lossloss_D = loss_D_adv + lambda_cls * loss_D_clsloss_D.backward()optimizer_D.step()optimizer_G.zero_grad()# Every n_critic times update generatorif i % opt.n_critic == 0:# -----------------#  Train Generator# -----------------# Translate and reconstruct imagegen_imgs = generator(imgs, sampled_c)recov_imgs = generator(gen_imgs, labels)# Discriminator evaluates translated imagefake_validity, pred_cls = discriminator(gen_imgs)# Adversarial lossloss_G_adv = -torch.mean(fake_validity)# Classification lossloss_G_cls = criterion_cls(pred_cls, sampled_c)# Reconstruction lossloss_G_rec = criterion_cycle(recov_imgs, imgs)# Total lossloss_G = loss_G_adv + lambda_cls * loss_G_cls + lambda_rec * loss_G_recloss_G.backward()optimizer_G.step()

2.4 SPADE(2019)

SPADE又名GauGAN,可以根据用户画的简单图像得到合成的实际图像,在合成时用户还可以选择合成图像的风格,得到非常多样的合成结果,如下图所示。

SPADE通过语义分割图生成原始图像,作者发现将语义分割图直接作为生成网络的输入进行计算时,这些生成网络中常用的传统BN层容易丢失输入语义图像中的信息, 因此提出了新的归一化层Spatially-Adaptive Normalization(SAN)来解决这个问题。

SAN是在BN的基础上做了修改,修改内容就在于γ和β计算的不同,如下图所示。在BN中γγγ和βββ的计算是通过网络训练得到的,而SAN中γ和β是通过语义图像计算得到的。


SAN的计算过程如下。在BN中,γγγ和βββ是向量一维的,其中每个值对应输入特征图的每个通道。而在SAN中,γγγ和βββ是三维矩阵,除了通道维度外,还有宽和高维度,因此下式中γγγ和βββ下标包含c,y,xc,y,xc,y,x三个符号,这也是spatially-adaptive的含义,翻译过来就是在空间上是有差异的,或者叫自适应的。而BN的γγγ和βββ的下标只有ccc,也就是通道,这种不区分空间维度的计算方式就比较容易丢失输入图像的信息。


公式中的均值μμμ和标准差σσσ的计算如下,这部分和BN中的计算一样。

在网络结构方面,下图是SPADE算法中生成器的网络结构示意图,生成器采用堆叠多个SPADE ResBlk实现(右图),其中每个SPADE ResBlk的结构如左图所示,SAN层中的γγγ和βββ参数通过输入的语义图像计算得到。

关于SPADE算法是如何实现多样化输出的。下图是SPADE算法的整体示意图,生成器的输入是一个向量,这个向量可以是随机值,这样生成的图像也是随机的;同样,这个向量也可以通过一个编码网络和一张风格图像计算得到,编码网络将输入图像编码成向量,这个向量就包含输入图像的风格,这样就能得到多样化风格输出的效果了。

参考文献:

  1. An Introduction to Image Synthesis with Generative Adversarial Nets
  2. DCGAN论文详解
  3. GAN在图像生成应用综述(论文解读)
  4. 完整code
  5. [GAN笔记] pix2pix
  6. 生成对抗网络系列(4)——pix2pix
  7. 深度学习《VAE-GAN》
  8. Understanding and Implementing CycleGAN in TensorFlow
  9. CycleGAN原理以及代码全解析
  10. CycleGAN算法原理
  11. StarGAN-多领域图像翻译
  12. 论文阅读-人脸生成_StyleGAN
  13. SPADE(GauGAN)算法笔记

GAN综述及其在图像生成领域的应用(含原理、代码详解)相关推荐

  1. [Pytorch系列-69]:生成对抗网络GAN - 图像生成开源项目pytorch-CycleGAN-and-pix2pix - test.py代码详解

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:[Pytorch系列-66]:生成对抗网络GAN - 图像生成开源项目pytorch-CycleG ...

  2. 涵盖18+ SOTA GAN实现,这个图像生成领域的PyTorch库火了

    视学算法报道 转载自:机器之心 作者:杜伟.陈萍 GAN 自从被提出后,便迅速受到广泛关注.我们可以将 GAN 分为两类,一类是无条件下的生成:另一类是基于条件信息的生成.近日,来自韩国浦项科技大学的 ...

  3. 在图像生成领域里,GAN这一大家族是如何生根发芽的

    作者:思源 生成对抗网络这一 ML 新成员目前已经枝繁叶茂了,截止今年 5 月份,目前 GAN 至少有 300+的论文与变体.而本文尝试借助机器之心 SOTA 项目梳理生成对抗网络的架构与损失函数发展 ...

  4. NIPS 2018 | 中科院自动化所两篇入选论文:高清真实图像生成领域及GAN研究在人脸识别领域的进展...

    [论文一]自动化所在高清真实图像生成领域获得新突破 IntroVAE: Introspective Variational Autoencoders for Photographic Image Sy ...

  5. GAN|在图像生成领域里,GAN这一大家族是如何生根发芽的

    作者:思源 本文经机器之心(微信公众号:almosthuman2014)授权转载,禁止二次转载 图像生成领域的 SOTA 排名涉及非常多的数据集与度量方法,我们并不能直观展示不同 GAN 的发展路线. ...

  6. [Python图像处理] 三十三.图像各种特效处理及原理万字详解(毛玻璃、浮雕、素描、怀旧、流年、滤镜等)...

    此文转载自:https://blog.csdn.net/Eastmount/article/details/111568397#commentBox 该系列文章是讲解Python OpenCV图像处理 ...

  7. php推荐码生成,最新最全PHP生成制作验证码代码详解(推荐),验证码详解_PHP教程...

    最新最全PHP生成制作验证码代码详解(推荐),验证码详解 1.0 首先先看代码 好,现在结合以上代码,来分析分析以上用到的几个函数: ① imagecreatetruecolor(); imagecr ...

  8. 关于图像显著性(MR)matlab代码详解

    本代码内容是关于Saliency Detection via Graph-Based Manifold Ranking的算法详解,想要运行此代码还需要一系列的文件,单纯此代码无法演示结果的. 可以在网 ...

  9. Gavin老师Transformer直播课感悟 - Rasa对话机器人项目实战之教育领域Education Bot项目Policies Data详解(七十二)

    本文继续围绕工业级业务对话平台和框架Rasa,对Rasa对话机器人项目实战之教育领域Education Bot项目Policies Data,end-to-end的训练方式及使用时需要注意的事项,ch ...

最新文章

  1. 聊一聊:下班后的消息,要不要回?
  2. 基础-计算机及操作系统和应用程序的概念
  3. html5 文字转换烟花,HTML5交互式烟花(点击并保持)
  4. postgresql参数化查询_一个能融会贯通PostgreSQL监控的人,大概率是高手
  5. window 2003 linux,一步步从Windows 2003 DNS 移植到Linux下
  6. 常见通信协议HTTP、TCP、UDP的简单介绍
  7. 每日一题(35)—— heap与stack的差别
  8. Codeforces Round #196 (Div. 1 + Div. 2)
  9. 网卡多队列:RPS、RFS、RSS、Flow Director(DPDK支持)
  10. (best!)JAVA中文字符编码问题详解
  11. java excel类库_Java 操作 Excel 的类库 jExcelApi
  12. 在Unity3D中使用Protobuf3
  13. 关于苹果Mac上设置固件密码的方法?
  14. dedecms(织梦)采集规则规则宝典
  15. android方法不混淆,Android 混淆时不混淆注解方法
  16. 国内信号处理类EI期刊
  17. vue 脚手架跨域问题解决
  18. Android 权限适配 从此第三方系统新增的权限无法判断状态的问题得到解决! 如MIUI自启动, 后台弹出界面权限等
  19. 网页压缩算法deflate揭秘
  20. CV学习:李宏毅2021机器学习(2)

热门文章

  1. 以太坊学习路线——(一)私有链搭建与基本操作
  2. 传奇外网架设全套图文教程-Hero引擎
  3. 51单片机之外部中断拙见
  4. 为有机会进大厂,程序员必须掌握的核心算法有哪些?
  5. 手把手教你将chatGpt接到微信
  6. 细致教程:从安装到实战手把手教你玩懂Nacos
  7. 2.5元组tuple
  8. 单片机——PWM调光工作原理
  9. 2020年 ICLR 国际会议最终接受论文(poster-paper)列表(一)
  10. 2020-12-4今日纪实