包含并行连结的网络(GoogLeNet)

在2014年的ImageNet图像识别挑战赛中,一个名叫GoogLeNet的网络结构大放异彩。它虽然在名字上向LeNet致敬,但在网络结构上已经很难看到LeNet的影子。GoogLeNet吸收了NiN中网络串联网络的思想,并在此基础上做了很大改进。在随后的几年里,研究人员对GoogLeNet进行了数次改进。

Inception块

GoogLeNet中的基础卷积块叫作Inception块,得名于同名电影《盗梦空间》(Inception)。

Inception块里有4条并行的线路。

  • 前3条线路使用窗口大小分别是1×11\times 11×1、3×33\times 33×3和5×55\times 55×5的卷积层来抽取不同空间尺寸下的信息,其中中间2个线路会对输入先做1×11\times 11×1卷积来减少输入通道数,以降低模型复杂度。
  • 第四条线路则使用3×33\times 33×3最大池化层,后接1×11\times 11×1卷积层来改变通道数。
  • 4条线路都使用了合适的填充来使输入与输出的高和宽一致。
  • 最后将每条线路的输出在通道维上连结,并输入接下来的层中去。

Inception块中可以自定义的超参数是每个层的输出通道数,以此来控制模型复杂度

import time
import torch
from torch import nn, optim
import torch.nn.functional as Fdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')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)  # 在通道维上连结输出

GoogLeNet模型

GoogLeNet跟VGG一样,在主体卷积部分中使用5个模块(block)每个模块之间使用步幅为2的3×33\times 33×3最大池化层来减小输出高宽

这里我们假设输入为96*96的图片,来推算每一个模块的输入输出尺寸

(1) 第一模块使用一个64通道的7×77\times 77×7卷积层。

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))

input=1∗96∗96卷积1:size=⌊(96+2+3∗2−7)/2⌋=48∣∣output1=64∗48∗48池化2:size=⌊(48+2+1∗2−3)/2⌋=24∣∣output2=64∗24∗24output=64∗24∗24input = 1*96*96 \\ 卷积1:size= \lfloor \left(96+2+3*2-7\right)/2 \rfloor=48||output1 = 64*48*48\\ 池化2:size= \lfloor \left(48+2+1*2-3\right)/2 \rfloor=24||output2=64*24*24\\ output = 64*24*24 input=1∗96∗96卷积1:size=⌊(96+2+3∗2−7)/2⌋=48∣∣output1=64∗48∗48池化2:size=⌊(48+2+1∗2−3)/2⌋=24∣∣output2=64∗24∗24output=64∗24∗24
(2) 第二模块使用2个卷积层:首先是64通道的1×11\times 11×1卷积层,然后是输出通道为192的3×33\times 33×3卷积层。它对应着Inception块中的第二条线路。

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))

input=64∗24∗24卷积1:size=⌊(24+1+0∗2−1)/1⌋=24∣∣output1=64∗24∗24卷积2:size=⌊(24+1+1∗2−3)/1⌋=24∣∣output1=192∗24∗24池化3:size=⌊(24+2+1∗2−3)/2⌋=12∣∣output2=192∗12∗12output=192∗12∗12input = 64*24*24 \\ 卷积1:size= \lfloor \left(24+1+0*2-1\right)/1 \rfloor=24||output1 = 64*24*24\\ 卷积2:size= \lfloor \left(24+1+1*2-3\right)/1 \rfloor=24||output1 = 192*24*24\\ 池化3:size= \lfloor \left(24+2+1*2-3\right)/2 \rfloor=12||output2=192*12*12\\ output = 192*12*12 input=64∗24∗24卷积1:size=⌊(24+1+0∗2−1)/1⌋=24∣∣output1=64∗24∗24卷积2:size=⌊(24+1+1∗2−3)/1⌋=24∣∣output1=192∗24∗24池化3:size=⌊(24+2+1∗2−3)/2⌋=12∣∣output2=192∗12∗12output=192∗12∗12
(3) 第三模块串联2个完整的Inception块。

  • 第一个Inception块的输出通道数为64+128+32+32=25664+128+32+32=25664+128+32+32=256,其中4条线路的输出通道数比例为64:128:32:32=2:4:1:164:128:32:32=2:4:1:164:128:32:32=2:4:1:1。其中第二、第三条线路先分别将输入通道数减小至96/192=1/296/192=1/296/192=1/2和16/192=1/1216/192=1/1216/192=1/12后,再接上第二层卷积层。
  • 第二个Inception块输出通道数增至128+192+96+64=480128+192+96+64=480128+192+96+64=480,每条线路的输出通道数之比为128:192:96:64=4:6:3:2128:192:96:64 = 4:6:3:2128:192:96:64=4:6:3:2。其中第二、第三条线路先分别将输入通道数减小至128/256=1/2128/256=1/2128/256=1/2和32/256=1/832/256=1/832/256=1/8。
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))

