生成式对抗网络(GANs)综述

2023-11-17

GAN

GAN简介

生成式对抗网络(Generative adversarial networks,GANs)的核心思想源自于零和博弈,包括生成器和判别器两个部分。生成器接收随机变量并生成“假”样本,判别器则用于判断输入的样本是真实的还是合成的。两者通过相互对抗来获得彼此性能的提升。判别器所作的其实就是一个二分类任务,我们可以计算他的损失并进行反向传播求出梯度,从而进行参数更新。

GAN的优化目标可以写作:
min ⁡ G max ⁡ D V ( D , G ) = E x ∼ p d a t a [ log ⁡ D ( x ) ] + E z ∼ p z ( z ) [ l o g ( 1 − D ( G ( z ) ) ) ] \large {\min_G\max_DV(D,G)= \mathbb{E}_{x\sim p_{data}}[\log D(x)]+\mathbb{E}_{z\sim p_z(z)}[log(1-D(G(z)))]} GminDmaxV(D,G)=Expdata[logD(x)]+Ezpz(z)[log(1D(G(z)))]
其中 log ⁡ D ( x ) \log D(x) logD(x)代表了判别器鉴别真实样本的能力,而 D ( G ( z ) ) D(G(z)) D(G(z))则代表了生成器欺骗判别器的能力。在实际的训练中,生成器和判别器采取交替训练,即先训练D,然后训练G,不断往复。

WGAN

在上一部分我们给出了GAN的优化目标,这个目标的本质是在最小化生成样本与真实样本之间的JS距离。但是在实验中发现,GAN的训练非常的不稳定,经常会陷入坍缩模式。这是因为,在高维空间中,并不是每个点都可以表示一个样本,而是存在着大量不代表真实信息的无用空间。当两个分布没有重叠时,JS距离不能准确的提供两个分布之间的差异。这样的生成器,很难“捕捉”到低维空间中的真实数据分布。因此,WGAN(Wasserstein GAN)的作者提出了Wasserstein距离(推土机距离)的概念,其公式可以进行如下表示:
W ( P r , P g ) = inf ⁡ γ ∼ ∏ P r , P g E ( x , y )   γ [ ∥ x − y ∥ ] W(\mathbb P_r,\mathbb P_g)=\inf_{\gamma\sim\prod{\mathbb P_r,\mathbb P_g}}\mathbb E_{(x,y)~\gamma}[\|x-y\|] W(Pr,Pg)=γPr,PginfE(x,y) γ[xy]
这里 ∏ P r , P g \prod{\mathbb P_r,\mathbb P_g} Pr,Pg指的是真实分布 P r \mathbb P_r Pr和生成分布 P g \mathbb P_g Pg的联合分布所构成的集合, ( x , y ) (x,y) (x,y)是从 γ \gamma γ中取得的一个样本。枚举两者之间所有可能的联合分布,计算其中样本间的距离 ∥ x − y ∥ \|x-y\| xy,并取其期望。而Wasserstein距离就是两个分布样本距离期望的下界值。这个简单的改进,使得生成样本在任意位置下都能给生成器带来合适的梯度,从而对参数进行优化。

DCGAN

卷积神经网络近年来取得了耀眼的成绩,展现了其在图像处理领域独特的优势。很自然的会想到,如果将卷积神经网络引入GAN中,是否可以带来效果上的提升呢?DCGAN(Deep Convolutional GANs)在GAN的基础上优化了网络结构,用完全的卷积替代了全连接层,去掉池化层,并采用批标准化(Batch Normalization,BN)等技术,使得网络更容易训练。

用DCGAN生成图像

为了更方便准确的说明DCGAN的关键环节,这里用一个简化版的模型实例来说明。代码基于pytorch深度学习框架,数据集采用MNIST

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms
from torchvision.utils import save_image
import os 
#定义一些超参数
nc = 1    				#输入图像的通道数
nz = 100   				#输入噪声的维度
num_epochs = 200		#迭代次数
batch_size = 64			#批量大小
sample_dir = 'gan_samples'
# 结果的保存目录
if not os.path.exists(sample_dir):
    os.makedirs(sample_dir)
