MMPose 中 ShuffleNetV1 人体姿态估计:MPII 数据集 Top-down 热图基线的完整解析
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
本篇基于 MMPose 模型库文档 shufflenetv1_mpii.md,围绕 ShuffleNetV1 骨干网络在 MPII 数据集上的 Top-down 热图姿态估计基线展开,完整解读其训练配置、骨干网络实现、热图编解码与 PCKh 评测指标,帮助读者掌握一个轻量级姿态估计模型的配置逻辑、复现方式与源码级实现细节。
模型背景与评测结果
ShuffleNetV1 是一种面向移动端设备设计的极轻量卷积网络,其核心思想是通过分组 1x1 卷积压缩通道、深度可分离卷积提取空间信息,并用 channel shuffle 在分组间传递信息以降低计算量。原始论文发表于 CVPR 2018:
@inproceedings{zhang2018shufflenet, title={Shufflenet: An extremely efficient convolutional neural network for mobile devices}, author={Zhang, Xiangyu and Zhou, Xinyu and Lin, Mengxiao and Sun, Jian}, booktitle={Proceedings of the IEEE conference on computer vision and pattern recognition}, pages={6848--6856}, year={2018} }MPII(Human3.6M)数据集是 2D 人体姿态估计的经典基准,来自 CVPR 2014 论文《2D Human Pose Estimation: New Benchmark and State of the Art Analysis》:
@inproceedings{andriluka14cvpr, author = {Mykhaylo Andriluka and Leonid Pishchulin and Peter Gehler and Schiele, Bernt}, title = {2D Human Pose Estimation: New Benchmark and State of the Art Analysis}, booktitle = {IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, year = {2014}, month = {June} }该基线模型在 MPII val 集上的评测结果为:
| 架构 | 输入尺寸 | Mean (PCKh@0.5) | Mean@0.1 (PCKh@0.1) | 配置 |
|---|---|---|---|---|
| pose_shufflenetv1 | 256x256 | 0.824 | 0.195 | td-hm_shufflenetv1_8xb64-210e_mpii-256x256.py |
其中 "Mean" 表示 PCKh@0.5 指标(以头部尺寸归一化、阈值为 0.5 的 PCK 准确率),"Mean@0.1" 为更严格的 PCKh@0.1。这两个数值与模型元数据文件 shufflenetv1_mpii.yml 中记录的Mean: 0.824、Mean@0.1: 0.195一致。
在 Top-down 热图模型汇总 的 MPII 榜单中,ShuffleNet-v1(0.824 / 0.195)与 ShuffleNet-v2(0.828 / 0.205)、MobileNet-v2(0.854 / 0.234)、LiteHRNet(0.859~0.869)等轻量骨干处于同一梯队,明显低于 HRNet、ResNet 等大模型,体现了其作为轻量级模型的定位:以较低精度换取更少的参数量与计算量,适合端侧或对速度敏感的场景。
Top-down 方法将姿态估计分为两阶段:先由目标检测器给出人体框,再对每个人体框单独估计姿态。姿态估计器不直接回归关键点坐标,而是输出表示关键点位置概率的热图(heatmap),这一范式源自《Simple Baselines for Human Pose Estimation and Tracking》(ECCV 2018),MMPose 将其实现为TopdownPoseEstimator架构。
训练配置详解
配置文件 td-hm_shufflenetv1_8xb64-210e_mpii-256x256.py 继承自 default_runtime.py,命名8xb64-210e即表示 8 卡 × 每卡 batch size 64、共训练 210 个 epoch。下面按模块逐一解析。
训练策略与学习率
train_cfg = dict(max_epochs=210, val_interval=10) optim_wrapper = dict( type='OptimWrapper', optimizer=dict(type='Adam', lr=5e-4)) param_scheduler = [ dict(type='LinearLR', begin=0, end=500, start_factor=0.001, by_epoch=False), # 前 500 次迭代线性 warmup dict(type='MultiStepLR', begin=0, end=210, milestones=[170, 200], gamma=0.1, by_epoch=True) # 第 170、200 个 epoch 学习率乘以 0.1 ] auto_scale_lr = dict(base_batch_size=512) default_hooks = dict(checkpoint=dict(save_best='PCK', rule='greater'))- 优化器为 Adam,初始学习率 5e-4;
- 前 500 个迭代(而非 epoch)做线性 warmup,从 0.001 倍基础学习率升至 1 倍;
- 之后在第 170、200 个 epoch 将学习率各衰减 10 倍,这与 210 个 epoch 的总长匹配,属于典型的"后期小学习率精调"策略;
auto_scale_lr以 512(8×64)为基准 batch size 线性缩放学习率,因此换用其他卡数或 batch size 复现时学习率会自动调整;- 每 10 个 epoch 验证一次(
val_interval=10),并按验证集 PCK 指标保存最优 checkpoint(save_best='PCK', rule='greater')。
热图编解码(Codec)
codec = dict( type='MSRAHeatmap', input_size=(256, 256), heatmap_size=(64, 64), sigma=2)MSRAHeatmap是 SimpleBaseline 范式的标准编解码器,其实现位于 msra_heatmap.py:
- 输入图像为 256×256,关键点坐标先按
input_size / heatmap_size的比例因子缩放到 64×64 的热图空间; - 编码(
encode)时以每个关键点为中心生成高斯热图,sigma=2控制热图扩散半径,同时输出keypoint_weights(仅可见关键点参与监督);该 codec 仅支持单实例编码(encode中assert keypoints.shape[0] == 1),符合 Top-down 范式"一个输入框对应一个人"的前提; - 解码(
decode)时通过热图最大值定位关键点(get_heatmap_maximum),将热图空间坐标还原回输入图像空间,输出 (N, K, D) 形状的关键点坐标与置信度。
sigma=2是 256 输入尺度下 SimpleBaseline 系列的常用取值;若改用 DarkPose 风格的无偏编码,可设unbiased=True并配合blur_kernel_size(源码注释给出经验公式:ks=11 对应 sigma≈2)。
模型结构
model = dict( type='TopdownPoseEstimator', data_preprocessor=dict( type='PoseDataPreprocessor', mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], bgr_to_rgb=True), backbone=dict( type='ShuffleNetV1', groups=3, init_cfg=dict(type='Pretrained', checkpoint='mmcls://shufflenet_v1')), head=dict( type='HeatmapHead', in_channels=960, out_channels=16, loss=dict(type='KeypointMSELoss', use_target_weight=True), decoder=codec), test_cfg=dict( flip_test=True, flip_mode='heatmap', shift_heatmap=True))各部分含义:
- data_preprocessor:使用 ImageNet 标准均值/方差归一化,并将 BGR 转为 RGB;
- backbone:
ShuffleNetV1的groups=3表示 1x1 分组卷积的分组数,init_cfg通过mmcls://shufflenet_v1加载 MMClassification 模型库中的 ImageNet 预训练权重(分类预训练权重用于迁移,姿态任务从头微调); - head:
HeatmapHead(实现见 heatmap_head.py)直接以一个卷积层将骨干输出的 960 通道特征映射为 16 通道热图(MPII 的 16 个关键点),损失函数KeypointMSELoss且use_target_weight=True,即按 codec 输出的keypoint_weights只对可见关键点计算 MSE; - test_cfg:测试时启用翻转增强——对水平翻转后的图像分别预测,按
flip_mode='heatmap'在热图层面取平均,shift_heatmap=True会对翻转热图做 +1 像素的水平平移校正,缓解左右不对称关键点(如左右手肘)的翻转误差。
数据集与数据流
dataset_type = 'MpiiDataset' data_mode = 'topdown' data_root = 'data/mpii/' train_pipeline = [ dict(type='LoadImage'), dict(type='GetBBoxCenterScale'), dict(type='RandomFlip', direction='horizontal'), dict(type='RandomBBoxTransform', shift_prob=0), dict(type='TopdownAffine', input_size=codec['input_size']), dict(type='GenerateTarget', encoder=codec), dict(type='PackPoseInputs')] train_dataloader = dict( batch_size=64, num_workers=2, persistent_workers=True, sampler=dict(type='DefaultSampler', shuffle=True), dataset=dict( type=dataset_type, data_root=data_root, data_mode=data_mode, ann_file='annotations/mpii_train.json', data_prefix=dict(img='images/'), pipeline=train_pipeline)) val_dataloader = dict( batch_size=32, num_workers=2, persistent_workers=True, drop_last=False, sampler=dict(type='DefaultSampler', shuffle=False, round_up=False), dataset=dict( type=dataset_type, data_root=data_root, data_mode=data_mode, ann_file='annotations/mpii_val.json', headbox_file='data/mpii/annotations/mpii_gt_val.mat', data_prefix=dict(img='images/'), test_mode=True, pipeline=val_pipeline)) val_evaluator = dict(type='MpiiPCKAccuracy') test_evaluator = val_evaluator关键点:
GetBBoxCenterScale从预存的人体检测框计算中心与尺度,TopdownAffine据此将人体裁剪并仿射变换到 256×256,GenerateTarget调用 codec 生成高斯热图标签;- 训练集使用
annotations/mpii_train.json,验证集使用annotations/mpii_val.json; - 验证集额外指定
headbox_file='data/mpii/annotations/mpii_gt_val.mat',这是 MPII 官方提供的头部框文件,用于 PCKh 指标中以头部尺寸归一化误差; - 数据集目录约定为
data/mpii/,需包含images/与annotations/子目录,具体的下载与组织方式可参考 数据集准备指南。
ShuffleNetV1 骨干的源码实现
MMPose 的 ShuffleNetV1 实现位于 shufflenet_v1.py,注册名为ShuffleNetV1。从源码结构看,其要点如下:
- 阶段划分:
self.stage_blocks = [4, 8, 4],即三个 stage 分别含 4、8、4 个ShuffleUnit;前接conv1(3×3、stride 2)与maxpool; - 通道配置由 groups 决定:当
groups=3时三个 stage 的输出通道为(240, 480, 960),并支持groups=1/2/3/4/8与widen_factor宽度缩放(通道数经make_divisible(ch, 8)对齐到 8 的倍数); - 默认
out_indices=(2, ):只输出第 2 个 stage 的特征(960 通道、输入 256 时特征图 8×8),这正是配置中HeatmapHead的in_channels=960的来源——热图头直接以该特征为输入,无需反卷积上采样,因为 64×64 热图与 8×8 特征图经 head 内部的步幅设计对齐(SimpleBaseline 系列的标准做法,热图分辨率低于输入是常态); - ShuffleUnit 结构:1x1 分组卷积压缩通道(瓶颈通道数为
out_channels // 4)→ 3×3 深度卷积 →channel_shuffle(groups>1 时在分组间重排通道,实现在 utils 中)→ 1x1 分组卷积恢复通道;同一 stage 内首个单元用concat方式合并残差并伴随下采样(stride 2),其余单元用add残差连接保持分辨率; - 骨干支持
frozen_stages、norm_eval、with_cp(梯度检查点省显存)等通用选项;forward返回out_indices指定 stage 的特征元组。
PCKh 评测指标
评测器MpiiPCKAccuracy定义在 keypoint_2d_metrics.py,继承自通用PCKAccuracy,归一化方式为'head',即 PCKh:
- PCK(Percentage of Correct Keypoints)衡量关键点预测误差小于
threshold × 归一化长度的比例;PCKh 用头部尺寸(来自headbox_file的 val 集头部框)作为归一化尺度,MPII 论文约定阈值为 0.5 和 0.1,对应结果表中的 "Mean" 与 "Mean@0.1"; - 从源码看,MPII 的 16 个关键点中 Neck 与 Head 两个点被 mask 掉(
PCKh.mask[6:8] = True)不参与 Mean 计算,并按 MPII 官方约定对各关节对取平均(如 Shoulder PCK 取两肩均值),再用jnt_ratio加权求和得到最终 "Mean"; - 验证结果同时输出 Head、Shoulder、Elbow、Wrist、Hip、Knee、Ankle 的分部位 PCK,便于定位模型薄弱环节。
训练与推理命令
MPII 为 Top-down 任务,官方预训练权重与训练日志可通过上述模型库页面(shufflenetv1_mpii.md 中的 ckpt/log 条目)下载。使用仓库自带脚本训练或测试:
# 单卡训练 python tools/train.py configs/body_2d_keypoint/topdown_heatmap/mpii/td-hm_shufflenetv1_8xb64-210e_mpii-256x256.py # 单机 8 卡分布式训练(与配置中 8xb64 基准一致) python -m torch.distributed.launch --nnodes=1 --nproc_per_node=8 \ --local_rank=0 \ tools/train.py configs/body_2d_keypoint/topdown_heatmap/mpii/td-hm_shufflenetv1_8xb64-210e_mpii-256x256.py分布式训练也可使用仓库提供的 dist_train.sh 封装脚本。测试/推理命令:
# 使用 checkpoint 在 MPII val 集上评估 python tools/test.py \ configs/body_2d_keypoint/topdown_heatmap/mpii/td-hm_shufflenetv1_8xb64-210e_mpii-256x256.py \ work_dir/ckpt.pth --out results.pkl由于配置中启用了auto_scale_lr(基准 512),若以单卡小 batch 复现,学习率会自动线性缩放,但训练动态(BN 统计量、warmup 比例)与 8 卡基准存在差异,指标可能与模型库报告值略有出入;同时验证集必须提供mpii_gt_val.mat头部框文件,PCKh 指标才能正常计算。
小结
- 该基线展示了 MMPose 中一个完整的 SimpleBaseline 热图方案:
TopdownPoseEstimator+ShuffleNetV1(groups=3)+HeatmapHead(960→16)+MSRAHeatmap(256/64, sigma=2)+MpiiPCKAccuracy; - 配置层面体现了 MMPose 的典型实践:基于 codec 的编解耦、Adam + 线性 warmup + 双步长衰减、按 PCK 保存最优权重、翻转热图平均测试增强;
- 源码层面,ShuffleNetV1 的
groups参数直接决定三阶段通道数(240/480/960)与热图头输入通道,out_indices=(2,)决定了骨干只输出最末 stage 特征,二者与配置严格对应; - ShuffleNetV1 在 MPII 上取得 PCKh@0.5 0.824 / PCKh@0.1 0.195,是轻量骨干梯队中的入门级选择,适合作为端侧部署或计算受限场景下的姿态估计起点;若需要更高精度,可在同目录配置中横向对比 LiteHRNet、MobileNet-v2、HRNet 等模型(见 MPII 汇总榜)。
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考