Inception(盗梦空间)及代码实现
⽂章⽬录
妻夫木聪演的电影前⾔
这段时间观看b站up主 刘⼆⼤⼈ 的关于深度学习的讲解,让我获益匪浅。让我了解到什么是盗梦空间(Inception),如何将结构嵌⼊到模型中,下⾯是视频地址:
以下是本篇⽂章正⽂内容,可供参考,如有不⾜,恳请⼤家指正,共同学习。
⼀、Inception(盗梦空间)是什么?
当你构建卷积层时,你要决定卷积核的⼤⼩,如何判别哪种卷积核效果更好?是1x1合适,还是3x3合适,还是5x5合适?要不要添加pooling层?
由于这些参数都是超参数,需要进⾏⼿动设置,在实验中逐个尝试的话⽆疑是⼀件费时费⼒的⼯程,这时通过Inception(盗梦空间)模块可很好的解决相应问题。
⼆、使⽤步骤
1.空间结构
结构如图所⽰(⽰例):
王自健 郭德纲图中5x5卷积和3x3卷积,都对图像进⾏了相应的填充,因此输⼊图像尺度和输出图像尺度不变。
2.结构模型
代码如下(⽰例):
代码中的数据集我使⽤的是常⽤的MNIST数据集,单个图像样本⼤⼩为(1, 28,28)。
盗梦空间代码⽰意图
盗梦空间最后结局 as nn
from torch.utils.data import DataLoader # 我们要加载数据集的
from torchvision import transforms # 数据的原始处理
from torchvision import datasets # pytorch⼗分贴⼼的为我们直接准备了这个数据集
functional as F # 激活函数
import torch.optim as optim
#盗梦空间Inception
#图像输⼊⽹络中同时经过4种不同的卷积进⾏处理,这⾥保证分别处理后的,w,h都相同,以便后⽅拼接#[b, c, w, h],这⾥b=64直接套⽤了上⽂提到的mnist数据集中batch_size的⼤⼩,可⾃由设置。
class Module):
def__init__(self,in_channels):
super(InceptionA,self).__init__()
#[64,1,28,28]-[64,16,28,28] 通过卷积核为⼀的卷积,图像尺⼨不变
self.branch1x1 = nn.Conv2d(in_channels,16,kernel_size=1)
l是多大码self.branch5x5_1 = nn.Conv2d(in_channels,16, kernel_size=1)
# [64,16,28,28]-[64,24,28,28] 通过卷积核为5的卷积,因为w,h分别填充了2,所以图像尺⼨不变 self.branch5x5_2 = nn.Conv2d(16,24, kernel_size=5,padding=2)
self.branch3x3_1 = nn.Conv2d(in_channels,16, kernel_size=1)
# [64,16,28,28]-[64,24,28,28] 通过卷积核为3的卷积,因为填充了1,所以图像尺⼨不变
self.branch3x3_2 = nn.Conv2d(16,24, kernel_size=3, padding=1)
# [64,24,28,28]-[64,24,28,28] 通过卷积核为3的卷积,因为填充了1,所以图像尺⼨不变
self.branch3x3_3 = nn.Conv2d(24,24, kernel_size=3, padding=1)
#[64,1,28,28]-[64,24,28,28]
低俗喜剧 陈静self.branch_pool = nn.Conv2d(in_channels,24, kernel_size=1)
def forward(self,x):
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_1(x)
branch5x5 = self.branch5x5_2(branch5x5)
branch3x3 = self.branch3x3_1(x)
branch3x3 = self.branch3x3_2(branch3x3)
branch3x3 = self.branch3x3_3(branch3x3)
#平均池化尺⼨不变
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs =[branch1x1, branch5x5, branch3x3, branch_pool]
#[b,c,h,w] dim=1是维度⽅向拼接,这⾥返回的维度是上述⼏个维度相加(16+24+24+24=88)
return torch.cat(outputs, dim=1)
通过盗梦空间的图⽚,只更改其的通道数量,⽽不更改图像的尺⼨⼤⼩,因此在维度⽅向进⾏拼接,上图拼接后的通道数量为24+16+24+24=88,对应了下⾯第⼆层卷积层的输⼊维度。
将盗梦空间结构嵌⼊到我们的⽹络中
# 接下来我们看⼀下模型是怎么做的
class Module):
def__init__(self):
super(Net, self).__init__()
# 定义了我们第⼀个要⽤到的卷积层,因为图⽚输⼊通道为1,第⼀个参数就是
# 输出的通道为10,kernel_size是卷积核的⼤⼩,这⾥定义的是5x5的
1一12月份的英文缩写# 看懂了上⾯的定义,下⾯这个你肯定也能看懂
#调⽤盗梦空间
self.incep1 = InceptionA(in_channels=10)
self.incep2 = InceptionA(in_channels=20)
# 再定义⼀个池化层
self.mp = MaxPool2d(2)
# 最后是我们做分类⽤的线性层
self.fc = Linear(1408,10)
# 下⾯就是计算的过程
def forward(self, x):
# Flatten data from (n, 1, 28, 28)
batch_size = x.size(0)# 这⾥⾯的0是x⼤⼩第1个参数,⾃动获取batch⼤⼩#(64, 1, 28, 28)经过10组ke
rnel=5的卷积 ((64, 10, 24, 24)),通过最⼤池化(64, 10, 12, 12) x = F.relu(self.v1(x)))
# 输⼊到盗梦空间(64, 10, 12, 12),尺⼨不变,维度相加(64, 88, 12, 12)
x = self.incep1(x)
# (64, 88, 12, 12)经过20组kernel=5的卷积 ((64, 20, 8, 8)),通过最⼤池化(64, 20, 4, 4)
x = F.relu((self.v2(x))))
#输⼊到盗梦空间(64, 20, 4, 4),尺⼨不变,维度相加(64, 88, 4, 4) ioriw
x = self.incep2(x)
# 为了给我们最后⼀个全连接的线性层⽤
# 我们要把⼀个⼆维的图⽚(实际上这⾥已经是处理过的)64X88x4x4张量变成⼀维的
x = x.view(batch_size,-1)# flatten
#64X88x4x4改变为64x1408
# 经过线性层,确定他是0~9每⼀个数的概率
#64x1408改变为64x10 因为⼿写数据集10个分类
x = self.fc(x)
return x
总结
学⽆⽌境,越⾛下去,发现⾃⼰不懂的越多,深感渺⼩,还需继续努⼒。
发布评论