深度学习架构:Inception网络解析

随着研究论文在全球范围内的涌现,深度学习架构的发展势头日益强劲。这些论文不仅包含了大量的信息,而且为新的深度学习架构的诞生提供了新的思路,但它们往往难以解析。为了理解这些论文,可能需要多次阅读,甚至阅读其他相关的论文。其中,Inception网络就是这些架构之一。

Inception网络是CNN图像分类器发展中的一个重要里程碑。在这种架构之前,大多数流行的CNN或分类器只是通过不断堆叠卷积层来获得更好的性能。而Inception网络则经过了精心设计,非常深且复杂。它使用了许多不同的技术来提升其性能,无论是在速度还是准确性方面。

Inception网络简介

Inception网络(ResNet)是由Christian Szegedy, Wei Liu, Yangqing Jia, Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke, 和 Andrew Rabinovich 在他们的论文《Going deeper with convolutions》中于2014年提出的一个著名的深度学习模型。随后,Sergey Ioffe, Christian Szegedy, Jonathon Shlens, Vincent Vanhouck, 和 Zbigniew Wojna 在他们的论文《Rethinking the Inception Architecture for Computer Vision》中于2015年提出了Inception网络的不同版本。Inception模型被归类为流行且广泛使用的深度学习模型之一。

设计原则

提出一些通用的设计原则和优化技术,对于有效地扩展卷积网络是有益的。在网络架构的早期阶段,避免表示瓶颈。如果网络拥有更多的不同过滤器,它将学习得更快,因为这意味着更多的不同特征图。在低维嵌入上进行空间聚合,即维度降低,不会对表示能力造成太大损失。通过平衡宽度和深度,可以实现网络的最优性能。

Inception模块

Inception模块(原始):近似一个最优的局部稀疏结构,处理不同尺度的视觉/空间信息,然后聚合。这在计算上有些乐观,特别是5×5卷积特别昂贵。

Inception模块(维度降低):维度降低是必要的,并且是动机化的(网络内的网络)。通过1×1卷积实现,可以认为是在深度上学习池化,而不是在高度/宽度上的最大/平均池化。

Inception架构

使用降维的Inception模块,构建了一个深度神经网络架构(Inception v1)。架构如下所示:Inception网络线性堆叠了9个这样的Inception模块。它有22层深(如果包括池化层则是27层)。在最后一个Inception模块的末尾,它使用全局平均池化。

class conv_block(nn.Module): def __init__(self, in_channels, out_channels, **kwargs): super(conv_block, self).__init__() self.relu = nn.ReLU() self.conv = nn.Conv2d(in_channels, out_channels, **kwargs) self.batchnorm = nn.BatchNorm2d(out_channels) def forward(self, x): return self.relu(self.batchnorm(self.conv(x)))

对于降维和修正线性激活,使用128个过滤器的1×1卷积。修正线性激活与具有1024个单元的全连接层。使用dropout层丢弃70%的输出。使用softmax损失和线性层作为分类器。

以下是Inception网络的流行版本:

  • Inception v1
  • Inception v2
  • Inception v3
  • Inception v4
  • Inception-ResNet

Inception架构多次使用具有不同过滤器的CNN块,如1×1、3×3、5×5等,因此让创建一个CNN块的类,它接受输入通道和输出通道以及batchnorm2d和ReLU激活。

class Inception_block(nn.Module): def __init__(self, in_channels, out_1x1, red_3x3, out_3x3, red_5x5, out_5x5, out_1x1pool): super(Inception_block, self).__init__() self.branch1 = conv_block(in_channels, out_1x1, kernel_size=(1, 1)) # ... 省略部分代码 ... def forward(self, x): return torch.cat([self.branch1(x), self.branch2(x), self.branch3(x), self.branch4(x)], 1)

让以下面的图像作为参考开始构建网络。

class GoogLeNet(nn.Module): def __init__(self, aux_logits=True, num_classes=1000): super(GoogLeNet, self).__init__() assert aux_logits == True or aux_logits == False self.aux_logits = aux_logits # ... 省略部分代码 ...

然后定义一个输出层的类,该类具有dropout=0.7,如论文中所述,以及一个带有softmax的线性层,用于输出n_classes。

class InceptionAux(nn.Module): def __init__(self, in_channels, num_classes): super(InceptionAux, self).__init__() self.relu = nn.ReLU() self.dropout = nn.Dropout(p=0.7) self.pool = nn.AvgPool2d(kernel_size=5, stride=3) self.conv = conv_block(in_channels, 128, kernel_size=1) self.fc1 = nn.Linear(2048, 1024) self.fc2 = nn.Linear(1024, num_classes) def forward(self, x): x = self.pool(x) x = self.conv(x) x = x.reshape(x.shape[0], -1) x = self.relu(self.fc1(x)) x = self.dropout(x) x = self.fc2(x) return x

然后,程序应该按照以下方式对齐:

  • GoogLeNet类
  • Inception_block类
  • InceptionAux类
  • conv_block类
if __name__ == "__main__": # N = 3 (Mini batch size) x = torch.randn(3, 3, 224, 224) model = GoogLeNet(aux_logits=True, num_classes=1000) print(model(x)[2].shape)
  • Christian Szegedy, Wei Liu, Yangqing Jia. Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke 和 Andrew Rabinovich: Going deeper with convolutions, Sep 2014, DOI:
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485