首页
/ 在 Transformers 中使用 MobileNetV2:倒残差架构原理、配置参数与图像分类/语义分割实战指南

在 Transformers 中使用 MobileNetV2:倒残差架构原理、配置参数与图像分类/语义分割实战指南

2026-09-07 20:25:50作者:羿妍玫Ivan

本文是面向视觉开发者的 MobileNetV2 实战指南。MobileNetV2 是 Google 于 2018 年提出的高效轻量级 CNN,专为移动端与嵌入式场景设计,通过倒残差块(Inverted Residual Block)、线性瓶颈(Linear Bottleneck)与深度可分离卷积在显著压缩计算量的同时保持较高精度。在 Transformers 仓库中,它以标准 AutoModel 体系提供图像分类与语义分割两个下游任务,并配套专用 Image Processor 与完整文档(见 mobilenet_v2.md)。读完本文,你将掌握 MobileNetV2 在 Transformers 中的调用方式、MobileNetV2Config 全部关键参数含义、预处理流水线行为,以及其底层 PyTorch 实现原理,可直接落地到移动端视觉推理项目。

一、MobileNetV2 的架构核心:从设计动机说起

MobileNetV2 的目标是在移动设备上以更高效的架构提升性能。它的三个核心设计在 Transformers 的实现中均有对应:

  1. 倒残差块(Inverted Residual Block):与经典残差网络"先压缩再扩张"相反,它先将输入用 1×1 卷积扩张到更高维(默认膨胀 6 倍),经过深度卷积处理后,再用 1×1 卷积压缩回低维,即"先缩小表示、扩张处理、再缩小输出"的漏斗结构,从而减少计算量。
  2. 线性瓶颈(Linear Bottleneck):在瓶颈层(输出通道数最少的投影层)移除非线性激活,防止 ReLU 在低维空间中破坏有效信息。
  3. 深度可分离卷积(Depthwise Separable Convolution):与 MobileNet V1 一脉相承,把标准卷积分解为逐通道的 depthwise 卷积与逐点 1×1 卷积,进一步削减乘加运算。

在源码 modeling_mobilenet_v2.py 中,上述设计被拆成三个可复用的 PyTorch 模块,一一对应:

源码类 对应设计 关键行为
MobileNetV2ConvLayer 基础卷积单元 Conv2d + BatchNorm2d + 激活;无 bias,BatchNorm momentum=0.997
MobileNetV2InvertedResidual 倒残差块 expand_1x1(扩张) → conv_3x3(depthwise) → reduce_1x1(压缩,无激活);仅当 stride==1 且通道数不变时启用残差捷径
MobileNetV2Stem 网络入口 首个 stride=2 的 3×3 卷积扩到 32 通道,再做一次 depthwise 3×3 与 1×1 投影

其中 MobileNetV2InvertedResidual__init__(见 modeling_mobilenet_v2.py)用 expanded_channels = make_divisible(int(round(in_channels * config.expand_ratio)), ...) 计算扩张通道数,并用 use_activation=False 实现"线性瓶颈"——压缩层不接激活函数。残差连接的存在条件被显式写为 (stride == 1) and (in_channels == out_channels),与原始论文一致。

二、在 Transformers 中加载与推理:Pipeline 与 AutoModel 两条路径

MobileNetV2 于 2022-11-14 合入 Transformers,全部原始 checkpoint 位于 Google 组织下(google/mobilenet_v2_* 分类系列与 google/deeplabv3_mobilenet_v2_* 分割系列)。下面两种加载方式来自 官方文档,可直接复制运行。

2.1 方式一:Pipeline(一行代码完成分类)

from transformers import pipeline


pipeline = pipeline(
    task="image-classification",
    model="google/mobilenet_v2_1.4_224",
    device=0
)
pipeline("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg")

device=0 指定使用 GPU 0;若在纯 CPU 环境可移除该参数。Pipeline 会自动完成图像加载、预处理、前向推理与 Top-K 结果后处理。

2.2 方式二:AutoModel(精细控制推理流程)

import requests
import torch
from PIL import Image

from transformers import AutoImageProcessor, AutoModelForImageClassification


image_processor = AutoImageProcessor.from_pretrained(
    "google/mobilenet_v2_1.4_224",
)
model = AutoModelForImageClassification.from_pretrained(
    "google/mobilenet_v2_1.4_224",
    device_map="auto",
)

