TensorFlow Slim 中的 MobileNet 系列模型指南:V2/V3/EdgeTPU 的架构定义、性能与 ImageNet 预训练模型
【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models
MobileNet 系列是面向移动端与边缘设备的轻量级卷积网络,本指南以 TensorFlow 仓库中 research/slim/nets/mobilenet/README.md 为主线,完整梳理 Slim 提供的 MobileNetV2、MobileNetV3 与专为 Google Pixel 4 Edge TPU 定制的 MobileNetEdgeTPU 模型:包括架构定义所在源码、各变体的 MACs/参数量/精度/延迟数据、ImageNet 预训练检查点清单,以及可在 Slim 框架下复现的训练超参配置。读完本文,你将掌握如何在该仓库中定位、加载、评估与重训不同 MobileNet 变体,并理解其设计取舍。
目录结构与代码定位
research/slim/nets/mobilenet/目录集中存放了 MobileNetV2/V3 与 MobileNetEdgeTPU 的构建代码,主要文件如下:
| 文件 | 职责 |
|---|---|
| mobilenet.py | 所有 MobileNet 共享的基类与通用机制(深度乘子、arg_scope、训练配置) |
| mobilenet_v2.py | MobileNetV2 网络结构定义(基于 Inverted Residual Block) |
| mobilenet_v3.py | MobileNetV3(Large/Small/Minimalistic)与 MobileNetEdgeTPU 定义 |
| conv_blocks.py | 卷积基础算子:expanded_conv、squeeze-excite 等核心模块 |
| mobilenet_v2_test.py、mobilenet_v3_test.py | 对应网络的单元测试 |
| mobilenet_example.ipynb | 端到端示例 notebook |
| g3doc/ | README 引用的延迟与精度对比图 |
关于版本归属需要区分清楚:MobileNetV1的构建代码与预训练模型清单并不在本目录,而是位于 mobilenet_v1.md 及其同级的 mobilenet_v1.py,V1 之后(V2 及以上)的文档才收敛到本文对应的 mobilenet/README.md。两个文档互相指引,构成完整的 MobileNet 文档链。
架构定义的源码级解读
MobileNetV2:由 V2_DEF 描述的倒残差结构
MobileNetV2 的完整结构以数据字典V2_DEF形式直接定义在 mobilenet_v2.py 中,分为defaults与spec两部分:
defaults:批量归一化启用center/scale,标准卷积、全连接与深度可分离卷积统一使用slim.batch_norm作归一化、tf.nn.relu6作激活;expanded_conv默认扩张系数 6、启用残差连接、SAME 填充。spec:按顺序列出每一层,首层为 stride=2 的 3x3 标准卷积输出 32 通道,其后是 17 个expanded_conv模块(即 Inverted Residual Block,含中间 1x1 升维扩张、3x3 深度卷积、1x1 投影降维与残差相加),通道数沿 16→24→32→64→96→160→320 逐阶段扩张,最终接 1x1 卷积输出 1280 维嵌入。
该文件还提供三类入口:
mobilenet(input_tensor, num_classes=1001, depth_multiplier=1.0, ...):完整分类网络,default_image_size = 224(mobilenet_v2.py)。finegrain_classification_mode=True时在depth_multiplier < 1下仍保持最后一层大通道,符合原论文对 ImageNet 类任务的建议。mobilenet_base(...):仅构建主干(base_only=True,不含池化与 logits),便于作为检测/分割等下游任务的 backbone 复用。mobilenet_v2_140/050/035:通过wrapped_partial预绑定深度乘子的便捷变体;另提供使用 Group Norm 的mobilenet_base_group_norm版本。
MobileNetV3 与 EdgeTPU:V3_LARGE/V3_SMALL/V3_EDGETPU
MobileNetV3 定义在 mobilenet_v3.py 中,通过V3_LARGE(L473)、V3_SMALL(L532)等数据字典描述。其设计要素反映在辅助函数上:
mbv3_op(ef, n, k, s, act, se):生成一个 bottleneck 层;se指定是否插入 squeeze-and-excite 模块(_se4为 4 通道全连接版本),早期层用 ReLU,深部层用hard_swish。hard_swish(L380):即 ReLU6 变体的分段线性近似,部署友好。reduce_to_1x1:用 7x7 自适应均值池化把特征图压到 1x1,再接末层卷积。
V3_LARGE_MINIMALISTIC、V3_SMALL_MINIMALISTIC是论文之外的实验变体:它们保持与 V3 相同逐层维度,但不使用squeeze-and-excite、hard-swish 与 5x5 卷积等高级模块,因此在 CPU 上效率略低,却在 GPU/DSP 上明显更友好(详见下文 checkpoint 表格)。
针对 Edge TPU 加速器(内置在 Google Pixel 4 设备中),仓库提供了MobileNetEdgeTPU,架构定义同样位于 mobilenet_v3.py,对应V3_EDGETPU(L585):其在浅层用 fused 卷积替代深度可分离卷积以减少 depthwise 算子、降低 int8 量化误差,深部继续堆叠大通道的 expanded_conv。模块级入口large / small / edge_tpu / edge_tpu_075 / large_minimalistic / small_minimalistic集中在文件末尾(L712)。
三个版本共享的基础设施(mobilenet.py)
所有 MobileNet 都复用 mobilenet.py 的通用机制:
mobilenet_base(inputs, conv_defs, multiplier, ...):逐条执行conv_defs['spec']中的算子并记录end_points(命名形如layer_N);支持output_stride自动切换到 atrous(空洞)卷积以控制空间分辨率(典型值 8/16/32),支持use_explicit_padding用 VALID 填充配合显式 prepad 以获得与 SAME 一致的空间尺寸(见 _fixed_padding)。depth_multiplier(L96)与_make_divisible(L62):实现深度乘子缩放,同时把通道数对齐到divisible_by=8、min_depth=8,以保证硬件友好的通道划分;这是 checkpoint 命名中 dm 参数的实际含义。mobilenet(...):在主干之上追加global_pool、Dropout 与Conv2d_1c_1x1得到 logits,默认 softmax 输出,返回(logits, end_points);num_classes=0时省略 logits 层直接返回嵌入。training_scope(is_training, weight_decay, stddev, dropout_keep_prob, bn_decay)(L435):统一设置 BN 的 decay/is_training、权重初始化(stddev为负则退化为 xavier)、dropout keep 概率与卷积权重的 L2 正则。V2/V3 均直接复用(training_scope = lib.training_scope)。
性能指标:延迟、MACs 与精度权衡
Pixel 1 上的 V2/V3 延迟
下图给出 MobileNetV2 与 MobileNetV3 在 Pixel 1 手机大核上通过 TF-Lite 运行的耗时对比(数值见文末 checkpoint 表格中的 "Mobile CPU (ms) Pixel 1" 列):
MACs:衡量模型效率的核心指标
MACs(Multiply-Accumulates,也常称 MADDs)指对单张图片做一次推理所需的乘加操作总数,是衡量模型计算效率的常用指标。README 给出的对标数据:
- 全尺寸 MobileNetV3(224 输入)约215 MMadds,ImageNet Top-1 约75.1%;
- MobileNetV2 约300 MMadds,Top-1 约72%;
- 作为参照,ResNet-50 约3500 MMadds,Top-1 约76%。
下图横向比较了 MobileNet 系列与若干其他网络的 MACs 与 Top-1 精度(图中每个气泡大小代表参数量)。其中 ShuffleNet 没有官方公开的体积数字,文档估计其与 MobileNetV2 相当:
Pixel 4 Edge TPU 延迟
下图给出 int8 量化后的 MobileNetEdgeTPU 与 MobileNetV2、以及 minimalistic 系列在 Pixel 4 Edge TPU 上的延迟对比(对应数值见 Edge TPU checkpoint 表):
ImageNet 预训练模型清单
MobileNetV3 检查点(224x224 训练)
所有 V3 检查点均以 224x224 分辨率训练;表格中手机延迟单位为毫秒,均在手机大核上测得。除常规 large/small 外,还包括minimalistic模型(无 SE、hard-swish 与 5x5 卷积的降级版)。检查点命名遵循v3-{large|small}[-minimalistic]_{input}_{dm}_{float|uint8}规则,例如 224 输入、dm=1.0 的 float 版即v3-large_224_1.0_float。
| 模型(float 精度) | MACs (M) | Params (M) | Top1 | Pixel 1 | Pixel 2 | Pixel 3 |
|---|---|---|---|---|---|---|
| Large dm=1.0 (float) | 217 | 5.4 | 75.2 | 51.2 | 61 | 44 |
| Large dm=1.0 (8-bit) | 217 | 5.4 | 73.9 | 44 | 42.5 | 32 |
| Large dm=0.75 (float) | 155 | 4.0 | 73.3 | 39.8 | 48 | 34 |
| Small dm=1.0 (float) | 66 | 2.9 | 67.5 | 15.8 | 19.4 | 14.4 |
| Small dm=1.0 (8-bit) | 66 | 2.9 | 64.9 | 15.5 | 15 | 10.7 |
| Small dm=0.75 (float) | 44 | 2.4 | 65.4 | 12.8 | 15.9 | 11.6 |
Minimalistic 检查点:
| 模型 | MACs (M) | Params (M) | Top1 | Pixel 1 | Pixel 2 | Pixel 3 |
|---|---|---|---|---|---|---|
| Large minimalistic (float) | 209 | 3.9 | 72.3 | 44.1 | 51 | 35 |
| Large minimalistic (8-bit) | 209 | 3.9 | 71.3 | 37 | 35 | 27 |
| Small minimalistic (float) | 65 | 2.0 | 61.9 | 12.2 | 15.1 | 11 |
Edge TPU 检查点:
| 模型 | MACs (M) | Params (M) | Top1 | Pixel 4 Edge TPU | Pixel 4 CPU |
|---|---|---|---|---|---|
| MobileNetEdgeTPU dm=0.75 (8-bit) | 624 | 2.9 | 73.5 | 3.1 | 13.8 |
| MobileNetEdgeTPU dm=1.0 (8-bit) | 990 | 4.0 | 75.6 | 3.6 | 20.6 |
注意:MobileNetEdgeTPU 的 8-bit 量化版是使用 TensorFlow Lite 的post training quantization(训练后量化)工具得到的——仓库 nets/post_training_quantization.py 也提供了对应脚本。这一事实与V3_EDGETPU浅层采用 fused 卷积的设计呼应:深度可分离卷积逐通道计算的性质与常见 int8 量化权重缩放并不完全匹配,fused 结构可在量化后显著降低精度损失。
MobileNetV2 检查点
MobileNetV2 检查点命名规则为mobilenet_v2_{dm}_{input}(float 版)与quantized_v2_{input}_{dm*100}(uint8 版)。全部在同一数据集(ILSVRC-2012-CLS)上训练,精度为单中心裁剪评估;"Mobile CPU (ms) Pixel 1" 为 Pixel 1 大核延迟。
| float 模型 | uint8 模型 | MACs (M) | Params (M) | Top1 | Top5 | CPU (ms) |
|---|---|---|---|---|---|---|
| float_v2_1.4_224 | uint8 版 | 582 | 6.06 | 75.0 | 92.5 | 138.0 |
| float_v2_1.3_224 | uint8 版 | 509 | 5.34 | 74.4 | 92.1 | 123.0 |
| float_v2_1.0_224 | uint8 版 | 300 | 3.47 | 71.8 | 91.0 | 73.8 |
| float_v2_1.0_192 | uint8 版 | 221 | 3.47 | 70.7 | 90.1 | 55.1 |
| float_v2_1.0_160 | uint8 版 | 154 | 3.47 | 68.8 | 89.0 | 40.2 |
| float_v2_1.0_128 | uint8 版 | 99 | 3.47 | 65.3 | 86.9 | 27.6 |
| float_v2_1.0_96 | uint8 版 | 56 | 3.47 | 60.3 | 83.2 | 17.6 |
| float_v2_0.75_224 | uint8 版 | 209 | 2.61 | 69.8 | 89.6 | 55.8 |
| float_v2_0.75_192 | uint8 版 | 153 | 2.61 | 68.7 | 88.9 | 41.6 |
| float_v2_0.75_160 | uint8 版 | 107 | 2.61 | 66.4 | 87.3 | 30.4 |
| float_v2_0.75_128 | uint8 版 | 69 | 2.61 | 63.2 | 85.3 | 21.9 |
| float_v2_0.75_96 | uint8 版 | 39 | 2.61 | 58.8 | 81.6 | 14.2 |
| float_v2_0.5_224 | uint8 版 | 97 | 1.95 | 65.4 | 86.4 | 28.7 |
| float_v2_0.5_192 | uint8 版 | 71 | 1.95 | 63.9 | 85.4 | 21.1 |
| float_v2_0.5_160 | uint8 版 | 50 | 1.95 | 61.0 | 83.2 | 14.9 |
| float_v2_0.5_128 | uint8 版 | 32 | 1.95 | 57.7 | 80.8 | 9.9 |
| float_v2_0.5_96 | uint8 版 | 18 | 1.95 | 51.2 | 75.8 | 6.4 |
| float_v2_0.35_224 | uint8 版 | 59 | 1.66 | 60.3 | 82.9 | 19.7 |
| float_v2_0.35_192 | uint8 版 | 43 | 1.66 | 58.2 | 81.2 | 14.6 |
| float_v2_0.35_160 | uint8 版 | 30 | 1.66 | 55.7 | 79.1 | 10.5 |
| float_v2_0.35_128 | uint8 版 | 20 | 1.66 | 50.8 | 75.0 | 6.9 |
| float_v2_0.35_96 | uint8 版 | 11 | 1.66 | 45.5 | 70.4 | 4.5 |
观察数据可得到三条选型规律:其一,V2 提供从 1.4 到 0.35 共 6 档depth_multiplier与 224/192/160/128/96 共 5 档输入分辨率,二者组合出 22 个检查点,便于按延迟/精度预算精细选型;其二,参数量只随 dm 变化、与输入分辨率无关(同一 dm 下 Params 恒定),分辨率只线性影响 MACs;其三,uint8 量化在几乎不损失 Top-1 的前提下显著降低延迟。这些数字与源码中depth_multiplier逐层缩放num_outputs、global_pool前特征维度保持不变的实现一一对应。
训练配置复现
V3:8 GPU / 2x2 TPU 复现配置
README 给出如下超参配置,可在8 GPU上复现 74.6% Top-1、在2x2 TPU上复现 75.2% Top-1:
| 超参 | 值 | 说明 |
|---|---|---|
| learning_rate | 0.16 | 总学习率(每 replica 实际 0.02) |
| optimizer | RMSProp | 与 MobileNetV2 训练一致的优化器 |
| rmsprop_momentum | 0.9 | |
| rmsprop_decay | 0.9 | |
| rmsprop_epsilon | 0.002 | |
| learning_rate_decay_factor | 0.99 | |
| warmup_epochs | 5 | Slim 按每 clone 计 epoch,因此 flag 填 0.6 |
| num_epochs_per_decay | 3 | Slim 按每 clone 计 epoch,因此 flag 填 0.375 |
| batch_size (per chip) | 192 | 每块芯片的 batch |
| moving_average_decay | 0.9999 | 参数滑动平均衰减 |
| weight_decay | 1e-5 | L2 正则系数 |
| init_stddev | 0.008 | 权重初始化标准差 |
| dropout_keep_prob | 0.8 | dropout 保留概率 |
| bn_moving_average_decay | 0.997 | BN 均值/方差滑动平均衰减 |
| bn_epsilon | 0.001 | BN 数值稳定项 |
| label_smoothing | 0.1 | 标签平滑系数 |
其中 0.6 与 0.375 两个 "折算值" 的提示很关键:Slim 的train_image_classifier在内部对多 GPU clone 做梯度平均并按单 clone 统计 epoch,因此传给 flag 的 epoch 数需要除以 clone(GPU)数。源码侧,training_scope(mobilenet.py)默认weight_decay=0.00004、bn_decay=0.997、dropout_keep_prob=0.8、stddev=0.09,其中 BN decay 0.997 与上表一致,说明表中的 bn 参数正是通过该 scope 注入网络构建过程的。
V2:train_image_classifier 命令参数
MobileNetV2 的上述精度可用 Slim 的train_image_classifier(入口见 research/slim)从头复现。全尺寸 MobileNetV2 在8 GPU上约 70 万步收敛到 72.0%(若用单卡则需要约 550 万步)。同样因 Slim 内部对克隆做平均,学习率与num_epochs_per_decay必须随 GPU 数量调整:
--model_name="mobilenet_v2" --learning_rate=0.045 * NUM_GPUS # slim 内部对 clones 求平均,因此需补偿 --preprocessing_name="inception_v2" --label_smoothing=0.1 --moving_average_decay=0.9999 --batch_size=96 --num_clones=NUM_GPUS # 依据硬件在 1~8 之间取值 --learning_rate_decay_factor=0.98 --num_epochs_per_decay=2.5 / NUM_GPUS # train_image_classifier 按每 clone 计 epoch注意--model_name需要与 nets_factory.py 中注册的名称一致;从源码看mobilenet_v2模块把mobilenet.default_image_size设为 224,且预训练表即按 224 分辨率给出,这正是--model_name与预处理分辨率对得上号的原因。
快速上手的 Example
仓库提供了可直接运行的示例 notebook:mobilenet_example.ipynb。其典型流程包括:
- 在
slim.arg_scope(mobilenet_v3.training_scope())(推理时可省略)下调用mobilenet_v3.large(...)或small(...)、edge_tpu(...)构建网络; - 通过返回的
end_points(如global_pool、Logits、Predictions)查看各层特征与输出; - 传入 224x224 输入做一次前向推理,观察
num_classes=1001的 logits 输出与 softmax 预测。
结合源码约定,最小可运行的推理代码形如:
import tensorflow.compat.v1 as tf tf.disable_v2_behavior() import tf_slim as slim from nets.mobilenet import mobilenet_v2 # 或 mobilenet_v3 inputs = tf.placeholder(tf.float32, [1, 224, 224, 3]) logits, end_points = mobilenet_v2.mobilenet(inputs, num_classes=1001) # end_points 含 global_pool / Logits / Predictions 等若只想要可供下游检测/分割任务复用、不含 logits 的主干,可改用mobilenet_v2.mobilenet_base(...)(等价于base_only=True);将输出特征图传入分割头时可配合output_stride(8/16/32)控制空间下采样倍率。这些用法都建立在 mobilenet.py 的mobilenet_base对conv_defs的解释执行之上——架构即数据,扩展新变体只需新增一个conv_defs字典。
小结
在 TensorFlow 仓库的 Slim 生态中,MobileNet 演进链路(V1 → V2 → V3 → EdgeTPU)被统一收纳进 nets/mobilenet/README.md 及各.py定义文件。选型时可按本文表格先看 MACs/Params/Top-1 权衡,再对照 Pixel 1 / Pixel 4 Edge TPU 延迟列确认设备约束;训练复现则参考 V3 超参表或 V2 的train_image_classifier命令行,关键都是要理解 Slim 按 clone 平均梯度导致的 epoch 与学习率折算规则。所有模型的网络定义均以conv_defs数据字典承载,同一个 mobilenet.py 引擎即可驱动全部变体,这也是该目录在工程上易于扩展、测试充分(见两个*_test.py)的根本原因。
【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考