文献名称:MobileNetV2: Inverted Residuals and Linear Bottlenecks
发表时间:2018年
下载地址:https://openaccess.thecvf.com/content_cvpr_2018/papers/Sandler_MobileNetV2_Inverted_Residuals_CVPR_2018_paper.pdf
Mobile Net V1 存在以下问题:
Mobile Net V2 就以上的问题,做了进一步的改善。
ResNet 的 residual block 和 Mobile Net 的 Inverted residual block 的相似与区别:
conv 1x1
→\rightarrow→ conv 3x3
→\rightarrow→ conv 1x1
, 最后做一个跨层连接 shortcut
conv 3x3
是标准的 3x3卷积,而 Inverted residual block 中间一层做的是 depth-wise convolutionReLU 激活函数
,而 Inverted residual block 第一个conv 1x1
和中间的 conv 3x3
后面跟的都是 ReLU6 ,最后一个 conv 1x1
做完降维后,跟的是一个 linear 线性激活函数
。也就是下图中 对角线斜纹表示的层后面跟的是 线性激活层Inverted residual block 的结构说明:
为什么要使用 倒残差结构呢?
(先说结论再细讲) 因为非线性变换 (ReLU) 会造成信息丢失,所以需要先升维,创造出冗余维度,再在冗余维度中做 非线性变换 (ReLU),最后再把维度降回去,只提取有用的必要信息。
作者做了一个实验,将一个2维空间中 n个点组成的 螺旋线 X2×nX_{2 \times n}X2×n, 将其经矩阵 Tm×2T_{m \times 2}Tm×2 映射到 m 维 ,并做 ReLU激活。表达式为: Y=ReLU(Tm×2⋅X2×n)Y = ReLU( T_{m \times 2} \cdot X_{2 \times n})Y=ReLU(Tm×2⋅X2×n)。 再将 YYY 通过 T−1T^{-1}T−1 转换回 二维空间,记为 X^\hat XX^,对比 XXX 和 X^\hat XX^,观察信息丢失情况
** m维 就对应下图中的 dim = 2 / 3 / 5 / 15 / 30
** T−1T^{-1}T−1 是 TTT 的广义逆矩阵
实验结论是,如果 映射的维度 m比较低,经过ReLU变化后,就会丢失很多信息。 如果 维度m比较高,做ReLU变换后,丢失的信息就少很多。 这也就是为什么 conv 1x1 降维后,不使用 ReLU,而是使用线性激活函数了。
为什么采用 ReLU6 呢?
因为 Mobile Net 的设计就是为了应用于 移动设备 或者 内嵌式设备 这种内存比较小的设备上,一般要求低精度表示,比如 使用 8 bit 表示一个数(应该是没有 float8 这种通用数据类型的,这种数据类型用于完全特定目的)。
(以下这句话是个人理解,如有不对请指出)
所以,使用 ReLU6 就可以将数值限制在6之内,整数部分只占3位,剩下的 bit 位 用于表示小数部分,也只能表达较低精度了。 (相关浮点数精度解释 看这里)
那为什么是 6,不是5, 7, 8 呢 ?
作者说 : the value 6 that fits best in 8 bits, which probably is the most use-case.
移动端大多数使用场景采用的是 float8 ,使用 6 是最合适的。
t :expansion rate
c : 输出的维度数
n : bottleneck 重复的次数
s : (重复的n个模块中)首个模块的步长,剩下的模块步长都为1
其中,block 有的需要跨层连接,有的不要,判断标准是 是否下采样了,下采样的block因为输入和输出尺寸不一样,不能shortcut。只有没有下采样的block(stride=1的block)才有 shorcut。 如下图:
代码地址:https://github.com/Enzo-MiMan/cv_related_collections/blob/main/classification/MobileNet/model_MobileNet_v2.py