url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
image = Image.open(requests.get(url, stream=True).raw)
inputs = image_processor(image, return_tensors="pt").to(model.device)

with torch.no_grad():
  logits = model(**inputs).logits
predicted_class_id = logits.argmax(dim=-1).item()

class_labels = model.config.id2label
predicted_class_label = class_labels[predicted_class_id]
print(f"The predicted class label is: {predicted_class_label}")

值得说明的是,AutoImageProcessor 会根据 checkpoint 自动匹配到 MobileNetV2ImageProcessor(Torchvision 后端)或 MobileNetV2ImageProcessorPil(PIL 后端),两者 API 完全一致。仓库集成测试正是在 google/mobilenet_v2_1.0_224 上验证分类输出 logits 形状为 (1, 1001) 并比对了数值切片(见 test_modeling_mobilenet_v2.py)。

三、命名规律与任务差异:读模型名即可知配置

  • 分类 checkpoint 遵循 mobilenet_v2_{depth_multiplier}_{resolution},例如 mobilenet_v2_1.4_2241.4 是深度乘子(depth multiplier),224 是训练时的图像分辨率。
  • 分割 checkpoint 遵循 deeplabv3_mobilenet_v2_{depth_multiplier}_{resolution},例如 google/deeplabv3_mobilenet_v2_1.0_513:它把 MobileNetV2 作为骨干,接上 DeepLabV3+ 语义分割头,通常在 PASCAL VOC 一类数据集上预训练。

几个必须了解的细节:

  • 预训练与分类数不一致:MobileNetV2 在 ImageNet-1k(1000 类)上预训练,但模型实际输出 1001 类——多出的一个类别是索引为 0 的额外"背景"类。集成测试中断言 logits 形状 (1, 1001) 印证了这一点。
  • 分辨率弹性:虽然权重在固定尺寸(如 224 或 513)上训练,但模型结构本身可处理最小 32×32 以上任意尺寸的输入,预处理由 MobileNetV2ImageProcessor 负责。
  • 分割模型测试尺寸:对 deeplabv3_mobilenet_v2_1.0_513,测试验证输出 logits 形状为 (1, 21, 65, 65)(21 对应 PASCAL VOC 类别数),见 test_modeling_mobilenet_v2.py

四、MobileNetV2Config 全参数详解

配置类定义于 configuration_mobilenet_v2.py。下表汇总全部默认值与其作用:

参数 默认值 说明
num_channels 3 输入图像通道数(RGB)
image_size 224 训练图像尺寸,可为 int 或 (h, w) 元组
depth_multiplier 1.0 深度乘子,按比例缩放各层通道数(校验:必须大于 0)
depth_divisible_by 8 每层通道数始终是该值的整数倍
min_depth 8 所有层至少保留这么多通道
expand_ratio 6.0 倒残差块内首层输出通道 = 输入通道 × 该系数
output_stride 32 输入与输出特征图空间分辨率之比;设为 8 或 16 时深度层改用空洞卷积,使特征图降采样不超过 8×/16×
first_layer_is_expansion True 首个卷积层是否同时充当第一个扩张块的扩张层
finegrained_output True 为 True 时,即使 depth_multiplier < 1,最终卷积层输出仍保持 1280 通道
hidden_act "relu6" 隐藏层激活函数,MobileNetV2 使用 ReLU6
tf_padding True 卷积层是否采用 TensorFlow 的 SAME padding 规则
classifier_dropout_prob 0.8 分类头 Dropout 概率(语义分割头用作 Dropout2d
initializer_range 0.02 参数初始化范围
layer_norm_eps 0.001 BatchNorm 的 eps(命名沿用了通用字段)
semantic_loss_ignore_index 255 语义分割损失中忽略的标签索引

两个需要特别留意的参数

(1)tf_padding——TensorFlow 原生 padding 行为

由于原始 TensorFlow checkpoint 的 padding 量取决于推理时的输入图像尺寸,Transformers 实现默认(tf_padding=True)在推理期动态计算 SAME 式 padding(见 apply_tf_padding),以复现原始数值行为;若希望使用原生 PyTorch 的显式 padding,则需在加载时显式关闭:

from transformers import MobileNetV2Config

config = MobileNetV2Config.from_pretrained("google/mobilenet_v2_1.4_224", tf_padding=True)

对应地,在 MobileNetV2ConvLayer 中(modeling_mobilenet_v2.py):padding = 0 if config.tf_padding else int((kernel_size - 1) / 2) * dilation,即开启 TF padding 时把 padding 交给前向中的 apply_tf_padding 动态计算。

(2)output_stride——空洞卷积控制特征图分辨率

MobileNetV2Model 的构建循环中(modeling_mobilenet_v2.py),当累计下采样倍数 current_stride == config.output_stride 后,后续 depthwise 层不再继续降采样,而是逐步增大空洞率 dilation 以维持感受野——这正是语义分割模型(如 DeepLabV3+ 骨干)能输出高分辨率特征图的原因。

五、三个模型入口类与输出约定

同一骨干对应三个公开入口(全部导出自 modeling_mobilenet_v2.py):

5.1 MobileNetV2Model

纯骨干网络,输出 BaseModelOutputWithPoolingAndNoAttention,包含 last_hidden_statepooler_output 与可选 hidden_states。骨干按论文给出通道表 [16, 24, 24, 32, 32, 32, 64, 64, 64, 64, 96, 96, 96, 160, 160, 160, 320](再经 depth_multiplier 缩放)逐层搭建 16 个倒残差块,最终接 1×1 卷积(输出由 finegrained_output 决定是否为 1280)与 AdaptiveAvgPool2d((1, 1)) 全局池化(modeling_mobilenet_v2.py)。注意:Transformers 实现使用全局平均池化取代原版可选的 7×7 stride=2 池化——对大输入,这会使池化输出大于 1×1 像素,这是文档明确列出的已知差异。

5.2 MobileNetV2ForImageClassification

在骨干之上加 Dropout + Linear 分类头。源码从 conv_1x1out_channels 动态获取分类输入维度(modeling_mobilenet_v2.py)。训练时可传入 labels(形状 (batch_size,)):num_labels==1 时计算 MSE 回归损失,否则计算交叉熵损失。

5.3 MobileNetV2ForSemanticSegmentation

内部以 add_pooling_layer=False 实例化骨干(分割不需要全局池化),再接 MobileNetV2DeepLabV3Plus 分割头。DeepLabV3+ 头在 modeling_mobilenet_v2.py 实现为:对最高层特征做 AdaptiveAvgPool2d(1) 后经 1×1 卷积并双线性上采样回原尺寸,与另一路 1×1 卷积(ASPP 简化版)结果拼接,再经投影卷积、Dropout2d 与 1×1 分类卷积输出 (batch, num_labels, h, w) 的 logits。训练时在标签尺寸上双线性插值后以 ignore_index=semantic_loss_ignore_index(默认 255)计算交叉熵。前向会强制 output_hidden_states=True 取骨干最终层特征(modeling_mobilenet_v2.py)。

六、图像预处理与后处理:MobileNetV2ImageProcessor 全解析

MobileNetV2 的图像处理器有 Torchvision 后端版PIL 后端版两个实现,均位于 models/mobilenet_v2 目录下,由仓库后端机制按环境自动选用,公开 API 相同。

6.1 默认预处理流水线

两个处理器类的默认行为完全一致(见 image_processing_mobilenet_v2.py):

阶段开关 默认值 含义
do_resize True 将短边缩放到 size={"shortest_edge": 256}
do_center_crop True 中心裁剪到 crop_size={"height": 224, "width": 224}
do_rescale True 像素值缩放到 [0, 1](因子 1/255
do_normalize True 使用 ImageNet 标准均值/方差归一化(IMAGENET_STANDARD_MEAN/IMAGENET_STANDARD_STD
resample BILINEAR 缩放插值方式
do_reduce_labels False 是否对分割标签执行标签减一

也就是说,默认输入的 224 分辨率正是在"短边 256 缩放 + 中心 224×224 裁剪"后得到的,这与训练期数据增强协议一致。

6.2 分割标签专用处理

preprocess 额外支持传入 segmentation_maps。对标签图的处理会强制关闭归一化与缩放、改用 NEAREST 最近邻插值(避免类别值被插值污染),并在处理后 squeeze 通道维并转为 int64/np.int64(见 image_processing_mobilenet_v2.py)。

针对如 ADE20k 这类"背景 0 不计入类别"的数据集,还提供 do_reduce_labels=True 选项:reduce_label 会将标签值为 0 的先替换为 255,再整体减一,使背景类被统一为 255(即损失中默认忽略的索引),实现见 reduce_label

6.3 分割结果后处理

post_process_semantic_segmentation(outputs, target_sizes=None, return_segmentation_scores=False) 把模型 logits 转成分割图:

  • 传入 target_sizes=[(h, w), ...] 时,会先把各样本 logits 双线性插值到目标尺寸,再沿类别维 argmax 得到类别 ID 图;
  • return_segmentation_scores=True 时返回每个类别置信度(形状 (num_classes, h, w)),同时可读取 segmentation 字段获得类别图。

完整的分割推理示例可参考 MobileNetV2ForSemanticSegmentation.forward 文档字符串中给出的代码(modeling_mobilenet_v2.py),它展示了用 AutoImageProcessor + google/deeplabv3_mobilenet_v2_1.0_513 获取 outputs.logits 的标准流程。

七、从 TF 权重到 PyTorch:官方转换脚本

仓库自带转换脚本 convert_original_tf_checkpoint_to_pytorch.py,用于将 tensorflow/models 官方库的 MobileNetV2 权重转换为 Transformers 格式。从源码(L40-L120)可看到其核心逻辑:

  • 建立 TF 变量名(如 MobilenetV2/expanded_conv_N/expand/weightsBatchNorm/beta|gamma|moving_mean|moving_variance)与 PyTorch 模块的逐层映射;
  • 自动优先使用 TF 中的 ExponentialMovingAverage(EMA)权重;
  • 按模型类型分别处理分类头(MobilenetV2/Logits/Conv2d_1c_1x1)与分割头(image_pooling/ 等 DeepLabV3+ 部分)的权重。

八、使用边界:当前实现明确不支持的能力

文档"Notes"一节给出了本仓库实现与原始论文/TF 版的功能差异,引用源码可逐一印证,使用前务必知悉:

  1. 全局平均池化替代 7×7 池化:如 5.1 节所述,骨干固定使用 AdaptiveAvgPool2d((1, 1))
  2. output_hidden_states=True 只返回全部中间层:从 forward 实现 可见,隐藏状态以元组形式累积所有层的输出,无法仅抽取特定中间层供下游任务使用(语义分割之所以能工作,正是因为它消费的就是"全部中间状态"里最后一层)。
  3. 不含量化模型:原始 checkpoint 中的量化版本因包含 FakeQuantization(伪量化反量化)操作而未被纳入。
  4. 分割骨干存在冗余计算:DeepLabV3+ 头并不使用骨干的最终卷积层输出,但前向仍会完整计算该层。

此外,MobileNetV2PreTrainedModel 明确声明 supports_gradient_checkpointing = False_no_split_modules = [](见 modeling_mobilenet_v2.py),即该模型不支持梯度检查点,做超大 batch 显存优化时需注意此限制。

九、快速自检与工程化建议

最后给出三条工程实践建议,帮助你在项目中正确选用 MobileNetV2:

  1. 按任务选 checkpoint 而非改头训练:图像分类直接用 mobilenet_v2_{乘子}_{分辨率}(如 1.4_224,越大精度越高、计算量越大);需要像素级理解(如车道线、物体轮廓)再选 deeplabv3_mobilenet_v2_1.0_513,其头结构与训练数据面向 PASCAL VOC 风格任务。
  2. 与 TF 生态对齐数值行为:若你的输入会因尺寸变化触发动态 padding,请保留默认 tf_padding=True;只有当你明确要用原生 PyTorch padding 语义并对齐数值精度时,才在 from_pretrained 时通过 MobileNetV2Config(tf_padding=False) 覆盖。
  3. 充分利用测试作为"可运行规范":仓库的 MobileNetV2ModelIntegrationTest./tests/fixtures/tests_samples/COCO/000000039769.png 这张猫咪图片验证了分类 logits 形状 (1, 1001)、分割 logits 形状 (1, 21, 65, 65) 与数值精度(rtol=2e-4),可作为你本地复现推理、核对输出形状的现成参照。

以上所有源码证据均可在当前仓库的 src/transformers/models/mobilenet_v2/tests/models/mobilenet_v2/ 目录下找到,按文中给出的行号即可快速定位验证。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388