(4) 第四模块更加复杂。

  • 它串联了5个Inception块,其输出通道数分别是192+208+48+64=512192+208+48+64=512192+208+48+64=512、160+224+64+64=512160+224+64+64=512160+224+64+64=512、128+256+64+64=512128+256+64+64=512128+256+64+64=512、112+288+64+64=528112+288+64+64=528112+288+64+64=528和256+320+128+128=832256+320+128+128=832256+320+128+128=832。
  • 这些线路的通道数分配和第三模块中的类似,首先含3×33\times 33×3卷积层的第二条线路输出最多通道,其次是仅含1×11\times 11×1卷积层的第一条线路,之后是含5×55\times 55×5卷积层的第三条线路和含3×33\times 33×3最大池化层的第四条线路。其中第二、第三条线路都会先按比例减小通道数。这些比例在各个Inception块中都略有不同。
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))

(5) 第五模块有输出通道数为256+320+128+128=832256+320+128+128=832256+320+128+128=832和384+384+128+128=1024384+384+128+128=1024384+384+128+128=1024的两个Inception块。

  • 其中每条线路的通道数的分配思路和第三、第四模块中的一致,只是在具体数值上有所不同。
  • 需要注意的是,第五模块的后面紧跟输出层,该模块同NiN一样使用全局平均池化层来将每个通道的高和宽变成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))

GoogLeNet模型的计算复杂,而且不如VGG那样便于修改通道数。本节里我们将输入的高和宽从224降到96来简化计算。下面演示各个模块之间的输出的形状变化。

net = nn.Sequential(b1, b2, b3, b4, b5, d2l.FlattenLayer(), nn.Linear(1024, 10))
X = torch.rand(1, 1, 96, 96)
for blk in net.children(): X = blk(X)print('output shape: ', X.shape)

输出:

output shape:  torch.Size([1, 64, 24, 24])
output shape:  torch.Size([1, 192, 12, 12])
output shape:  torch.Size([1, 480, 6, 6])
output shape:  torch.Size([1, 832, 3, 3])
output shape:  torch.Size([1, 1024, 1, 1])
output shape:  torch.Size([1, 1024])
output shape:  torch.Size([1, 10])

获取数据训练模型

