深度学习笔记

二、现代卷积神经网络

1.  深度卷积神经网络--AlexNet

 (1). AlexNet介绍  

        AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个全连接输出层。AlexNet使用ReLU作为其激活函数,因为ReLU激活函数的计算更简单,它不需要如sigmoid激活函数那般复杂的求幂运算。

  

左图为LeNet, 右图为AlexNet 

         用Sequential块将需要的层连接在一起。

net = nn.Sequential(
    # 这里使用一个11*11的更大窗口来捕捉对象。
    nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
    nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    # 使用三个连续的卷积层和较小的卷积窗口。
    nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),
    nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),
    nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nn.Flatten(),
    # 使用dropout层来减轻过拟合
    nn.Linear(6400, 4096), nn.ReLU(),
    nn.Dropout(p=0.5),
    nn.Linear(4096, 4096), nn.ReLU(),
    nn.Dropout(p=0.5),
    # 最后是输出层。
    nn.Linear(4096, 10))

        训练模型。

# 使用Fathion_mnist来训练,将尺寸改为224*224
batch_size = 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)

lr, num_epochs = 0.01, 10
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

        输出:

2.  使用块网络--VGG 

(1).VGG介绍

        VGG网络可以分为两部分:第一部分主要由卷积层和池化层组成,第二部分由全连接层组成。

         原始VGG网络有5个卷积块,其中前两个块各有一个卷积层,后三个块各包含两个卷积层。该网络使用8个卷积层和3个全连接层,因此它通常被称为VGG-11。

        VGG块。

# VGG块
# 卷积层的数量num_convs、输入通道的数量in_channels 和输出通道的数量out_channels
def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for i in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels,kernel_size=3, padding=1))
        layers.append(nn.ReLU())     
        in_channels = out_channels
    # 池化层
    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
    return nn.Sequential(*layers)

        VGG网络模型: 

def vgg(conv_arch):
    conv_blks = []
    in_channels = 1
    # 卷积层部分
    for (num_convs, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *conv_blks, nn.Flatten(),
        # 全连接层部分
        nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 10))

总结:

        1. VGG-11使用可复用的卷积块构造网络。

        2. 块的使用导致网络定义的非常简洁。 

3.  网络中的网络--NiN

 (1).NiN介绍

        NiN块以一个普通卷积层开始,后面是两个1×1的卷积层。这两个1×1卷积层充当带有ReLU激活函数的全连接层。第一层的卷积窗口形状通常由用户设置。 随后的卷积窗口形状固定为1×1。

         NiN块代码定义:

def nin_block(in_channels, out_channels, kernel_size, strides, padding):
    return nn.Sequential(
        # 自定义卷积层
        nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding), 
        nn.ReLU(),
        # 两个1*1卷积层
        nn.Conv2d(out_channels, out_channels, kernel_size=1),nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1),nn.ReLU())

        NiN使用全剧平均池化层来代替全连接层,不容易过拟合,更少的参数个数。

        NiN模型代码:

net = nn.Sequential(
    nin_block(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(3, stride=2),
    nin_block(96, 256, kernel_size=5, strides=1, padding=2),
    nn.MaxPool2d(3, stride=2),
    nin_block(256, 384, kernel_size=3, strides=1, padding=1),
    nn.MaxPool2d(3, stride=2),
    nn.Dropout(0.5),
    # 标签类别数是10
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    # 将四维的输出转成二维的输出,其形状为(批量大小,10)
    nn.Flatten())

总结:

        1.  NiN使用由一个卷积层和多个1×1卷积层组成的块。

        2. NiN去除了容易造成过拟合的全连接层,将它们替换为全局平均汇聚层。该汇聚层通道数

            量为所需的输出数量。

        3. 移除全连接层可减少过拟合,同时显著减少NiN的参数

4. GoogLeNet

(1). GoogLeNet介绍

        在GoogLeNet中,基本的卷积块被称为Inception块, 四条并行路径组成。这四条路径都使用合适的填充来使输入与输出的高和宽一致,最后我们将每条线路的输出在通道维度上连结,并构成Inception块的输出。

   Inception块 

 GoogLeNet模型 一共使用9个Inception块和全局平均池化层。

 

 总结:

        1. Inception块相当于一个有4条路径的子网络。它通过不同窗口形状的卷积层和最大汇聚层来并行抽取信息,并使用1×1卷积层减少每像素级别上的通道维数从而降低模型复杂度。

5. 批量规范化

(1). 介绍

        批量规范化是在卷积层或全连接层之后、相应的激活函数之前应用的, 可以加速神经网络的收敛。

使用torch.nn.BatchNorm2d()

如下代码是使用了BatchNorm的LeNet

net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5), nn.BatchNorm2d(6), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5), nn.BatchNorm2d(16), nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),
    nn.Linear(256, 120), nn.BatchNorm1d(120), nn.Sigmoid(),
    nn.Linear(120, 84), nn.BatchNorm1d(84), nn.Sigmoid(),
    nn.Linear(84, 10))

6. 残差网络--ResNet

(1). 介绍

        残差块里首先有2个有相同输出通道数的3×3卷积层。每个卷积层后接一个批量规范化层和ReLU激活函数。 然后我们将输入直接加在最后的ReLU激活函数前。如果想改变通道数,可以引入1×1卷积层来将输入变换成需要的形状后再做相加运算。

                                                                残差块

(2). ResNet-18模型

        每个模块有4个卷积层(不包括1×1卷积层)。 加上第一个7×7卷积层和最后一个全局平均池化层,共有18层。

7. 稠密连接网络--DenseNet

(1). 介绍

        DenseNet输出是连接(用图中的[,]表示)而不是如ResNet的简单相加。 

         ResNet(左)与 DenseNet(右)在跨层连接上的主要区别:使用相加和使用连结

DenseNet所有当前层与之前的所有层想拼接。

 

        稠密网络主要由2部分构成:稠密块过渡层。 前者定义如何连接输入和输出,而后者则控制通道数量。

         稠密块由多个卷积块组成,每个卷积块使用相同数量的输出通道。 然而,在前向传播中,我们将每个卷积块的输入和输出在通道维上连结。

class DenseBlock(nn.Module):
    def __init__(self, num_convs, input_channels, num_channels):
        super(DenseBlock, self).__init__()
        layer = []
        for i in range(num_convs):
            layer.append(conv_block(
                num_channels * i + input_channels, num_channels))
        self.net = nn.Sequential(*layer)

    def forward(self, X):
        for blk in self.net:
            Y = blk(X)
            # 连接通道维度上每个块的输入和输出
            X = torch.cat((X, Y), dim=1)
        return X

        过渡层可以用来控制模型复杂度。 它通过1×1卷积层来减小通道数,并使用步幅为2的平均汇聚层减半高和宽,从而进一步降低模型复杂度。

def transition_block(input_channels, num_channels):
    return nn.Sequential(
        nn.BatchNorm2d(input_channels), nn.ReLU(),
        nn.Conv2d(input_channels, num_channels, kernel_size=1),
        nn.AvgPool2d(kernel_size=2, stride=2))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值