# 加载MNIST数据集
trans = transforms.Compose([
                transforms.ToTensor(),transforms.Normalize([0.5], [0.5])])
mnist = torchvision.datasets.MNIST(root=r'G:\VsCode\ml\mnist',
                                   train=True,
                                   transform=trans,
                                   download=False)
data_loader = torch.utils.data.DataLoader(dataset=mnist,
                                          batch_size=batch_size, 
                                          shuffle=True)

判别器&生成器

判别器使用LeakyReLU作为激活函数,最后经过Sigmoid输出,用于真假二分类
生成器使用ReLU作为激活函数,最后经过tanh将输出映射在 [ − 1 , 1 ] [-1,1] [1,1]之间

# 构建判别器
class Discriminator(nn.Module):
    def __init__(self, in_channel=1, num_classes=1):
        super(Discriminator, self).__init__()
        self.conv = nn.Sequential(
            # 28 -> 14
            nn.Conv2d(nc, 512, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(512),
            nn.LeakyReLU(0.2),
            # 14 -> 7
            nn.Conv2d(512, 256, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(256),
            nn.LeakyReLU(0.2),
            # 7 -> 4
            nn.Conv2d(256, 128, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(128),
            nn.LeakyReLU(0.2),
            nn.AvgPool2d(4),
        )
        self.fc = nn.Sequential(
            # reshape input, 128 -> 1
            nn.Linear(128, 1),
            nn.Sigmoid(),
        )
    
    def forward(self, x, label=None):
        y_ = self.conv(x)
        y_ = y_.view(y_.size(0), -1)
        y_ = self.fc(y_)
        return y_

# 构建生成器
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(nz, 4*4*512),
            nn.ReLU(),
        )
        self.conv = nn.Sequential(
            # input: 4 by 4, output: 7 by 7
            nn.ConvTranspose2d(512, 256, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            # input: 7 by 7, output: 14 by 14
            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            # input: 14 by 14, output: 28 by 28
            nn.ConvTranspose2d(128, 1, 4, stride=2, padding=1, bias=False),
            nn.Tanh(),
        )
        
    def forward(self, x, label=None):
        x = x.view(x.size(0), -1)
        y_ = self.fc(x)
        y_ = y_.view(y_.size(0), 512, 4, 4)
        y_ = self.conv(y_)
        return y_

训练模型

# 使用GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
D = Discriminator().to(device)
G = Generator().to(device)
# 损失函数及优化器
criterion = nn.BCELoss()
D_opt = torch.optim.Adam(D.parameters(), lr=0.001, betas=(0.5, 0.999))
G_opt = torch.optim.Adam(G.parameters(), lr=0.001, betas=(0.5, 0.999))

def denorm(x):
    out = (x + 1) / 2
    return out.clamp(0, 1)

def reset_grad():
    d_optimizer.zero_grad()
    g_optimizer.zero_grad()

for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(data_loader):
        images = images.to(device)
        real_labels = torch.ones(batch_size, 1).to(device)
        fake_labels = torch.zeros(batch_size, 1).to(device)
        #————————————————————训练判别器——————————————————————
        #鉴别真实样本
        outputs = D(images)
        d_loss_real = criterion(outputs, real_labels)
        real_score = outputs
        #鉴别生成样本
        z = torch.randn(batch_size, nz).to(device)
        fake_images = G(z)
        outputs = D(fake_images)
        d_loss_fake = criterion(outputs, fake_labels)
        fake_score = outputs        
     	#计算梯度及更新
        d_loss = d_loss_real + d_loss_fake      
        reset_grad()
        d_loss.backward()
        d_optimizer.step()

        #————————————————————训练生成器——————————————————————
        z = torch.randn(batch_size, nz).to(device)
        fake_images = G(z)
        outputs = D(fake_images)
        g_loss = criterion(outputs, real_labels)
        #计算梯度及更新
        reset_grad()
        g_loss.backward()
        g_optimizer.step()
        
        if (i+1) % 200 == 0:
            print('Epoch [{}/{}], Step [{}/{}], d_loss: {:.4f}, g_loss: {:.4f}, D(x): {:.2f}, D(G(z)): {:.2f}' 
                  .format(epoch, num_epochs, i+1, total_step, d_loss.item(), g_loss.item(), 
                          real_score.mean().item(), fake_score.mean().item()))
    # 保存生成图片
    fake_images = fake_images.reshape(fake_images.size(0), 1, 28, 28)
    save_image(denorm(fake_images), os.path.join(sample_dir, 'fake_images-{}.png'.format(epoch+1)))
# 保存模型
torch.save(G.state_dict(), 'G.ckpt')
torch.save(D.state_dict(), 'D.ckpt')

可视化结果

reconsPath = './gan_samples/fake_images-200.png'
Image = mpimg.imread(reconsPath)
plt.imshow(Image)
plt.axis('off')
plt.show()

cGAN

在之前介绍的几种模型中,我们注意到生成器的输入都是一个随机的噪声。可以认为这个高维噪声向量提供了一些关键信息,而生成器根据自己的理解将这些信息进行补充,最终生成需要的图像。生成器生成图片的过程是完全随机的。例如上述的MNIST数据集,我们不能控制它生成的是哪一个数字。那么,有没有方法可以对其做一定的限制约束,来让生成器生成我们想要的结果呢?cGAN(Conditional Generative Adversarial Nets)通过增一个额外的向量y对生成器进行约束。以MNIST分类为例,限制信息y可以取10维的向量,对于类别进行one-hot编码,并与噪声进行拼接一起输入生成器。同样的,判别器也将原来的输入和y进行拼接。作者通过各种实验证明了这个简单的改进确实可以起到对生成器的约束作用。

判别器&生成器

只需要在前向传播的过程中加入限制变量y,我们很容易就能得到cGAN的生成器和判别器模型

class Discriminator(nn.Module):
    ...
    def forward(self, x, label):
        label = label.unsqueeze(2).unsqueeze(3)
        label = label.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat(tensors=(x, label), dim=1)
        y_ = self.conv(x)
        ...
class Generator(nn.Module):
    ...
    def forward(self, x, label):
        x = x.unsqueeze(2).unsqueeze(3)
        label = label.unsqueeze(2).unsqueeze(3)
        x = torch.cat(tensors=(x, label), dim=1)
        y_ = self.fc(x)
        ...

Pix2Pix

在上面的cGAN例子中,我们的控制信息取的是想要图像的标签,如果这个控制信息更加的丰富,例如输入一整张图像,那么它能否完成一些更加高级的任务?Pix2Pix(Image-to-Image Translation with Conditional Adversarial Networks)将这一类问题归纳为图像到图像的翻译,其使用改进后的U-net作为生成器,并设计了新颖的Patch-D判别器结构来输出高清的图像。Patch-D是指,不管网络所使用的输入图像有多大,都将其切割成若干个固定大小的Patch,判别器只需对这些Patch的真假进行判断。因为L1损失已经可以衡量生成图像和真实图像的全局差异,所以作者认为判别器只需要用Patch-D这样更关注于局部差异的结构即可。同时Patch-D的结构使得网络的输入变小,减少了计算量并且增大了框架的扩展性。

CycleGAN

Pix2Pix虽然可以生成高清的图像,但其存在一个致命的缺点:需要相互配对的图片x与y。在现实生活中,这样成对的图片很难或者根本不可能搜集到,这就大大的限制了Pix2Pix的应用。对此,CycleGAN(Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks)提出了不需要配对的图像翻译方法。

CycleGAN其实就是一个X->Y的单向GAN上再加一个Y->X的单向GAN,构成一个“循环”。网络的结构和单次训练过程如下(图片来自于量子位):

除了经典的基础GAN损失之外,CycleGAN还引入了Consistency loss的概念。循环一致损失使得X->Y转变的过程中必须保留有X的部分特性。循环损失的公式如下:
L c y c ( G , F ) = E x ∼ p d a t a ( x ) [ ∥ F ( G ( x ) ) − x ∥ 1 ] + E y ∼ p d a t a ( y ) [ ∥ G ( F ( x ) ) − y ∥ 1 ] L_{cyc}(G,F)=\mathbb E_{x\sim p_{data}(x)}[\|F(G(x))-x\|_1]+\mathbb E_{y\sim p_{data}(y)}[\|G(F(x))-y\|_1] Lcyc(G,F)=Expdata(x)[F(G(x))x1]+Eypdata(y)[G(F(x))y1]
两个判别器的损失表示如下:
L G A N ( G , D Y , X , Y ) = E y ∼ p d a t a ( y ) [ l o g D Y ( y ) ] + E x ∼ p d a t a ( x ) [ l o g ( 1 − D Y ( G ( x ) ) ) ] \textit{L}_{GAN}(G,D_Y,X,Y)=\mathbb E_{y\sim p_{data}(y)}[logD_Y(y)]+\mathbb E_{x\sim p_{data}(x)}[log(1-D_Y(G(x)))] LGAN(G,DY,X,Y)=Eypdata(y)[logDY(y)]+Expdata(x)[log(1DY(G(x)))]

L G A N ( F , D X , Y , X ) = E x ∼ p d a t a ( x ) [ l o g D X ( x ) ] + E y ∼ p d a t a ( y ) [ l o g ( 1 − D X ( F ( y ) ) ) ] \textit{L}_{GAN}(F,D_X,Y,X)=\mathbb E_{x\sim p_{data}(x)}[logD_X(x)]+\mathbb E_{y\sim p_{data}(y)}[log(1-D_X(F(y)))] LGAN(F,DX,Y,X)=Expdata(x)[logDX(x)]+Eypdata(y)[log(1DX(F(y)))]

最后网络的优化目标可以表示为
min ⁡ G X → Y , G Y → X max ⁡ D X , D Y L ( G , F , D x , D y ) = L G A N ( G , D Y , X , Y ) + L G A N ( F , D X , Y , X ) + λ L c y c ( G , F ) \min _{G_{X\rightarrow Y},G_{Y\rightarrow X}}\max_{D_X,D_Y} L(G,F,D_x,D_y)=L_{GAN}(G,D_Y,X,Y)+L_{GAN}(F,D_X,Y,X)+\lambda L_{cyc}(G,F) GXY,GYXminDX,DYmaxL(G,F,Dx,Dy)=LGAN(G,DY,X,Y)+LGAN(F,DX,Y,X)+λLcyc(G,F)

Pix2Pix以及CycleGAN的官方复现入口:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix

StarGAN

Pix2Pix解决了有配对图像的翻译问题,CycleGAN解决了无配对图像的翻译问题,然而他们所作的图像到图像翻译,都是一对一。假设现在需要将人脸转换为喜怒哀乐四个表情,那么他们就需要进行4次不同的训练,这无疑会耗费巨大的计算资源。针对于这个问题,StarGAN(StarGAN: Unified Generative Adversarial Networks for Multi-Domain Image-to-Image Translation)借助cGAN的思想,在网络输入中加入一个域的控制信息。对于判别器,其不仅需要鉴别样本是否真实,还需要判断输入的图像来自哪个域。StarGAN的训练过程如下:

  1. 将原始图片 c c c和目标生成域 c c c进行拼接后丢入生成器得到生成图像 G ( x , c ) G(x,c) G(x,c)
  2. 将生成图像 G ( x , c ) G(x,c) G(x,c)和真实图像 y y y分别丢入判别器D,判别器除了需要判断输入图像的真伪之外,还需要判断它来自哪个域
  3. 将生成图像 G ( x , c ) G(x,c) G(x,c)和原始生成域 c ′ c' c丢入生成器生成重构图片(为了对生成器生成的图像做进一步的限制,与CycleGAN的重构损失类似)

了解了StarGAN的训练过程,我们很容易得到其损失函数各项的表达形式
首先是GAN的一般损失,这里作者采用了前文所述的WGAN的损失形式:
KaTeX parse error: Got function '\hat' with no arguments as subscript at position 110: … x}[(\|\nabla _\̲h̲a̲t̲ ̲xD_{src}(\hat x…
对于判别器,我们需要鼓励其将输入图像正确的分类到目标域c‘(原始生成域):
L s r c r = E x , c ′ [ − l o g D c l s ( c ′ ∣ x ) ] L_{src}^r=\mathbb E_{x,c'}[-logD_{cls}(c'|x)] Lsrcr=Ex,c[logDcls(cx)]
对于生成器,我们需要鼓励其成功欺骗判别器将图片分类到目标域c(目标生成域),此外,生成器还需要在以生成图像和原始生成域c’的输入下成功将图像还原回去,这两部分的损失表示如下:
L s r c f = R x , c [ − l o g D c l s ( c ∣ G ( x , c ) ) ] L_{src}^f=\mathbb R_{x,c}[-logD_{cls}(c|G(x,c))] Lsrcf=Rx,c[logDcls(cG(x,c))]

L r e c = E x , c , c ′ [ ∥ x − G ( G ( x , c ) , c ′ ) ∥ 1 ] L_{rec}=\mathbb E_{x,c,c'}[\|x-G(G(x,c),c')\|_1] Lrec=Ex,c,c[xG(G(x,c),c)1]

各部分损失乘上自己的权重加总后就构成了判别器和生成器的总损失:
L D = − L a d v + λ c l s L c l s r L_D=-L_{adv}+\lambda_{cls}L_{cls}^{r} LD=Ladv+λclsLclsr

L G = L a d v + λ c l s L c l a s f + λ r e c L r e c L_G=L_{adv}+\lambda_{cls}L_{clas}^f+\lambda_{rec}L_{rec} LG=Ladv+λclsLclasf+λrecLrec

此外,为了更具备通用性,作者还加入了mask vector来适应不同的数据集之间的训练。

总结

名称 创新点
DCGAN 首次将卷积神经网络引入GAN中
cGAN 通过拼接标签信息来控制生成器的输出
Pix2Pix 提出了一种图像到图像翻译的通用方法
CycleGAN 解决了Pix2Pix需要图像配对的问题
StarGAN 提出了一种一对多的图像到图像的翻译方法
InfoGAN 基于cGAN改进,提出一种无监督的生成方法,适用于不知道图像标签的情况
LSGAN 用最小二乘损失函数代替原始GAN的损失函数,缓解了训练不稳定、生成图像缺乏多样性的问题
ProGAN 在训练期间逐步添加新的高分辨率层,可以生成高分辨率的图像
SAGAN 将注意力机制引入GAN当中,简约高效利用了全局信息

本文列举了生成式对抗网络在发展过程中一些具有代表性的网络结构。GANs如今已广泛应用于图像生成、图像去噪、超分辨、文本到图像的翻译等各个领域,且在近几年的研究中涌现了很多优秀的论文。感兴趣的同学可以从下面的链接中pick自己想要了解的GAN~

  • THE-GAN-ZOO:汇总了各种GAN的论文及代码地址。
  • GAN Timeline:按照时间线对不同的GAN进行了排序。
  • Browse state-of-the-art:将ArXiv上的最新论文与GitHub代码相关联,并做了比较排序,涉及了深度学习的各个方面。

参考文献

  1. Goodfellow I, Pouget-Abadie J, Mirza M, et al. Generative adversarial nets[C]//Advances in neural information processing systems. 2014: 2672-2680.
  2. Arjovsky M, Chintala S, Bottou L. Wasserstein gan[J]. arXiv preprint arXiv:1701.07875, 2017.
  3. Radford A, Metz L, Chintala S. Unsupervised representation learning with deep convolutional generative adversarial networks[J]. arXiv preprint arXiv:1511.06434, 2015.
  4. Mirza M, Osindero S. Conditional generative adversarial nets[J]. arXiv preprint arXiv:1411.1784, 2014.
  5. Isola P, Zhu J Y, Zhou T, et al. Image-to-image translation with conditional adversarial networks[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 1125-1134.
  6. Zhu J Y, Park T, Isola P, et al. Unpaired image-to-image translation using cycle-consistent adversarial networks[C]//Proceedings of the IEEE international conference on computer vision. 2017: 2223-2232.
  7. Choi Y, Choi M, Kim M, et al. Stargan: Unified generative adversarial networks for multi-domain image-to-image translation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2018: 8789-8797.
  8. Mao X, Li Q, Xie H, et al. Least squares generative adversarial networks[C]//Proceedings of the IEEE international conference on computer vision. 2017: 2794-2802.
  9. Karras T, Aila T, Laine S, et al. Progressive growing of gans for improved quality, stability, and variation[J]. arXiv preprint arXiv:1710.10196, 2017.
  10. Chen X, Duan Y, Houthooft R, et al. Infogan: Interpretable representation learning by information maximizing generative adversarial nets[C]//Advances in neural information processing systems. 2016: 2172-2180.
  11. Zhang H, Goodfellow I, Metaxas D, et al. Self-attention generative adversarial networks[C]//International Conference on Machine Learning. 2019: 7354-7363.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生成式对抗网络(GANs)综述 的相关文章

  • 区块链+教育 解决教育行业所面临的问题

    众所周知 教育对于一个国家 一个民族来说是成就未来的重要方式 它的社会职能 就是传递生产经验和社会生活经验 促进新生一代的成长 但是教育行业也有被一些问题困扰着 怎样运用区块链技术解决这些问题 1 完善学籍档案管理 我们都知道 现在很多地方
  • 基于规则的优化

    MySQL会对用户编写的查询语句执行一些重写操作 比如 移除不必要的括号 常量传递 移除没用的条件 表达式计算 最好让那个索引列以单独的形式出现在搜索条件表达式中 HAVING子句和WHERE子句的合并 如果查询语句中没用出现诸如 SUM
  • java web项目答辩答辩题总结(书本网上语言答辩+自己的语言答辩)

    答辩每个人的总分为1 5分 每个人主要问3个问题 开发流程 系统架构 项目模块 功能 项目得失重定向与转发 九个隐式对象 get与post的区辨 jsp有静态包含 动态包含 两者的区辨 什么是MVC web系统架构 java web项目答辩
  • 虚拟机ubuntu18.04桥接模式详解

    背景 虚拟机ubuntu18 04桥接模式下 配置静态ip 配置静态ip vim etc network interfaces 具体配置如下 auto lo iface lo inet loopback auto ens33 iface e
  • 算法题Day6-第三大的数

    给定一个非空数组 返回此数组中第三大的数 如果不存在 则返回数组中最大的数 要求算法时间复杂度必须是O n 示例 1 输入 3 2 1 输出 1 解释 第三大的数是 1 示例 2 输入 1 2 输出 2 解释 第三大的数不存在 所以返回最大
  • SQL查询结果按照指定内容排序

    一般来说 我们在开发SQL脚本的时候 遇到需要排序的内容 用order by需要排序的字段就可以满足我们排序的需求 asc为升序 desc为降序 不指定关键字默认为升序 但是有时候 我们需要的排序不仅仅是升序和降序 asc与desc并不能满

随机推荐

  • Kibana 7.X 导出CSV报告

    背景 由于有时候需要基于日志做一些处理 由官网得知 ES7 3 0发布的新特性 从保存的搜索中导出CSV 我们的Kibana刚好是7 3 0 于是将自己的使用经验及解决的问题 分享给有需要的小伙伴 一 使用步骤 1 1 保存搜索 Disco
  • Spring Cloud 与 Dubbo 冲突吗——强强联合

    微服务开发选型 到底是基于 Dubbo 还是 Spring Cloud 相信不少开发的小伙伴都有拿这两个项目作过作比较的经历 本章节就带你走近这两个项目 二者究竟是竞争发展还是融合共赢 项目发展简介 我们还是先来看看 Dubbo 的发展历史
  • (递归)杨辉三角实现

    问题描述 杨辉三角形又称Pascal三角形 它的第i 1行是 a b i的展开式的系数 它的一个重要性质是 三角形中的每个数字等于它两肩上的数字相加 下面给出了杨辉三角形的前4行 1 1 1 1 2 1 1 3 3 1 思路 可以用二维数组
  • c++ string替换指定字符串

    string fnd dataset string rep labels string buf d data dataset ii jpg buf buf replace buf find fnd fnd length rep 去掉由于wi
  • ubuntu不息屏、隐藏其他软件图标 小技巧

    1 有时想安静的写写代码 但是这时候ubuntu老是自动进入休眠状态 这是你可以进入 设置 gt system setting gt power gt Brightness Lock 或者直接搜索Brightness Lock 将Turn
  • Latex学习笔记二——Overleaf在线练习

    锵锵 本文是基于Overleaf的Latex学习的第二部分 目录 1 结构化文档 2 添加图表 让论文更生动可读 2 1 Graphics 2 2 Floats 2 3 Tables 3 Bibliographies 1 结构化文档 这一部
  • SQl语句查询重复数据 只显示其中一条

    SQL查询重复数据 只显示其中一条 有重复数据主要有以下几种情况 1 存在两条完全相同的纪录 这是最简单的一种情况 用关键字distinct就可以去掉 example select distinct from table 表名 where
  • 电子专业 英语词汇大全(持续更新)

    文章目录 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 序号 词汇的领域 1 软件 软件开发 2 计算机 计算机网络 多媒体 3 单片机 电子 电子仪器 通信 A 序号 词汇 描述
  • GD32 和 ST32的区别

    TIM重载寄存器 复位值不一样 xxx xxx xxx xxxx
  • 服务器如何查询配置信息吗,如何查看linux服务器的配置信息

    如何查看linux服务器的配置信息 内容精选 换一换 本节介绍如何查看云服务器的mac地址 云服务器的mac地址不支持修改 登录Linux云服务器 执行以下命令 查看云服务器的mac地址 ifconfig查看MAC地址ifconfig登录L
  • 解决子盒子把父盒子撑破问题

    场景 div class demo 父盒子 div class box div 子盒子 div 当你设置子盒子的padding和border的时候就会把父盒子撑破 因为子盒子的宽度是100 而浏览器的默认盒模型为content box 即内
  • 遇到argument of type ‘Word2Vec‘ is not iterable不要慌。。。

    重要的事开头说 不要以为是返回值的问题或参数的问题 因为很有可能你学的那个是个老文档 现在已经改变函数了 报这个错我这里的原因是word2vec构造出来的模型不能遍历 原来代码 if word in model model就是用word2v
  • 设计模式【精简概述, 应用场景】(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 Gof23设计模式分为三类 创建型模式 负责组件的创建 结构型模式 负
  • C++实现裴波那契数列——自顶向下递归

    随便写一下 没有整理 注释比较多 大家按需自取 include
  • gitlab 12.0.3_GitLab 13.0强调安全性

    gitlab 12 0 3 GitLab已发布其devops平台的13 0版 该平台集成了用于软件开发 部署和项目管理的工具 GitLab 13 0添加了许多新的安全性和协作功能 GitLab结合了Git开源分布式版本控制系统 持续集成和持
  • C/C++2019秋招面试题集合01

    C C 2019秋招面试题集合01 8 19 腾讯 提前批 客户端开发 1 给定一个字符串数组 和一个子串 求字符串中是否存在子串 如果存在则返回首个匹配到的索引位置 否则 返回 1 不能调用库函数 例如 字符串数组 Integrity P
  • 【小练习】windows与linux进行socket文件传输

    在Windows与Linux使用socket通信基础上 添加文件传输功能 需要进行简单的交互 目录 程序效果 实现流程 样例代码 测试用例 参考资料 程序效果 Windows客户端可以从Linux服务器端索要文件 也可以发送文件至Linux
  • matlab算法集

    matlab 算法集 自定义函数 1 高斯消去法 注 高斯消元法可以用来找出一个可逆矩阵的逆矩阵 设A 为一个N N的矩阵 其逆矩阵可被两个分块矩阵表示出来 将一个N N单位矩阵 放在A 的右手边 形成一个N 2N的分块矩阵B A I 经过
  • HTML的作用与功能,css是什么?有什么作用?

    css是什么 有什么作用 下面本篇文章就来给大家介绍一下CSS样式表 让大家对CSS有一个简单的了解 希望对大家有所帮助 一 CSS定义与解释 CSS是Cascading Style Sheets 层叠样式表单 的简称 CSS就是一种叫做样
  • 生成式对抗网络(GANs)综述

    GAN GAN简介 生成式对抗网络 Generative adversarial networks GANs 的核心思想源自于零和博弈 包括生成器和判别器两个部分 生成器接收随机变量并生成 假 样本 判别器则用于判断输入的样本是真实的还是合