def load_data_fashion_mnist(batch_size, resize=None, root='~/Datasets/FashionMNIST'):"""Download the fashion mnist dataset and then load into memory."""trans = []if resize:trans.append(torchvision.transforms.Resize(size=resize))trans.append(torchvision.transforms.ToTensor())transform = torchvision.transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)if sys.platform.startswith('win'):num_workers = 0  # 0表示不用额外的进程来加速读取数据else:num_workers = 4train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)return train_iter, test_iterdef train(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):net = net.to(device)print("training on ", device)loss = torch.nn.CrossEntropyLoss()for epoch in range(num_epochs):train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()for X, y in train_iter:X = X.to(device)y = y.to(device)y_hat = net(X)l = loss(y_hat, y)optimizer.zero_grad()l.backward()optimizer.step()train_l_sum += l.cpu().item()train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()n += y.shape[0]batch_count += 1test_acc = evaluate_accuracy(test_iter, net)print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'% (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))
batch_size = 128
# 如出现“out of memory”的报错信息,可减小batch_size或resize
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=96)lr, num_epochs = 0.001, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
train(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

(pytorch-深度学习)包含并行连结的网络(GoogLeNet)相关推荐

  1. 含并行连结的网络 GoogLeNet / Inception V3 动手学深度学习v2 pytorch

    1. 含并行连结的网络 GoogLeNet 第一个神经网络可以做到超过100层. Inception 块的名字,取自盗梦空间,就是不断深入到梦境中,不断深入. Inception 使得参数减少,计算量 ...

  2. Pytorch 含并行连结的网络 GoogLeNet

    Pytorch 含并行连结的网络 GoogLeNet 0. 环境介绍 环境使用 Kaggle 里免费建立的 Notebook 教程使用李沐老师的 动手学深度学习 网站和 视频讲解 小技巧:当遇到函数看 ...

  3. PyTorch 深度学习实战 | 基于生成式对抗网络生成动漫人物

    生成式对抗网络(Generative Adversarial Network, GAN)是近些年计算机视觉领域非常常见的一类方法,其强大的从已有数据集中生成新数据的能力令人惊叹,甚至连人眼都无法进行分 ...

  4. 李沐动手学深度学习笔记---含并行连结的网络 GoogLeNet / Inception V3

    Inception块:  Inception块由四条并行路径组成.前三条路径使用窗口大小为1 × 1.3 × 3和5 × 5的卷积层, 从不同空间大小中提取信息.中间的两条路径在输入上执行1 × 1卷 ...

  5. 动手深度学习笔记(四十)7.4. 含并行连结的网络(GoogLeNet)

    动手深度学习笔记(四十)7.4. 含并行连结的网络(GoogLeNet) 7.4. 含并行连结的网络(GoogLeNet) 7.4.1. Inception块 7.4.2. GoogLeNet模型 7 ...

  6. [pytorch、学习] - 5.9 含并行连结的网络(GoogLeNet)

    参考 5.9 含并行连结的网络(GoogLeNet) 在2014年的ImageNet图像识别挑战赛中,一个名叫GoogLeNet的网络结构大放异彩.它虽然在名字上向LeNet致敬,但在网络结构上已经很 ...

  7. pytorch深度学习实战——预训练网络

    来源:<Pytorch深度学习实战>,2.1,一个识别图像主体的预训练网络 from torchvision import models from torchvision import t ...

  8. pytorch | 深度学习分割网络U-net的pytorch模型实现

    原文:https://blog.csdn.net/u014722627/article/details/60883185 pytorch | 深度学习分割网络U-net的pytorch模型实现 这个是 ...

  9. 手把手教你搭建pytorch深度学习网络

    总有人在后台问我,如今 TensorFlow 和 PyTorch 两个深度学习框架,哪个更流行? 就这么说吧,今年面试的实习生,问到常用的深度学习框架时,他们清一色的选择了「PyTorch」. 这并不 ...

最新文章

  1. SQL-Hive中的Select From解析
  2. eclipse打包项目为aar_Eclipse中使用AAR
  3. 通过制定编码规范的过程来说明《学会放弃、妥协也是个大进步,也是相当的提高工作效率》...
  4. Linux 命令之 curl -- 文件传输工具/下载工具/网络接口调试
  5. 小程序 省市区县三级联动选择器(caseCade)
  6. day22:更换yum源及源码包安装
  7. js动态生产table、Div、select
  8. C++STL::两种方式实现STL容器的reference语义
  9. 使用C++实现二叉搜索树的数据结构
  10. Java Web基础回顾 —HTTP
  11. UVa 674 Coin Change(完全背包)
  12. 计算机基础相关知识面试题
  13. 虚拟机VMware安装PhoenixOS(凤凰OS)进入命令行黑屏页面无法进入图形界面
  14. u-boot 之配置分析 (2)
  15. 【Scratch 3.0游戏】—— 乒乓弹球游戏
  16. 前端基础----html初识、常用标签
  17. ubuntu激活pycharm
  18. LTE:PHICH物理层处理过程及资源映射
  19. c语言设计程序之数组,软考程序员考点C语言程序设计之数组
  20. 人的天性是贪嗔痴和戒定慧的等量叠加态

热门文章

  1. java中哪些可以私有化_《Java基础学习笔记》JAVA修饰符之私有化(Private)
  2. 【论文党福利】如何提取图像中的数据
  3. CSS串联和后代选择器
  4. 计算机考研的调查和改进建议
  5. java php html,java和html的区别是什么
  6. java 调用 mahout_java – 运行Mahout本地获取MahoutDriver的ClassNotFoundException
  7. 灰度调节_网关实现灰度发布
  8. caged系统pdf_建筑行业单词中英文对照教材.pdf
  9. python指定进程断网_python通过scapy模块进行arp断网攻击
  10. 【LeetCode笔记】剑指 Offer 62. 圆圈中最后剩下的数字(Java、约瑟夫环、链表)