MobileNet V2 随笔

本文详细探讨了MobileNetV2的网络结构改进,包括LinearBottlenecks、InvertedResiduals及其对特征信息处理的影响。并通过实验论证了ReLU6激活函数对特征信息空间的潜在损害。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MobileNet V2

Linear Bottlenecks and Inverted Residuals

下图是可分离卷积:

请注意到由于 MobileNet 使用 Batch Normalization ,而 Batch Normalization 的 beta 项含有均值,因此整个 MobileNet 并没有使用 BiasAdd 操作。其次,我们要注意到 MobileNetV1 无论是 Depthwise Conv 还是 Pointwise Conv ,它们后面会加入一个 ReLu6 操作,作者在 MobileNetV2 花了很大篇幅来讨论这个操作的影响。

下面两张图是 MobileNet V1 的模块结构:

下图是 MobileNet V2 的主要模块结构(Linear Bottlenecks and Inverted Residuals):

不难发现 MobileNet V2 的主要结构,只是在 MobileNet V1 的基础上引入了,残差连接和瓶颈结构,以及把 Pointwise 的激活改成了 Linear 。

MobileNet V2 网络结构

下图是 MobileNet V2 的网络架构:

下图是 MobileNet V1 的网络架构:

对比 MobileNet 的 V1 和 V2 两版网络架构,我们发现两版都没有 Pooling 层,而是直接把 stride 设成 2 ,直接卷积缩放。而且最近有些观点表示,Pooling 层产生的的特征丢失不可逆转,所以 MobileNet 一直就没有 Pooling 层。另外,大致一眼过去,貌似 V2 宽度比 V1 小很多。然而,我们挑出其中一层,比如 56×56 56 × 56 来算一下,会发现 V2 中间该模块中间有两层 feature map 的维度达到 192 ,而 V1 仅有128。这么看来,V2 的特征信息传输更高效,对数据带宽利用率更好。再就是,尽管 v2 比 v1 更深,但是 v2 的 parameters 未必就比 v1 多。因为 MobileNet 的参数重量,主要不在 depthwise 上,而是在 poinwise ,所以瓶颈压缩部分减少了不少 pointwise 的参数。

Memory Efficient Trick

这个内存高效利用技巧,我用下面的草稿解释。

需要注意,源码这部分的实现逻辑可能是有问题的,貌似与原文精神不一致。

