DIDL笔记(pytorch版)(八)

文章目录

前言

LeNet、AlexNet和VGG都是不断的加深模型的层数,看网络结构可以看出后者有前者的影子,并且都是一系列卷积+最后全连接的操作。

NiN却是网络串联网络,并且NiN最后的分类方法也很不同。

NiN

之前的网络都是卷积提取特征之后带全连接做分类。NiN提供另一个思路,卷积层和全连接层交替。因为全连接层的输入输出要是二维,卷积通常是四维,为了方便全连接层使用1 × \times × 1 卷积代替。原理之前解释过。

贡献:

  • 空间信息有效的传递到后层。
  • 最后分类采用输出通道数等于标签类别数的NiN块,再加上全局平均池化来分类。可以显著减少模型参数尺寸,缓解过拟合。
import torch
from torch import nn
import torch.nn.functional as F
import d2l as d2l

def nin_block(in_channels, out_channels, kernel_size, stride, padding):
    blk = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding),
                        nn.ReLU(),
                        nn.Conv2d(out_channels, out_channels, kernel_size=1),
                        nn.ReLU(),
                        nn.Conv2d(out_channels, out_channels, kernel_size=1),
                        nn.ReLU())
    return blk

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

GoogLeNet

改进很大,除了吸收了NiN的串联网路的思想,设置的基础模块也更加复杂。它认为之前加深层数会导致参数太多、计算复杂难以应用、出现梯度消失的问题。要解决这个问题不得不引入稀疏性并且把全连接变为稀疏连接。

引入稀疏性可以从下面两个方面着手:

  1. 卷积的稀疏性
    传统的神经网络是全连接的,后面每一层的单元都与它之前层的输入单元之间存在权重连接,而在卷积运算中,卷积核的尺寸是远小于输入图像的大小,一个神经元只受少数输入单元的影响,可以理解成有些输入单元的权重连接为0,不同于密集的全连接,称之为稀疏性。
  2. 特征维度的稀疏
    使用多分支多个尺寸卷积核对图像进行卷积,每个尺寸卷积核(分支)提取出对应的高相关性特征,而每个分支得到的结果在通道维度上进行拼接,这就相当于把各个分支提取出的高相关性特征在通道维度上进行了聚合,这样一来作者就真正实现了使用稠密运算来近似稀疏连接的目的

Inception模块
在这里插入图片描述
在这里插入图片描述

参考:https://blog.csdn.net/weixin_43624538/article/details/84863685
https://blog.csdn.net/weixin_30888027/article/details/97739699
https://www.cnblogs.com/leebxo/p/10315490.html

import torch
from torch import nn
import torch.nn.functional as F
import d2l as d2l

class Inception(nn.Module):
    # c1 - c4为每条线路里的层的输出通道数
    def __init__(self, in_c, c1, c2, c3, c4):
        super(Inception, self).__init__()
        # 线路1,单1 x 1卷积层
        self.p1_1 = nn.Conv2d(in_c, c1, kernel_size=1)
        # 线路2,1 x 1卷积层后接3 x 3卷积层
        self.p2_1 = nn.Conv2d(in_c, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 线路3,1 x 1卷积层后接5 x 5卷积层
        self.p3_1 = nn.Conv2d(in_c, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 线路4,3 x 3最大池化层后接1 x 1卷积层
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_c, c4, kernel_size=1)

    def forward(self, x):
        p1 = F.relu(self.p1_1(x))
        p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
        p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
        p4 = F.relu(self.p4_2(self.p4_1(x)))
        return torch.cat((p1, p2, p3, p4), dim=1)  # 在通道维上连结输出
        
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
                   
b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),
                   nn.Conv2d(64, 192, kernel_size=3, padding=1),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
                   
b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),
                   Inception(256, 128, (128, 192), (32, 96), 64),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
                   
b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),
                   Inception(512, 160, (112, 224), (24, 64), 64),
                   Inception(512, 128, (128, 256), (24, 64), 64),
                   Inception(512, 112, (144, 288), (32, 64), 64),
                   Inception(528, 256, (160, 320), (32, 128), 128),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
                   
b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
                   Inception(832, 384, (192, 384), (48, 128), 128),
                   d2l.GlobalAvgPool2d())

net = nn.Sequential(b1, b2, b3, b4, b5, 
                    d2l.FlattenLayer(), nn.Linear(1024, 10))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值