《动手学深度学习 Pytorch版》 7.4 含并行连接的网络(GoogLeNet)

python 复制代码
import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l

7.4.1 Inception块

GoogLNet 中的基本卷积块叫做 Inception 块(大概率得名于盗梦空间),由 4 条并行路径组成。

前 3 条路径使用窗口大小为 1 × 1 1\times 1 1×1、 3 × 3 3\times 3 3×3 和 5 × 5 5\times 5 5×5 的卷积层;

中间 2 条路径在输入上执行 1 × 1 1\times 1 1×1 卷积,以减少通道数,从而降低模型的复杂度;

第 4 条路径使用 3 × 3 3\times 3 3×3 的最大汇聚层;

最后使用 1 × 1 1\times 1 1×1 卷积层改变通道数。

回避了用哪种卷积核的问题,小孩子才做选择,Google全部都要。

python 复制代码
class Inception(nn.Module):
    # c1--c4是每条路径的输出通道数
    def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):
        super(Inception, self).__init__(**kwargs)
        # 线路1,单1x1卷积层
        self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
        # 线路2,1x1卷积层后接3x3卷积层
        self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 线路3,1x1卷积层后接5x5卷积层
        self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 线路4,3x3最大汇聚层后接1x1卷积层
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_channels, 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)

7.4.2 GoogLeNet 模型

GoogLetNet 一共使用 9 个 Inception 块和全局平均汇聚层来生成其估计值。

  • Inception块之间的最大汇聚层可降低维度

  • 第一个模块类似于AlexNet和LeNet,Inception块的组合从VGG继承

  • 全局平均汇聚层避免了在最后使用全连接层。

python 复制代码
b1 = nn.Sequential(  # 第一个模块使用64个通道、3*3的卷积层。
    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(  # 第二个模块使用一个64个通道、1*1卷积层的卷积层和一个卷积层使用192的通道、3*3的卷积层。这对应于Inception块中的第二条路径。
    nn.Conv2d(64, 64, kernel_size=1),
    nn.ReLU(),
    nn.Conv2d(64, 192, kernel_size=3, padding=1),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b3 = nn.Sequential(  # 串联两个Inception模块
    Inception(192, 64, (96, 128), (16, 32), 32),  # 输出通道数为 64+128+32+32=256  各路径输出比例为 64:128:32:32=2:4:1:1
    Inception(256, 128, (128, 192), (32, 96), 64),  # 输出通道数为 128+192+96+64=480  各路径输出比例为 128:196:96:64=4:6:3:2
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b4 = nn.Sequential(  # 串联五个Inception模块 
    Inception(480, 192, (96, 208), (16, 48), 64),  # 输出通道数为 192+208+48+64=512
    Inception(512, 160, (112, 224), (24, 64), 64),  # 输出通道数为 160+224+64+64=512
    Inception(512, 128, (128, 256), (24, 64), 64),  # 输出通道数为 128+256+64+64=512
    Inception(512, 112, (144, 288), (32, 64), 64),  # 输出通道数为 112+288+64+64=528
    Inception(528, 256, (160, 320), (32, 128), 128),  # 输出通道数为 256+320+128+128=832
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b5 = nn.Sequential(  # 串联两个Inception模块
    Inception(832, 256, (160, 320), (32, 128), 128),  # 输出通道数为 256+320+128+128=832
    Inception(832, 384, (192, 384), (48, 128), 128),  # 输出通道数为 384+384+128+128=1024
    nn.AdaptiveAvgPool2d((1,1)),
    nn.Flatten())

net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10))
python 复制代码
X = torch.rand(size=(1, 1, 96, 96))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape:\t', X.shape)
Sequential output shape:	 torch.Size([1, 64, 24, 24])
Sequential output shape:	 torch.Size([1, 192, 12, 12])
Sequential output shape:	 torch.Size([1, 480, 6, 6])
Sequential output shape:	 torch.Size([1, 832, 3, 3])
Sequential output shape:	 torch.Size([1, 1024])
Linear output shape:	 torch.Size([1, 10])

7.4.3 训练模型

python 复制代码
lr, num_epochs, batch_size = 0.1, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)  # 输入宽高降为96以减小计算量
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())  # 大约需要二十分钟,慎跑
loss 0.297, train acc 0.887, test acc 0.861
542.8 examples/sec on cuda:0

练习

(1)GoogLeNet 有一些后续版本如下,尝试实现并运行它们,并观察实验结果。

a. 添加批量规范层

b. 对 Inception 进行调整

c. 使用标签平滑进行模型正则化

d. 加入残差连接

(2)使用 GoogLeNet 的最小图像大小是多少?

最小图像大小应该是 3 × 3 3\times 3 3×3

因为 5 × 5 5\times 5 5×5卷积核、2填充、1步幅至少需要 3 × 3 3\times 3 3×3大小的图像才能使输出大于零


(3)将AlexNet、VGG 和 NiN 的模型参数大小与 GoogLeNet 进行比较。后两个网络架构是如何显著减少模型参数大小的?

用 1 × 1 1\times 1 1×1 的卷积数取代全连接层让参数变小。

相关推荐
编码浪子15 分钟前
Transformer的编码机制
人工智能·深度学习·transformer
IE0628 分钟前
深度学习系列76:流式tts的一个简单实现
人工智能·深度学习
m0_743106465 小时前
【论文笔记】MV-DUSt3R+:两秒重建一个3D场景
论文阅读·深度学习·计算机视觉·3d·几何学
m0_743106465 小时前
【论文笔记】TranSplat:深度refine的camera-required可泛化稀疏方法
论文阅读·深度学习·计算机视觉·3d·几何学
AI浩8 小时前
【面试总结】FFN(前馈神经网络)在Transformer模型中先升维再降维的原因
人工智能·深度学习·计算机视觉·transformer
幽兰的天空9 小时前
介绍 HTTP 请求如何实现跨域
网络·网络协议·http
lisenustc9 小时前
HTTP post请求工具类
网络·网络协议·http
心平气和️9 小时前
HTTP 配置与应用(不同网段)
网络·网络协议·计算机网络·http
心平气和️9 小时前
HTTP 配置与应用(局域网)
网络·计算机网络·http·智能路由器
Mbblovey10 小时前
Picsart美易照片编辑器和视频编辑器
网络·windows·软件构建·需求分析·软件需求