def split_conv(input_tensor,
               num_outputs,
               num_ways,
               scope,
               divisible_by=8,
               **kwargs):
    """Creates a split convolution.
    Split convolution splits the input and output into
    'num_blocks' blocks of approximately the same size each,
    and only connects $i$-th input to $i$ output.
    Args:
        input_tensor: input tensor
        num_outputs: number of output filters
        num_ways: num blocks to split by.
        scope: scope for all the operators.
        divisible_by: make sure that every part is divisiable by this.
        **kwargs: will be passed directly into conv2d operator
    Returns:
        tensor
    """
    b = input_tensor.get_shape().as_list()[3]

    if num_ways == 1 or min(b // num_ways,
                            num_outputs // num_ways) < divisible_by:
        # Don't do any splitting if we end up with less than 8 filters
        # on either side.
        return slim.conv2d(input_tensor, num_outputs, [1, 1], scope=scope, **kwargs)

    outs = []
    input_splits = _split_divisible(b, num_ways, divisible_by=divisible_by) # 这句貌似不应该拆分输入
    output_splits = _split_divisible(
        num_outputs, num_ways, divisible_by=divisible_by)
    inputs = tf.split(input_tensor, input_splits, axis=3, name='split_' + scope)
    base = scope
    for i, (input_tensor, out_size) in enumerate(zip(inputs, output_splits)):
        scope = base + '_part_%d' % (i,)
        n = slim.conv2d(input_tensor, out_size, [1, 1], scope=scope, **kwargs)
        n = tf.identity(n, scope + '_output')
        outs.append(n)
    return tf.concat(outs, 3, name=scope + '_concat')

上面源码这段,我认为是有问题的,输入输出一般不可能是同时进行 split 的,甚至大多数情况都不会去尝试拆输入。

下面附录一张我的原始推导笔记:

关于 ReLu6 的讨论

我认为 MobileNet V2 的关键论点,可能并不是 Linear Bottleneck 和 Inverted Residuals 本身的形式,它们只是一个研究结果而已。而作者主要的论点应该是,以 ReLu6 为例的非线性激活映射,对特征信息空间的有害影响。在部分的讨论中,作者有一个观点,我认为比较有趣。这个观点是:

In ReLu(Bx) R e L u ( B x ) , which B B is the linear classifier to ensure which are the non-zero volume part of output space

这也就是说,每个卷积层都能看作 Feature Map 分类器,而 ReLu 决定了一些特征的去留。大于零的算做重要特征被留下,小于等于零作为冗余特征被舍弃。同时,我们很清楚世上并不存在完美分类器,从不误判的分类器。因此这些分类器只要出现误判,那么特征信息就会出现损失,而且作为符合条件概率的链式响应,这个信息损失应该相当严重,精度应该很低,那为何现在 CNN 在某些领域,依然表现出色呢?这是因为 B 会把 x 的信息,散落到比 x 更高的维度空间上,保持了一定的信息冗余。这样就能在有信息损失的推理过程中,利用剩下的特征信息推理出正确的结果。因此,有了 Linear Bottleneck 和 Inverted Residuals 设计,既能逐步筛选有效的抽象特征,而又不在 bottleneck 时,丢失重要的特征信息。

下面的实验现象是:

S2=(x1(t),x2(t))t线Tn×2R2RnnT2×n1ReLu6(Tn×2S2)S2
我们可以看到 ReLu 非线性激活对原始信息损害,因此在 bottleneck module 后面加 ReLu6 操作,并不一定是个恰当的选择。

下面图的实验,将 Linear bottleneck 的猜想用到 MobileNet 的表现,还顺带讨论了 shortcut 对 expansion module 的影响。

这里,我也借机表达个人观点。首先,对于 Inverted residuals 的设计,作者很诚实告诉我们这是一个无心插柳柳成荫的故事。他最初的动机,只是打算借助 classical residual connections 在梯度传播上的优势,提高网络推理的准确性。然而,classical residual connections 是 shortcut between expansions 的,这对前面 Memory Efficinet Trick 在实现上很不友好,甚至相当麻烦。因此,补充了一个 Shortcut between bottleneck 的实验对照,本来只要效果过得去,就谢天谢地了。没想到,这效果竟然比传统的要好,所以他也把这个点作为 MobileNet V2 的其中一个亮点放在了标题。

对 Linear bottleneck Inverted residual block ,作者尝试从信息流动的角度进行解释。他直观地把这种 block 拆分成两个阶段,一个是 expansion ,再就是 bottleck 。他认为 expansion layers 可以看作相应层的 capacity ,这好比是一种特征池。而 bottleneck 则是 expressiveness ,对众多特征反应结果的综合概括。这仿佛就是人类对事物的认知过程,先从众多维度,各个方面,分析事物的不同特性,这是一种发散型分析,expansion 的过程。然后,对这些不同的特性进行总结,从而归纳出该事物的一个简单规律,是事物的抽象而完整表述,bottlenect 的过程。基于作者的这解析角度,我们可以不难猜测 Inverted residuals 成功背后的原理是,事物的抽象表达更完整了,而且更容易保全事物的信息。用 Shortcut between Expansions 保留事物的重要信息,犹如在茫茫人海中,确认眼神找对象一样,是个大海捞针的过程,稍不留神 bottleneck 就把信息丢了,丢了再 shortcut 也只是徒劳。Expansion 空间维度那么高,事情反而不好学了。

总结

当初笔者粗读原文时,MobileNet V2 给我的感觉就是并没有创意,改几个连接,做几个尝试性实验出来的成果。随着对作者观点的深入,虽然现在我还没感受 MobileNet V2 的重大突破,但是我觉着作者的想法和观点很大胆,很独特,很新颖,很有趣。主要原因是作者看待 bottleneck 的方式,是跟原来相反的。原来人们都爱把 bottleneck 放在两个胖子中间,比如 ResNeXt 就是这种观点,而作者却把 bottlenecks 看作一个胖子的两端,这么想的话,其实这个胖子还有不少的瘦身空间,比如对胖子引入 ResNeXt 的 Cardinality 参数等。也正因为作者很多这种“反过来想”的研究观点,丰富了我对轻量网络结构设计的观点,所以这篇论文更适合耐心品尝,浮躁很难感受到这篇文章的真实亮点。

### MobileNet V2 架构概述 MobileNet V2 是一种高效的卷积神经网络架构,专为移动设备和嵌入式视觉应用设计[^2]。它通过引入 **倒残差结构 (Inverted Residuals)** 和 **线性瓶颈层 (Linear Bottlenecks)** 来优化计算效率和模型表现。 #### 主要特点 - **深度可分离卷积 (Depthwise Separable Convolutions):** 这种技术显著减少了计算复杂度和参数数量。标准卷积分解为两部分:深度卷积(depthwise convolution)处理空间信息,逐点卷积(pointwise convolution)负责通道间的交互[^4]。 - **倒残差块:** 倒残差块的设计思路是从低维特征映射扩展到高维特征映射,再压缩回低维输出。这种机制允许在网络较浅的部分保留更多细节信息,从而提升性能[^4]。 - **线性瓶颈层:** 在每个倒残差块的末端使用线性激活函数来保持信息流稳定,防止因非线性操作导致的信息丢失。 --- ### 实现代码示例 以下是基于 PyTorch 的 MobileNet V2 模型加载与推理代码: ```python import torch from torchvision import models # 加载预训练的 MobileNet V2 模型 model = models.mobilenet_v2(pretrained=True) # 设置模型为评估模式 model.eval() # 创建随机输入张量 (模拟图像数据) input_tensor = torch.randn(1, 3, 224, 224) # 执行前向传播推理 with torch.no_grad(): output = model(input_tensor) print(output.shape) # 输出形状应为 [1, 1000] 对应 ImageNet 数据集中的类别数 ``` 此代码片段展示了如何利用 `torchvision` 中提供的接口快速加载并运行 MobileNet V2 预训练模型[^5]。 --- ### 使用场景分析 MobileNet V2 广泛应用于多种计算机视觉任务,例如图像分类、目标检测和语义分割等。其高效性和轻量化特性使其特别适合资源受限环境下的部署[^3]。具体来说,在 COCO 数据集中,MobileNet V2 被用作 SSD 单阶段检测器的基础特征提取器之一,并表现出良好的速度与精度权衡[^3]。 ---
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值