欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pytorch学习第三次打卡

程序员文章站 2022-07-13 22:05:27
...

Pytorch学习第三次打卡

目录

批量归一化

对输入的标准化(浅层模型)

处理后的任意一个特征在数据集中所有样本上的均值为0、标准差为1。
标准化处理输入数据使各个特征的分布相近

批量归一化(深度模型)

利用小批量上的均值和标准差,不断调整神经网络中间输出,从而使整个神经网络在各层的中间输出的数值更稳定。

  1. 对全连接层做批量归一化

    位置:全连接层中的仿射变换和**函数之间。

  2. 对卷积层做批量归⼀化

    位置:卷积计算之后、应⽤**函数之前。
    如果卷积计算输出多个通道,我们需要对这些通道的输出分别做批量归一化,且每个通道都拥有独立的拉伸和偏移参数。 计算:对单通道,batchsize=m,卷积计算输出=pxq 对该通道中m×p×q个元素同时做批量归一化,使用相同的均值和方差。

  3. 预测时的批量归⼀化
    训练:以batch为单位,对每个batch计算均值和方差。
    预测:用移动平均估算整个训练数据集的样本均值和方差。

代码实现

net = nn.Sequential(
            nn.Conv2d(1, 6, 5), # in_channels, out_channels, kernel_size
            nn.BatchNorm2d(6),
            nn.Sigmoid(),
            nn.MaxPool2d(2, 2), # kernel_size, stride
            nn.Conv2d(6, 16, 5),
            nn.BatchNorm2d(16),
            nn.Sigmoid(),
            nn.MaxPool2d(2, 2),
            d2l.FlattenLayer(),
            nn.Linear(16*4*4, 120),
            nn.BatchNorm1d(120),
            nn.Sigmoid(),
            nn.Linear(120, 84),
            nn.BatchNorm1d(84),
            nn.Sigmoid(),
            nn.Linear(84, 10)
        )

optimizer = torch.optim.Adam(net.parameters(), lr=lr)
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

残差网络

残差块(Residual Block)

恒等映射:
左边:f(x)=x
右边:f(x)-x=0 (易于捕捉恒等映射的细微波动)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iqONEJck-1582603377227)(F:\笔记\image\残差网络.png)]

ResNet模型

卷积(64,7x7,3)
批量一体化
最大池化(3x3,2)

残差块x4 (通过步幅为2的残差块在每个模块之间减小高和宽)

全局平均池化

全连接

代码:

def resnet_block(in_channels, out_channels, num_residuals, first_block=False):
    if first_block:
        assert in_channels == out_channels # 第一个模块的通道数同输入通道数一致
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(in_channels, out_channels, use_1x1conv=True, stride=2))
        else:
            blk.append(Residual(out_channels, out_channels))
    return nn.Sequential(*blk)

net.add_module("resnet_block1", resnet_block(64, 64, 2, first_block=True))
net.add_module("resnet_block2", resnet_block(64, 128, 2))
net.add_module("resnet_block3", resnet_block(128, 256, 2))
net.add_module("resnet_block4", resnet_block(256, 512, 2))

ResNet结构包括ResNet50和ResNet101


稠密连接网络

pytorch学习第三次打卡

主要构建模块

稠密块(dense block): 定义了输入和输出是如何连结的。

代码:

