本文参考:
D
i
v
e
Dive
D i v e
I
n
t
o
Into
I n t o
D
e
e
p
Deep
D e e p
L
e
a
r
n
i
n
g
Learning
L e a r n i n g
AlexNet 和 VGG 对 LeNet 的改进主要在于如何对卷积层和全连接层模块加宽(增加通道数)和加深。而 NiN 提出了另外一个思路,即串联多个由卷积层和“全连接”层构成的小网络来构建一个深层网络
NiN 块
1
×
1
1×1
1 × 1 卷积层中可以把通道当作特征,高和宽上的每个元素相当于样本。因此,NiN 使用
1
×
1
1×1
1 × 1 卷积层来替代全连接层,从而使空间信息能够自然传递到后面的层中去 (可以实现多个 feature map 的线性组合,实现跨通道的信息整合的功效) NiN 块 是 NiN 中的基础块。它由一个卷积层加两个充当全连接层的
1
×
1
1×1
1 × 1 卷积层串联而成。其中第一个卷积层的超参数可以自行设置,而第二和第三个卷积层的超参数一般是固定的
def nin_block ( in_channels, out_channels, kernel_size, strides, padding) :
blk = [ ]
blk += [ nn. Conv2d( in_channels, out_channels, kernel_size, strides, padding) ,
nn. ReLU( inplace= True ) ,
nn. Conv2d( out_channels, out_channels, kernel_size= 1 ) ,
nn. ReLU( inplace= True ) ,
nn. Conv2d( out_channels, out_channels, kernel_size= 1 ) ,
nn. ReLU( inplace= True ) ]
return blk
NiN 模型
NiN 是在 AlexNet 问世不久后提出的。它们的卷积层设定有类似之处。NiN使用卷积窗口形状分别为
11
×
11
11×11
1 1 × 1 1 、
5
×
5
5×5
5 × 5 和
3
×
3
3×3
3 × 3 的卷积层,相应的输出通道数也与 AlexNet 中的一致。每个 NiN 块后接一个步幅为 2、窗口形状为
3
×
3
3×3
3 × 3 的最大池化层 NiN去掉了 AlexNet 最后的3个全连接层,取而代之地,NiN 使用了输出通道数等于标签类别数的 NiN 块,然后使用全局平均池化层 (Global Average Pooling, GAP) 对每个通道中所有元素求平均并直接用于分类
class NiN ( nn. Module) :
def __init__ ( self, num_classes= 1000 ) :
super ( NiN, self) . __init__( )
layers = [ ]
channels = [ 3 , 96 , 256 , 384 ]
kernel_size = [ 11 , 5 , 3 ]
strides = [ 4 , 1 , 1 ]
paddings = [ 0 , 2 , 1 ]
for i in range ( 3 ) :
layers += nin_block( channels[ i] , channels[ i + 1 ] , kernel_size[ i] , strides[ i] , paddings[ i] )
layers. append( nn. MaxPool2d( 3 , 2 ) )
layers. append( nn. Dropout( 0.5 ) )
self. features = nn. Sequential( * layers)
layers = [ ]
layers += nin_block( 384 , 10 , kernel_size= 3 , strides= 1 , padding= 1 )
layers. append( nn. AdaptiveAvgPool2d( 1 ) )
self. classifier = nn. Sequential( * layers)
def forward ( self, x) :
x = self. features( x)
x = self. classifier( x)
x = x. squeeze( )
return x
为什么NiN块中要有两个1x1卷积层?
截取《DIVE INTO DEEP LEARNING》讨论区里的回答: 每个
1
×
1
1\times1
1 × 1 卷积层都可以视为多了一层非线性变换,多加了这种非线性变换网络的性能应该也能变好