Resnet
method
Resnet引入了所谓残差连接的思想:对于每一个层,我们要学习的不是$\mathcal{H}(x)$,而是$\mathcal{F}(x) = \mathcal{H}(x) - x$。换句话讲,我们不需要再学之前层学过的东西,而是要学两者的差距。

注意Resnet在连接时,存在两种不同的连接方式: $$ y = \mathcal{F}(x,{W_i})+x \ $$
$$ y = \mathcal{F}(x,{W_i})+W_sx $$
当跨越维度连接时,有两种可选方案来解决维度不适配的问题:1) 补0 2)投影。消融实验表明,这两种方法对结果没有本质影响。
不同的Resnet配置如下:

code
BasicBlock
见resnet.py。
Resnet提供了两种原版结构:BasicBlock和BottleNeck。此处不再深究两者的区别,以默认的BasicBlock为例:
 | 
 | 
每一个BasicBlock对应的是这样一个模块:

其__init__参数中的inplanes和planes分别指代input channel和output channel,一个简单示例如下:
 | 
 | 
其forward部分如下:
 | 
 | 
注意到其中的残差连接部分。值得注意的是,为了进行维度匹配,forward中还存在self.downsample部分,是一个channel维度不匹配的二维卷积。之后在Resnet的解释中会详细说明:
 | 
 | 
Resnet
观察其forward函数,我们逐个分析其中的模块:
 | 
 | 
self.conv1(x)使用7x7卷积核,将图片的channel从3变为64,同时特征图长宽缩短一半。
 | 
 | 
self.maxpool(x)将特征图长宽再缩短一半。
 | 
 | 
之后是模块的主体部分:
 | 
 | 
首先看这4个层中共有的特征:64/128/256/512是输出通道数,layers[i]是通道的层数。
注意到layer1和其它模块参数的不同之处:无stride。这决定了:
- 每一个layer第一个
BasicBlock的状态: 
 | 
 | 
第一个layer用于缩小特征图和增加channel数(stride=1时除外)。其它的layer保持特征图的尺寸不变。
 | 
 | 
- 是否含有downsample层:
 
 | 
 | 
当跨层进行残差连接时,可能会出现维度不匹配的问题,这时候需要进行downsampling以使得维度匹配:
 | 
 | 
self.avgpool所使用的是torch.nn.AdaptiveAvgPool2d,使用时只需要指定最后两维的尺寸(H_0, W_0)即可。
self.fc将图片分为1000类。
最后我们对模型的使用做一个总结(以resnet34为例):
 | 
 | 
 | 
 | 

