MobileNetv3简记
- 简单记录一下
MobileNetv2
- 简单回顾下MobileNetv2,主要是引入了深度可分离卷积,见:MobileNetv2
MobileNetv3的主要修改
-
1、看代码主要是加上了SqueezeExcitation模块(参考SENet)
-
2、在网络末端减少1x1卷积(减少的这个是用来改变通道的),不过在我看来应该是作者试验了一下,发现减少了效果也还行,就说了 (此话不负责)
-
3、在网络开头,减少3x3卷积核的数量,并使用非线性激活函数减少损失
-
hard swish nonlinearity
-
由于sigmoid计算代价大,于是乎换成了ReLU6,效果似乎还可以
-
(We were able to reduce the number of filters to 16 either ReLU or swish(原本是32))
-
代码
# 这段是主体部分
class InvertedResidual(nn.Module):
def __init__(self, cnf: InvertedResidualConfig,
norm_layer: Callable[..., nn.Module]):
super(InvertedResidual, self).__init__()
if cnf.stride not in [1, 2]:
raise ValueError("illegal stride value.")
self.use_res_connect = (cnf.stride == 1 and cnf.input_c == cnf.out_c)
layers: List[nn.Module] = []
activation_layer = nn.Hardswish if cnf.use_hs else nn.ReLU
# expand
if cnf.expanded_c != cnf.input_c:
layers.append(
ConvBNActivation(cnf.input_c,
cnf.expanded_c,
kernel_size=1,
norm_layer=norm_layer,
activation_layer=activation_layer))
# depthwise
layers.append(
ConvBNActivation(cnf.expanded_c,
cnf.expanded_c,
kernel_size=cnf.kernel,
stride=cnf.stride,
groups=cnf.expanded_c,
norm_layer=norm_layer,
activation_layer=activation_layer))
if cnf.use_se:
# 这里要用SE了
layers.append(SqueezeExcitation(cnf.expanded_c))
self.block = nn.Sequential(*layers)
self.out_channels = cnf.out_c
self.is_strided = cnf.stride > 1
def forward(self, x: Tensor) -> Tensor:
result = self.block(x)
if self.use_res_connect:
result += x
return result
# SE的实现如下
class SqueezeExcitation(nn.Module):
def __init__(self, input_c: int, squeeze_factor: int = 4):
super().__init__()
# 这个结构其实就是加入了SENet的思想
squeeze_c = _make_divisible(input_c // squeeze_factor, 8)
self.fc1 = nn.Conv2d(in_channels=input_c,
out_channels=squeeze_c,
kernel_size=1)
self.fc2 = nn.Conv2d(in_channels=squeeze_c,
out_channels=input_c,
kernel_size=1)
def forward(self, x):
scale = F.adaptive_avg_pool2d(x, output_size=(1, 1))
scale = self.fc1(scale)
scale = F.relu(scale, inplace=True)
scale = self.fc2(scale)
scale = F.hardsigmoid(scale, inplace=True)
return scale * x
语义分割的应用
- Lite R-ASPP,没试过,但是感觉Segmentation Head没有太大的创新
总结
- 看起来改动不大,主要就SE模块,网络末端减少1x1卷积,ReLU6三块内容,不知道有没有漏掉了~