在GoogLeNet中,根本的卷积块被称为Inception块
- 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)
复制代码 inception块的亮点:
多路径并行处理惩罚,增加了网络的宽度
1*1卷积被用来淘汰或增加通道数,同时淘汰盘算量
差别大小的卷积核使得网络能够捕获差别尺度的特征
使用最大汇聚层,在空间上低沉特征图的尺寸,同时保留最重要的信息
在最大汇聚层后立纵然用1*1卷积层,有助于淘汰参数量,使得特征图的通道数可以调整
滤波器(filter)的组合
它们可以用各种滤波器尺寸探索图像,这意味着差别大小的滤波器可以有效地识别差别范围的图像细节。 同时,我们可以为差别的滤波器分配差别数量的参数。
GoogLeNet模型
逐层实现
第一层:64个通道,7*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))
复制代码 第二层:第一个卷积层64个通道,1*1卷积层,第二个卷积层使用将通道数量增加三倍的3*3卷积层,这对于inception块中的第二条路径
- b2 = nn.Sequential(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))
复制代码 第三个模块串联两个完备的Inception块
- 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))
复制代码 第四模块更加复杂, 它串联了5个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))
复制代码 第五模块包罗输出通道数为256+320+128+128=832和384+384+128+128=1024的两个Inception块。
- b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
- Inception(832, 384, (192, 384), (48, 128), 128),
- nn.AdaptiveAvgPool2d((1,1)),
- nn.Flatten())
- net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10))
复制代码 问题:
什么时候需要些forward函数?
自界说卷积层的时候:创建一个具有特别举动的卷积层,比如改变卷积核的大小,步长,添补或者添加特定的激活函数组合时,需要继续现有的层并重写forward函数
组合卷积操纵:当你想要将卷积与其他操纵(如批量归一化,激活函数,dropout等)组合在一起时,可以通过界说forward函数来实现
实现特别模型时:如Inception网络,ResNet等,其中包罗了多个并行的卷积路径,需要在forward函数中实现这些路径的数据活动
集成外部操纵:如果要集成一些外部操纵,比如自界说的数学函数或从其他库导入的操纵时,在forward中实现
修改前向传播逻辑:如果需要根据输入数据的差别特性动态改变前向传播举动,如使用条件卷积
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |