mmpose 中的 Lite-HRNet 轻量级高分辨率骨干网络:从条件通道加权原理到实战配置
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
Lite-HRNet(Lite-HRNet: A Lightweight High-Resolution Network,CVPR 2021)是面向人体姿态估计等密集预测任务的轻量级高分辨率骨干网络。本文以 mmpose 仓库中的算法文档为核心,结合 LiteHRNet 源码实现、单元测试 与 COCO/MPII/手部关键点的真实训练配置,系统讲解其论文核心思想、逐模块源码结构、extra配置字典的每个字段,以及从训练到评估的完整实操方法,帮助你理解并直接上手这一经典轻量级骨干。
论文核心思想:用条件通道加权替代 1x1 卷积
Lite-HRNet 论文(Yu Changqian 等人,CVPR 2021)的目标是构建一个高效的高分辨率网络用于人体姿态估计。其出发点非常直接:把 ShuffleNet 中高效的 shuffle block 直接移植到 HRNet(高分辨率网络)上,就能获得优于 MobileNet、ShuffleNet 以及 Small HRNet 等主流轻量级网络的性能。
论文随后指出一个关键观察:shuffle block 中大量使用的 pointwise(1x1)卷积成为了计算瓶颈。为此,论文引入了一个轻量级单元——条件通道加权(Conditional Channel Weighting,CCW),用它来替换 shuffle block 中昂贵的 1x1 卷积。该方案的核心性质如下:
- 复杂度优势:通道加权的计算复杂度与通道数呈线性关系,远低于 1x1 卷积的二次方时间复杂度;
- 信息交换桥梁:权重从所有通道以及 HRNet 并行分支中天然可用的多个分辨率上学习得到,用这些权重作为跨通道、跨分辨率信息交换的桥梁,补偿被移除的 1x1 卷积所承担的角色;
- 通用性:Lite-HRNet 在人体姿态估计上表现出色,同时可以以同样的轻量化方式直接迁移到语义分割任务。
对应的 BibTeX 引用(收录于算法文档 docs/src/papers/backbones/litehrnet.md):
@inproceedings{Yulitehrnet21, title={Lite-HRNet: A Lightweight High-Resolution Network}, author={Yu, Changqian and Xiao, Bin and Gao, Changxin and Yuan, Lu and Zhang, Lei and Sang, Nong and Wang, Jingdong}, booktitle={CVPR}, year={2021} }mmpose 中的源码实现:模块逐层拆解
mmpose 将 Lite-HRNet 完整实现于 mmpose/models/backbones/litehrnet.py,并通过 backbones 注册表 以LiteHRNet名称注册,可在配置文件中直接以type='LiteHRNet'引用。整份实现由一组相互独立、职责清晰的模块组成,下面逐一说明。
1. 空间加权 SpatialWeighting
对应源码 SpatialWeighting,是一个经典的 SE(Squeeze-and-Excitation)风格模块:先用全局平均池化nn.AdaptiveAvgPool2d(1)压缩空间信息,再经两个 1x1ConvModule得到逐通道权重,最后与原特征x * out相乘。其构造参数包括:
channels:输入通道数;ratio:通道压缩比,默认 16,在ConditionalChannelWeighting中被固定传 4;act_cfg:默认(dict(type='ReLU'), dict(type='Sigmoid')),即第一个卷积用 ReLU、最后一个卷积用 Sigmoid 生成 (0,1) 区间权重;conv_cfg/norm_cfg:分别控制卷积层与归一化层类型。
2. 跨分辨率加权 CrossResolutionWeighting
对应源码 CrossResolutionWeighting,它是 Lite-HRNet 区别于一般 SE 模块的关键:输入是多分辨率特征列表x,其前向流程为——
- 将除最小分辨率以外的特征
F.adaptive_avg_pool2d池化到最小尺寸,与最小分辨率特征拼接; - 通过两个 1x1 卷积(
total_channel -> total_channel/ratio -> total_channel)生成聚合权重; - 按各分支通道数
torch.split切分,再F.interpolate(nearest 模式)回各自分辨率并与原特征逐元素相乘。
这样每个分支的通道权重都同时利用了所有分支(所有分辨率)的信息,正是论文所述"从所有通道、多个分辨率学习权重"的直接体现。
3. 条件通道加权 ConditionalChannelWeighting
对应源码 ConditionalChannelWeighting,它是替换 shuffle block 中 1x1 卷积的完整基本单元,前向流程为:
- 将每个分支特征按通道
chunk(2, dim=1)分为x1、x2两路; x1直通(identity 分支),x2依次经过跨分辨率加权、3x3 深度可分离卷积(groups=channel的分组卷积)与空间加权;- 两路
torch.cat拼接后执行channel_shuffle(s, 2)通道混洗,完成跨组信息交换。
其中深度卷积与通道混洗共同承担了原 1x1 卷积"跨通道混合"的职责,而权重计算复杂度保持与通道数线性相关。该模块还支持with_cp(梯度检查点)选项,开启后可节省显存但会降低训练速度。
4. Stem 与 IterativeHead
- Stem(源码):先经过一个 stride=2 的 3x3 卷积得到
stem_channels的特征,再将通道对半分为两条路径:分支 1 走深度卷积+1x1 卷积下采样,分支 2 走 InvertedResidual 式(expand→depthwise→linear)下采样,最后拼接并通道混洗,输出进入第一阶段。 - IterativeHead(源码):当
with_head=True时挂载,对多分辨率特征按从低到高的顺序逐级用DepthwiseSeparableConvModule投影,并自低分辨率向高分辨率F.interpolate(bilinear)累加特征,实现跨分辨率的迭代式特征增强。
5. ShuffleUnit 与 LiteHRModule
- ShuffleUnit(源码):标准 ShuffleNetV2 的 InvertedResidual 单元,stride=1 时短接一半通道、stride>1 时两个分支都参与下采样,最终统一做
channel_shuffle; - LiteHRModule(源码):HRNet 风格的高分辨率模块,
module_type支持'LITE'(使用ConditionalChannelWeighting权重块,由_make_weighting_blocks构建)与'NAIVE'(使用ShuffleUnit分支,由_make_naive_branches构建)两种模式;with_fuse=True时通过_make_fuse_layers构建跨分支融合层(高分辨率分支向上采样、低分辨率分支向下采样,最后求和并经 ReLU 输出)。源码注释特别提示融合求和时y不能以 0 初始化,否则精度会下降 0.5~1 mAP。
6. LiteHRNet 整体前向
LiteHRNet 主类 的前向流程为:Stem → 逐阶段 transition(跨阶段通道转换与分支扩充)→ LiteHRModule 堆叠 → IterativeHead(可选)。最终输出为(x[0], )的单元素元组(第一分支高分辨率特征)。主类还提供norm_eval选项,训练时可将 BatchNorm 层的 running stats 冻结(参考其train方法对_BatchNorm的遍历处理)。
通道混洗操作由独立工具函数 channel_shuffle 提供:把(N, C, H, W)张量 reshape 为(N, groups, C/groups, H, W),交换第 1、2 维后重整回原形状。
核心配置:extra字典逐字段详解
LiteHRNet 的深度结构完全由backbone下的extra字典驱动,这既是它灵活性所在,也是上手时需要重点理解的配置面。以 COCO 上 LiteHRNet-18 配置 为例:
backbone=dict( type='LiteHRNet', in_channels=3, extra=dict( stem=dict(stem_channels=32, out_channels=32, expand_ratio=1), num_stages=3, stages_spec=dict( num_modules=(2, 4, 2), num_branches=(2, 3, 4), num_blocks=(2, 2, 2), module_type=('LITE', 'LITE', 'LITE'), with_fuse=(True, True, True), reduce_ratios=(8, 8, 8), num_channels=( (40, 80), (40, 80, 160), (40, 80, 160, 320), )), with_head=True, )),各字段含义与取值范围如下:
| 字段 | 含义 | 说明 |
|---|---|---|
stem.stem_channels | Stem 首层输出通道 | 源码中经第一个 stride=2 的 3x3 卷积得到 |
stem.out_channels | Stem 输出通道数 | 决定第一阶段的输入通道,LiteHRNet-18/30 均为 32 |
stem.expand_ratio | 中间隐藏层通道扩张比 | mid_channels = round(stem_channels * expand_ratio),用于 InvertedResidual 式下采样分支 |
num_stages | 阶段数量 | 每阶段新增一个更低分辨率分支,典型值为 3 |
stages_spec.num_modules | 每阶段堆叠的 LiteHRModule 数量 | LiteHRNet-18 为(2, 4, 2),LiteHRNet-30 为(3, 8, 3),是 18 与 30 深度的主要差异 |
stages_spec.num_branches | 每阶段的分支(分辨率)数 | (2, 3, 4),从 1/2 分辨率逐步扩到 1/4、1/8 |
stages_spec.num_blocks | 每阶段每个模块内的 block 数 | (2, 2, 2) |
stages_spec.module_type | 模块类型 | 'LITE'使用条件通道加权块,'NAIVE'使用 ShuffleUnit;源码对非法值会抛ValueError |
stages_spec.with_fuse | 是否启用跨分支融合层 | 全部为True |
stages_spec.reduce_ratios | 跨分辨率加权的通道压缩比 | 全部为 8,即total_channel/8 |
stages_spec.num_channels | 各阶段每分支的通道数 | 逐阶段从(40, 80)扩到(40, 80, 160)、(40, 80, 160, 320) |
with_head | 是否使用 IterativeHead | 姿态估计任务通常为True;源码 docstring 示例中演示过False场景 |
在 LiteHRNet docstring 示例 中可以找到与上述配置一致的最小可运行用法:构造模型后输入(1, 1, 32, 32)张量,输出第一分支形状为(1, 40, 8, 8)。
模型库结果:COCO 与 MPII 基准
仓库模型库记录了 Lite-HRNet 在 COCO 与 MPII 两个数据集上的公开复现结果(详见 litehrnet_coco.md 与 litehrnet_mpii.md),可作为训练效果的对照参考。
COCO val2017(使用在 COCO val2017 上人体 AP 为 56.4 的检测器):
| 架构 | 输入尺寸 | AP | AP^50 | AP^75 | AR | AR^50 |
|---|---|---|---|---|---|---|
| LiteHRNet-18 | 256x192 | 0.642 | 0.867 | 0.719 | 0.705 | 0.911 |
| LiteHRNet-18 | 384x288 | 0.676 | 0.876 | 0.746 | 0.735 | 0.919 |
| LiteHRNet-30 | 256x192 | 0.676 | 0.880 | 0.756 | 0.736 | 0.922 |
| LiteHRNet-30 | 384x288 | 0.700 | 0.883 | 0.776 | 0.758 | 0.926 |
MPII val set(Mean/Mean@0.1,PCK 指标):
| 架构 | 输入尺寸 | Mean | Mean@0.1 |
|---|---|---|---|
| LiteHRNet-18 | 256x256 | 0.859 | 0.260 |
| LiteHRNet-30 | 256x256 | 0.869 | 0.271 |
对应的配置入口分别是 COCO 四种组合、MPII 两种组合(如 LiteHRNet-30 on MPII),以及手部关键点场景的 coco-wholebody-hand 配置。
从配置到训练:完整实操流程
训练调度与超参
LiteHRNet 相关配置的训练协议一致(以 COCO 384x288 为例):
- 训练轮数:
max_epochs=210,每 10 轮验证一次; - 优化器:Adam,学习率
lr=5e-4; - 学习率调度:前 500 iter 使用
LinearLR线性 warm-up(start_factor=0.001,按 iter 计算),随后MultiStepLR在 170/200 轮衰减,gamma=0.1; - 自动缩放学习率:
auto_scale_lr = dict(base_batch_size=512),当实际 batch size 与基准不一致时自动等比缩放 LR; - Checkpoint 选择:COCO 配置用
save_best='coco/AP'、MPII 用'PCK'、手部配置用'AUC',均按"更大更好"保存最优权重。
编解码与模型头
LiteHRNet 配置统一采用MSRAHeatmapcodec,例如 COCO 384x288 配置为dict(type='MSRAHeatmap', input_size=(288, 384), heatmap_size=(72, 96), sigma=3)(MPII 256x256 与手部 256x256 则为heatmap_size=(64, 64), sigma=2)。模型头使用无上采样转置卷积的HeatmapHead:
head=dict( type='HeatmapHead', in_channels=40, # 必须与 LiteHRNet 第一分支输出通道一致 out_channels=17, # COCO 17 个关键点;MPII 为 16,手部为 21 deconv_out_channels=None, loss=dict(type='KeypointMSELoss', use_target_weight=True), decoder=codec),注意in_channels=40与extra.stages_spec.num_channels的第一分支 40 通道严格对应。测试阶段启用翻转测试:test_cfg=dict(flip_test=True, flip_mode='heatmap', shift_heatmap=True)。
数据流管线
训练管线依次为LoadImage → GetBBoxCenterScale → RandomFlip(水平)→ RandomHalfBody → RandomBBoxTransform(rotate_factor=60,scale_factor=(0.75, 1.25))→ TopdownAffine → GenerateTarget → PackPoseInputs;验证/测试管线仅保留LoadImage → GetBBoxCenterScale → TopdownAffine → PackPoseInputs。COCO 评测时验证集需提供检测框文件(person_detection_results/COCO_val2017_detections_AP_H_56_person.json),并使用CocoMetric评估;MPII 则使用MpiiPCKAccuracy,并指定headbox_file。
训练与测试命令
在完成数据准备(COCO 数据置于data/coco/,MPII 置于data/mpii/,目录结构见 prepare_datasets 文档)后,即可使用仓库标准的训练入口 tools/train.py 与测试入口 tools/test.py:
# 单卡训练 python tools/train.py configs/body_2d_keypoint/topdown_heatmap/coco/td-hm_litehrnet-18_8xb32-210e_coco-384x288.py # 多卡分布式训练(tools/dist_train.sh 用法见文件头注释) bash tools/dist_train.sh configs/body_2d_keypoint/topdown_heatmap/coco/td-hm_litehrnet-18_8xb32-210e_coco-384x288.py 8 # 测试并评估 python tools/test.py configs/body_2d_keypoint/topdown_heatmap/coco/td-hm_litehrnet-18_8xb32-210e_coco-384x288.py /path/to/checkpoint.pth模型库 md 文件中同时提供了各架构预训练权重与日志的下载入口,可下载后直接用于推理或微调。此外也可以借助 inferencer_demo.py 快速体验推理效果。
单元测试如何验证实现正确性
test_litehrnet.py 从两个层面保证了实现与预期一致:
- LiteHRModule 单测:分别构造
module_type='LITE'与'NAIVE'的单分支模块,输入(2, 40, 56, 56)张量,断言输出形状不变;并验证非法module_type='none'会触发ValueError; - LiteHRNet 整体前向:使用与真实配置一致的
extra(LiteHRNet-18 结构),输入(2, 3, 224, 224),断言返回类型为 tuple 且最后一层输出形状为(2, 40, 56, 56),同时覆盖LITE与NAIVE两种模式以及init_weights初始化流程。
这些断言直接约束了"第一分支输出 40 通道高分辨率特征"这一与HeatmapHead(in_channels=40)对接的关键约定,是配置与实现一致性的第一道保障。
总结
Lite-HRNet 通过在 HRNet 多分辨率框架中引入条件通道加权与跨分辨率加权,以线性复杂度的通道信息交换替代 shuffle block 中的 1x1 卷积,在保持高分辨率特征优势的同时显著降低计算开销。在 mmpose 仓库中,它形成了从算法文档(docs/src/papers/backbones/litehrnet.md)、源码实现(mmpose/models/backbones/litehrnet.py)、单元测试到 COCO/MPII/手部三类数据集的完整闭环,extra配置字典提供了从 18 层到 30 层、从 256x192 到 384x288 的灵活扩展能力。对于需要轻量级骨干支撑的实时人体姿态估计场景,LiteHRNet 是经过基准验证的可靠选择。
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考