MobileNet V2中InvertedResidual实现
1、为了方便理解其本身结构,找到源码理解一下。
2、论文地址:http://arxiv.org/pdf/1801.04381.pdf
3、V2相比较V1增加了倒残差结构和线性瓶颈层。整个结构按照维度来看,类似一个中间宽,两边窄的结构。其中最后一层使用linear卷积(没有使用ReLU进行非线性激活,也就是线性了),主要是考虑到ReLU对于高维激活可以得到很好的非线性特征信息,但是低维采用非线性就行破坏特征信息(也称为数据坍塌,就是有一部分特征被毁掉了),虽然在高维经常使用ReLU,但是不像在低维造成很大的特征丢失情况(因为可能丢掉一部分不重要的特征,对最终结果没啥影响)。因此采用线性(就不加ReLU)。至于为什么叫倒残差,可能也是由于该结构的形状吧,便于与残差结构区分。毕竟原始残差结构是中间窄,两边宽。
class InvertedResidual(nn.Module): def __init__(self, inp, oup, stride, expand_ratio): super(InvertedResidual, self).__init__() assert stride in [1, 2] hidden_dim = round(inp * expand_ratio) self.identity = stride == 1 and inp == oup if expand_ratio == 1: self.conv = nn.Sequential( # dw nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False), nn.BatchNorm2d(hidden_dim), nn.ReLU6(inplace=True), # pw-linear nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), nn.BatchNorm2d(oup), ) else: self.conv = nn.Sequential( # pw nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False), nn.BatchNorm2d(hidden_dim), nn.ReLU6(inplace=True), # dw nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False), nn.BatchNorm2d(hidden_dim), nn.ReLU6(inplace=True), # pw-linear nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), nn.BatchNorm2d(oup), ) def forward(self, x): if self.identity: return x + self.conv(x) else: return self.conv(x)