mmpose 中的 Debias IPR:用 ResNet-50 在 COCO 上实现无偏积分回归的完整配置与源码解析
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
导读
本文聚焦 mmpose 仓库中基于**去偏积分姿态回归(Debias Integral Pose Regression, Debias IPR)**的 top-down 人体 2D 关键点检测方案,其核心配置位于 ipr_res50_debias-8xb64-210e_coco-256x256.py。文章将系统讲解该模型的算法动机、配置文件逐段拆解、IntegralRegressionLabel编解码器与DSNTHead的底层实现原理,以及训练、测试、评估的完整流程。读完本文,你将掌握如何在 mmpose 中复现并在 COCO val2017 上达到 AP 0.675 的 Debias IPR 基线,也能理解它与普通 IPR、DSNT 在精度上的差异根源。
Debias IPR 技术背景
从积分回归到"去偏"
传统 top-down 热图方法通过高斯热图回归关键点位置,解码时常用 argmax 或 DSNT 中的 soft-argmax。而积分回归(Integral Pose Regression, IPR)将热图与坐标回归通过可微的积分操作统一起来,是 IntegralRegressionHead 的核心思想。
Debias IPR 来自论文Removing the Bias of Integral Pose Regression(ICCV'2021,作者 Gu、Yang、Yao)。它指出:soft-argmax 在归一化热图上求期望时,会因 softmax 归一化(归一化常数C = Σ exp(x))与坐标缩放而产生系统性偏差,导致预测坐标向热图中心收缩。Debias IPR 通过一个闭式修正项消除该偏差,相关论文与 bibtex 引用记录在 resnet_debias_coco.md 中。
三种积分回归方案在 mmpose 中的对比
在 integral_regression 目录下,mmpose 用同一套 ResNet-50 骨干给出了三组可对照的基线(均为 256x256 输入、COCO val2017、人体检测器 AP 为 56.4):
| 模型 | 输入尺寸 | AP | AR | 详情 |
|---|---|---|---|---|
| ResNet-50 + Debias-IPR | 256x256 | 0.675 | 0.765 | resnet_debias_coco.md |
| ResNet-50 + DSNT | 256x256 | 0.674 | 0.764 | resnet_dsnt_coco.md |
| ResNet-50 + IPR | 256x256 | 0.633 | 0.730 | resnet_ipr_coco.md |
可以看到,仅加入 debias 修正即可把 AP 从 0.633 提升到 0.675(+4.2 AP),这正是"去偏"核心价值的直接体现。
模型结果与论文引用
关联文档 resnet_debias_coco.md 记录了该配置在COCO val2017上的完整结果(检测器在 COCO val2017 上的人体 AP 为 56.4):
| Arch | Input Size | AP | AP50 | AP75 | AR | AR50 |
|---|---|---|---|---|---|---|
| debias-ipr_resnet_50 | 256x256 | 0.675 | 0.872 | 0.740 | 0.765 | 0.928 |
该结果的模型元信息(架构、训练数据、指标)同样记录在 resnet_debias_coco.yml 中:Architecture 为Debias + ResNet,训练数据为 COCO。文档同时以 bibtex 形式收录了三篇关联文献:Debias IPR(ICCV'2021)、ResNet(CVPR'2016,Deep Residual Learning for Image Recognition)与 COCO 数据集(ECCV'2014,Microsoft COCO: Common Objects in Context)。
配置文件逐段拆解
完整配置文件位于 ipr_res50_debias-8xb64-210e_coco-256x256.py,其基础运行时继承自 default_runtime.py。下面按功能模块拆解。
训练调度与优化器
# runtime train_cfg = dict(max_epochs=210, val_interval=10) # optimizer optim_wrapper = dict(optimizer=dict( type='Adam', lr=5e-4, )) # learning policy param_scheduler = [ dict( type='LinearLR', begin=0, end=500, start_factor=0.001, by_epoch=False), # warm-up dict( type='MultiStepLR', begin=0, end=train_cfg['max_epochs'], milestones=[170, 200], gamma=0.1, by_epoch=True) ] # automatically scaling LR based on the actual training batch size auto_scale_lr = dict(base_batch_size=512)- 总训练周期 210 个 epoch,每 10 个 epoch 验证一次;
- 优化器使用Adam,初始学习率 5e-4;
- 学习率策略为两段式:前 500 个 iteration 用
LinearLR做 warm-up(起始系数 0.001),随后用MultiStepLR在第 170、200 个 epoch处以 gamma=0.1 衰减; auto_scale_lr声明基准 batch size 为 512,当实际 batch size 与该基准不一致时,mmpose 会自动按比例缩放学习率。
Codec:IntegralRegressionLabel
codec = dict( type='IntegralRegressionLabel', input_size=(256, 256), heatmap_size=(64, 64), sigma=2.0, normalize=True)IntegralRegressionLabel是 mmpose 专门为 DSNT/IPR 系列设计的联合编解码器,实现位于 mmpose/codecs/integral_regression_label.py。从源码看,它内部组合了两个子 codec:
- MSRAHeatmap(
sigma=2.0):负责把关键点坐标编码为 64x64 的高斯热图,作为 DSNT 训练时的监督信号; - RegressionLabel(
input_size=(256, 256)):把坐标归一化到 [0, 1] 区间,作为坐标回归的目标标签,实现见 mmpose/codecs/regression_label.py。RegressionLabel.encode以keypoints / [w, h]得到归一化标签,并在坐标越界或不可见时将keypoint_weights置 0;decode则反向乘回输入尺寸并返回坐标与置信度。
normalize=True时,encode会进一步对热图做归一化:heatmaps = heatmaps / heatmaps.sum(...),使每个关键点的热图概率和为 1(代码中加1e-24防止除零),这与 soft-argmax 的期望计算在数学上保持一致。
模型结构:TopdownPoseEstimator + ResNet-50 + DSNTHead
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='ResNet', depth=50, ), head=dict( type='DSNTHead', in_channels=2048, in_featuremap_size=(8, 8), num_joints=17, debias=True, beta=10., loss=dict( type='MultipleLossWrapper', losses=[ dict(type='SmoothL1Loss', use_target_weight=True), dict(type='JSDiscretLoss', use_target_weight=True) ]), decoder=codec), test_cfg=dict( flip_test=True, shift_coords=True, shift_heatmap=True, ), init_cfg=dict( type='Pretrained', checkpoint='https://download.openmmlab.com/mmpose/' 'pretrain_models/td-hm_res50_8xb64-210e_coco-256x192.pth'))关键点说明:
debias=True:这是本配置区别于普通 IPR 的唯一开关。在 IntegralRegressionHead 的forward中,当debias为真时,会对期望坐标施加闭式修正:C = feats.reshape(B, N, H * W).exp().sum(dim=2).reshape(B, N, 1) pred_x = C / (C - 1) * (pred_x - 1 / (2 * C)) pred_y = C / (C - 1) * (pred_y - 1 / (2 * C))这里
C即 softmax 的归一化常数(对 e 的指数和)。修正项补偿了归一化与坐标缩放共同引入的偏差,是 Debias IPR 论文的核心贡献在代码中的落地。beta=10.0:softmax 前的平滑参数,用于锐化/钝化预测热图,随后执行_flat_softmax(feats * self.beta);in_featuremap_size=(8, 8):ResNet-50 输出 2048 通道、8x8 的特征图,经过simplebaseline_head(3 层反卷积,每层 256 通道、kernel 4)上采样到 64x64 的热图;双损失
MultipleLossWrapper:SmoothL1Loss:对预测坐标与归一化坐标标签计算平滑 L1 损失;JSDiscretLoss:对预测热图与高斯真值热图计算 JS 散度损失,实现见 mmpose/models/losses/classification_loss.py 中的JSDiscretLoss类——它以KLDivLoss为基础,先计算m = 0.5*(pred+gt),再取0.5*(KL(pred,m)+KL(gt,m)),配合use_target_weight=True按关键点可见性加权。
test_cfg:开启flip_test(水平翻转测试时对坐标与热图分别做平均融合,见predict中的 TTA 分支)、shift_coords与shift_heatmap;init_cfg:加载预训练的 top-down 热图 ResNet-50 权重td-hm_res50_8xb64-210e_coco-256x192.pth,复用已有热图监督学习的骨干特征。
数据流水线与 DataLoader
dataset_type = 'CocoDataset' data_mode = 'topdown' data_root = 'data/coco/' train_pipeline = [ dict(type='LoadImage'), dict(type='GetBBoxCenterScale'), dict(type='RandomFlip', direction='horizontal'), dict(type='RandomHalfBody'), dict(type='RandomBBoxTransform'), dict(type='TopdownAffine', input_size=codec['input_size']), dict(type='GenerateTarget', encoder=codec), dict(type='PackPoseInputs') ] test_pipeline = [ dict(type='LoadImage'), dict(type='GetBBoxCenterScale'), dict(type='TopdownAffine', input_size=codec['input_size']), dict(type='PackPoseInputs') ]- 训练时依次执行水平翻转、半身随机裁剪(
RandomHalfBody)、随机框变换(RandomBBoxTransform)与仿射变换(TopdownAffine),最后用GenerateTarget以codec完成标签编码; - 测试流水线保持简洁,不包含任何数据增强;
GenerateTarget仅存在于训练流水线中,测试时直接由模型头内的 decoder 完成解码; - 训练 batch size 为 64(2 个 worker),验证 batch size 为 32。
数据集与评估
val_dataloader = dict( batch_size=32, ... dataset=dict( type=dataset_type, data_root=data_root, data_mode=data_mode, ann_file='annotations/person_keypoints_val2017.json', bbox_file=f'{data_root}person_detection_results/' 'COCO_val2017_detections_AP_H_56_person.json', data_prefix=dict(img='val2017/'), test_mode=True, pipeline=test_pipeline, )) test_dataloader = val_dataloader default_hooks = dict(checkpoint=dict(save_best='coco/AP', rule='greater')) val_evaluator = dict( type='CocoMetric', ann_file=f'{data_root}annotations/person_keypoints_val2017.json') test_evaluator = val_evaluator- 验证使用 top-down 惯例的外部检测框文件
COCO_val2017_detections_AP_H_56_person.json(检测器人体 AP 为 56.4),这是复现表中指标的前提; - checkpoint 保存策略为按
coco/AP取最优(rule='greater'); - 评估使用
CocoMetric,与官方 COCO 关键点 AP 协议一致。
源码级原理:从编码到解码的完整链路
训练时的标签生成
训练时,GenerateTarget调用IntegralRegressionLabel.encode,同时产出三份标签(见 integral_regression_label.py):
keypoint_labels:归一化坐标(N, K, 2),供SmoothL1Loss使用;heatmaps:高斯热图(K, 64, 64),经normalize归一化后供JSDiscretLoss使用;keypoint_weights:按可见性加权的权重掩码。
前向推理与 debias 修正
DSNTHead继承自IntegralRegressionHead,其前向流程为(integral_regression_head.py):
- 骨干特征经
simplebaseline_head(3 层反卷积 + 1x1 卷积)得到每关节一张热图; _flat_softmax(feats * beta)做深度方向 softmax 归一化;- 用预生成的
linspace_x/linspace_y网格计算线性期望pred_x、pred_y(即 soft-argmax); debias=True时按上述闭式公式修正;- 输出
(coords, heatmaps)二元组——DSNTHead.loss同时使用两者计算坐标损失与热图 JS 散度损失。
测试时的 TTA 与解码
predict中开启flip_test后,原始与水平翻转的特征各自前向,翻转结果经flip_coordinates/flip_heatmaps(mmpose/models/utils/tta.py)对齐后取平均;随后调用 decoder(即IntegralRegressionLabel)把归一化坐标乘回输入尺寸,得到最终像素坐标与置信度。
训练与测试复现
环境准备与通用训练流程可参考 docs/zh_cn/user_guides/train_and_test.md 与 docs/zh_cn/quick_run.md。在按 docs/zh_cn/user_guides/prepare_datasets.md 准备好data/coco(含 val2017 检测框文件)后,使用以下命令训练:
python tools/train.py configs/body_2d_keypoint/integral_regression/coco/ipr_res50_debias-8xb64-210e_coco-256x256.py多卡训练可使用仓库自带的 tools/dist_train.sh:
bash tools/dist_train.sh configs/body_2d_keypoint/integral_regression/coco/ipr_res50_debias-8xb64-210e_coco-256x256.py 8测试与指标评估:
python tools/test.py configs/body_2d_keypoint/integral_regression/coco/ipr_res50_debias-8xb64-210e_coco-256x256.py \ <checkpoint.pth>测试输出将包含 AP、AP50、AP75、AR、AR50等完整指标,可与上文结果表对照。若要在其他数据集上复用该方案,可在configs/body_2d_keypoint/integral_regression/目录下参照本配置修改dataset_type、data_root与ann_file,并同步调整codec与head中的num_joints。
小结
Debias IPR 用一行闭式修正解决了积分回归中的系统性偏差问题。在 mmpose 中,它落地为DSNTHead的debias=True开关、IntegralRegressionLabel编解码器与SmoothL1Loss + JSDiscretLoss双损失组合,配合 ipr_res50_debias-8xb64-210e_coco-256x256.py 开箱即用的配置,即可在 COCO val2017 上稳定复现 AP 0.675 的基线。对比同目录下的普通 IPR(AP 0.633),去偏带来的增益清晰可验证,也使其成为在回归范式下权衡精度与推理速度时的可靠选择。
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考