def conv_block(in_channels, out_channels):
    blk = nn.Sequential(nn.BatchNorm2d(in_channels), 
                        nn.ReLU(),
                        nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
    return blk

class DenseBlock(nn.Module):
    def __init__(self, num_convs, in_channels, out_channels):
        super(DenseBlock, self).__init__()
        net = []
        for i in range(num_convs):
            in_c = in_channels + i * out_channels
            net.append(conv_block(in_c, out_channels))
        self.net = nn.ModuleList(net)
        self.out_channels = in_channels + num_convs * out_channels # 计算输出通道数

    def forward(self, X):
        for blk in self.net:
            Y = blk(X)
            X = torch.cat((X, Y), dim=1)  # 在通道维上将输入和输出连结
        return X

过渡层(transition layer):用来控制通道数,使之不过大。代码:

1X1卷积层:来减小通道数
步幅为2的平均池化层:减半高和宽

def transition_block(in_channels, out_channels):
    blk = nn.Sequential(
            nn.BatchNorm2d(in_channels), 
            nn.ReLU(),
            nn.Conv2d(in_channels, out_channels, kernel_size=1),
            nn.AvgPool2d(kernel_size=2, stride=2))
    return blk

blk = transition_block(23, 10)
blk(Y).shape # torch.Size([4, 10, 4, 4])

目标检测基础

锚框

​ 目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边缘从而更准确地预测目标的真实边界框(ground-truth bounding box)。不同的模型使用的区域采样方法可能不同。这里我们介绍其中的一种方法:它以每个像素为中心生成多个大小和宽高比(aspect ratio)不同的边界框。这些边界框被称为锚框(anchor box)。我们将在后面基于锚框实践目标检测。

示例:

bbox_scale = torch.tensor((w, h, w, h), dtype=torch.float32)
ground_truth = torch.tensor([[0, 0.1, 0.08, 0.52, 0.92],
                            [1, 0.55, 0.2, 0.9, 0.88]])
anchors = torch.tensor([[0, 0.1, 0.2, 0.3], [0.15, 0.2, 0.4, 0.4],
                    [0.63, 0.05, 0.88, 0.98], [0.66, 0.45, 0.8, 0.8],
                    [0.57, 0.3, 0.92, 0.9]])

fig = d2l.plt.imshow(img)
show_bboxes(fig.axes, ground_truth[:, 1:] * bbox_scale, ['dog', 'cat'], 'k')
show_bboxes(fig.axes, anchors * bbox_scale, ['0', '1', '2', '3', '4']);
  • 以每个像素为中心,生成多个大小和宽高比不同的锚框。
  • 交并比是两个边界框相交面积与相并面积之比。
  • 在训练集中,为每个锚框标注两类标签:一是锚框所含目标的类别;二是真实边界框相对锚框的偏移量。
  • 预测时,可以使用非极大值抑制来移除相似的预测边界框,从而令结果简洁

风格迁移

pytorch学习第三次打卡

首先,我们初始化合成图像,例如将其初始化成内容图像。该合成图像是样式迁移过程中唯一需要更新的变量,即样式迁移所需迭代的模型参数。然后,我们选择一个预训练的卷积神经网络来抽取图像的特征,其中的模型参数在训练中无须更新。深度卷积神经网络凭借多个层逐级抽取图像的特征。我们可以选择其中某些层的输出作为内容特征或样式特征。这里选取的预训练的神经网络含有3个卷积层,其中第二层输出图像的内容特征,而第一层和第三层的输出被作为图像的样式特征。接下来,我们通过正向传播(实线箭头方向)计算样式迁移的损失函数,并通过反向传播(虚线箭头方向)迭代模型参数,即不断更新合成图像。样式迁移常用的损失函数由3部分组成:内容损失(content loss)使合成图像与内容图像在内容特征上接近,样式损失(style loss)令合成图像与样式图像在样式特征上接近,而总变差损失(total variation loss)则有助于减少合成图像中的噪点。最后,当模型训练结束时,我们输出样式迁移的模型参数,即得到最终的合成图像。

训练示例:

def train(X, contents_Y, styles_Y, device, lr, max_epochs, lr_decay_epoch):
    print("training on ", device)
    X, styles_Y_gram, optimizer = get_inits(X, device, lr, styles_Y)
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, lr_decay_epoch, gamma=0.1)
    for i in range(max_epochs):
        start = time.time()
        
        contents_Y_hat, styles_Y_hat = extract_features(
                X, content_layers, style_layers)
        contents_l, styles_l, tv_l, l = compute_loss(
                X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram)
        
        optimizer.zero_grad()
        l.backward(retain_graph = True)
        optimizer.step()
        scheduler.step()
        
        if i % 50 == 0 and i != 0:
            print('epoch %3d, content loss %.2f, style loss %.2f, '
                  'TV loss %.2f, %.2f sec'
                  % (i, sum(contents_l).item(), sum(styles_l).item(), tv_l.item(),
                     time.time() - start))
    return X.detach()
  • 样式迁移常用的损失函数由3部分组成:内容损失使合成图像与内容图像在内容特征上接近,样式损失令合成图像与样式图像在样式特征上接近,而总变差损失则有助于减少合成图像中的噪点。
  • 可以通过预训练的卷积神经网络来抽取图像的特征,并通过最小化损失函数来不断更新合成图像。
  • 用格拉姆矩阵表达样式层输出的样式。

GAN

GAN 有两个网络,一个是 generator,一个是 discriminator,从二人零和博弈中受启发,通过两个网络互相对抗来达到最好的生成效果。
  • **不依赖任何先验假设。**传统的许多方法会假设数据服从某一分布,然后使用极大似然去估计数据分布。

  • 生成real-like样本的方式非常简单。GAN生成real-like样本的方式通过生成器的前向传播。
    GAN的主要灵感来自于博弈论中的零和博弈的思想,应用到深度学习的神经网络中来就是,通过生成网络G和判别网络D不断博弈,以便使生成器G学习到数据的分布。生成器G和判别器D的主要功能是:

  • G是生成式的网络,接收一个随机的噪声,生成图像;

  • D是一个判别网络,判别一张图片是不是真实的。

优势:

  • 相比于其他的生成模型,GAN只利用了反向传播,不需要复杂的马尔科夫链。而且可以生成更清晰真实的样本。
  • GAN可以用到很多场景上,比如图片风格迁移、超分辨率、图像补全等等。

缺点:

  • 训练需要达到纳什平衡,现在还没有一个很好的达到纳什平衡的方法。
  • GAN不适合处理离散形式的数据。
  • GAN存在训练不稳定、梯度消失、模式崩溃等问题。原因:GAN是采用对抗的训练方式,G的损失来自于D,因此G训练的效果的好坏与否是由D决定的。如果某一次G生成的样本可能并不是真是的,但是D还是给出了正确的评价,或者说G生成的结果中的某些特征得到了D的认可,那么G就认为自己生成的结果是正确的,这样子自我欺骗下去就会导致最终生成的额结果会丢失一些信息,特征不全。

改进:

  • DCGAN:入了卷积并给了比较优雅的网络结构,DCGAN的生成器何判别器几乎是对称的。
  • WGAN:WGAN的生成器等价于求解最优传输映射,判别器等价于计算Wasserstein 距离,即最优的传输代价。
  • LSGAN:解决了传统GAN训练过程中的梯度饱和问题。通过惩罚原理判别器决策边界的生成样本来实现。

的样本可能并不是真是的,但是D还是给出了正确的评价,或者说G生成的结果中的某些特征得到了D的认可,那么G就认为自己生成的结果是正确的,这样子自我欺骗下去就会导致最终生成的额结果会丢失一些信息,特征不全。

改进:

  • DCGAN:入了卷积并给了比较优雅的网络结构,DCGAN的生成器何判别器几乎是对称的。
  • WGAN:WGAN的生成器等价于求解最优传输映射,判别器等价于计算Wasserstein 距离,即最优的传输代价。
  • LSGAN:解决了传统GAN训练过程中的梯度饱和问题。通过惩罚原理判别器决策边界的生成样本来实现。