经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

经典论文复现 | PyraNet:基于特征金字塔网络的人体姿态估计

原创: 黄泽宇 PaperWeekly

学校丨深圳大学

研究方向丨计算机图形学、深度学习

Learning Feature Pyramids for Human Pose Estimation 是发表在 ICCV 2017 的一篇有关人体姿态估计的论文,提出利用特征金字塔来进行人体姿势预测。作者是 Wei Yang,香港中文大学博士生。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

论文复现代码:

http://aistudio.baidu.com/aistudio/#/projectdetail/24019

人体姿态估计介绍

人体姿态估计是计算机视觉领域一个较有挑战性的任务,问题的输入是一张图片,输出是图片中的人体各个关节点的位置,如下图所示。人体姿态任务可以是单人姿态估计,或者是多人姿态估计,而本文给出的方法是单姿态估计,即一张图片只预测一个人的姿态。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

在本文之前,在人体姿态估计效果较好的工作是 2016 年 Alejandro Newell 等人的 Stacked Hourglass Networks for Human Pose Estimation [1],而本文的网络结构是在此之上的改进, 因此 Hourglass Network 的相关设计对理解本文网络非常重要。

重要工作介绍

Stacked Hourglass Network

Stacked Hourglass Network 是一种堆叠沙漏型的全卷积网络,能够很好地捕捉图片的多尺度特征,并由粗到细地预测关节点位置的热力图 Heatmap,即关节点出现在各个位置的概率。最终的关节点的位置预测结果取 Heatmap 中概率最大的索引。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

网络的基本结构如下图所示,可以看到网络后面都是由一个个沙漏型的结构堆叠而成的。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

Hourglass Module

沙漏模块则是一种编码器-解码器加短接层的设计,其动机是捕获多尺度信息。因为对于人体的各个不同部位的大小尺度是不一样的,通过短接层将不同尺度下的特征图加入到解码阶段可以获得更尺度的信息,从而得到更精准的预测。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

Hourglass 模块和 Networks 中的白色方块表示的都是类似于 ResNet 中的残差模块 [2],其作用是在保留原特征信息的同时进一步提取更深层次的特征,同时也能使得网络变得更深又不至于梯度消失。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

像堆叠残差模块一样堆叠沙漏模块就得到了堆叠沙漏网络。值得注意的是,沙漏模块的输入和输出大小可以是一样的,也就是说在每个沙漏模块之后都可以进行最终结果的预测并计算损失,起到中间监督作用

另外,上层模块的预测结果也可以作为下层模块的输入,从而更好的帮助下层模块进行预测,因此预测结果也可以通过 1*1 的卷积重新加入到原来的特征中,进行由粗糙到细致的估计

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

改进方向

为了捕捉不同尺度的,除了使用短接层,还可以使用不同的卷积核同时进行卷积,再将得到的特征进行叠加,比如 Inception 模块 [3]。Inception 模块通过使用不同大小的卷积核以及 1*1 的卷积使得网络能够捕捉不同分辨率的特征,并减少参数数量。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

而在减少参数数量方面,ResNeXt 又在 ResNet 更进一步 [4],将初始的输入分裂成多条分支进行卷积,其中每条分支的卷积核大小都是一样的。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

另外,使用空洞卷积也可以获得多尺度的特征 [5],空洞卷积是通过使用具有间隔的卷积核在特征图上进行卷积从而避免对原特征图进行下采样的步骤。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

本文方法

Pyramid Residual Modules (PRMs)

可能是受到上述三种模块的启示,本文作者设计出了四种特征金字塔模块如下图所示。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

PRM-A 是在原先的残差模块的分支基础上,直接增加多个分辨率的分支,其分辨率的不同主要是通过下采样实现的,而由于残差模块的结果需要将不同分支的结果相加,因此下采样后的特征要通过上采样恢复原来分辨率。

PRM-B 则是将 PRM-A 中不同分辨率的分支开始的 1*1 卷积进行参数共享,从而减少参数数量。

PRM-C 则是将 PRM-B 中多分辨率特征的相加改为了串联,由于串联后的特征通道数与原来不同,因此可能需要再进行一个 1*1 的卷积对齐特征通道后再与原特征相加。

PRM-D 则是使用空洞卷积代,替下采样和上采样得到多尺度的特征。

根据后面的实验结果可以看到在准确率、参数数量和复杂度的权衡之下,PRM-B 模块是较好的选择。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

Output Variance Accumulation

除了上述的改进,本文作者还提到原始的残差模块有输出方差积累的问题,当堆叠多个残差块时,将原始特征直接与卷积后的特征相加时会有较大的方差,通过对原始特征添加一个 Bn-ReLu-Conv 操作可以较好的控制这个问题。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

PyraNet

本文网络框架使用 Stacked Hourglass Network 的基本框架,但将其中的残差模块都替换成了上述特征金字塔模块 PRMs,网络结构图如下。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

再谈初始化

网络参数的初始化对网络的训练以及结果会有一定影响,为了使得网络更顺利的开始训练,有许多不同的初始化方案,其中较常见的即是

Xavier [6]。

Xavier

Xavier 的提出者指出,第 i 层的参数方差从正向和反向传播的角度考虑,应分别满足如下式子。其中的 n_i 和 n_(i+1) 分别是该层输入的元素个数以及输出的元素个数。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

折衷考虑,Xavier 初始化的参数方差同时考虑输入和输出元素个数,即将上述两式相加后得到的结果。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

Initialization Multi-Branch Networks

本文作者考虑到提出 Xavier 时的大部分网络并没有多条分支,因此对多分支网络的初始化方案重新考量,得出了如下的更泛化的结果。其中 l 表示网络层数,C_i 和 C_o 分别表示输入和输出分支数,n_i 和 n_o 分别表示各输入和输出分支的元素个数,α 根据激活函数有不同取值,ReLu 取 0.5。即从前向和反向传播的角度考虑,各层参数初始化时的方差应与各输入分支合并前的总元素个数、各输出分支分离后的总元素个数有关。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

折衷考虑,多分支参数初始化的方差在文中应为满足如下式子。注意到 α 带有平方,特殊情况下,若 α 取 0.5,输入输出均只有 1 条分支,结果与 Xavier 不一致,因此笔者认为 α 不应取平方,这样在上述情况下仍能 Xavier 保持一致,作为 Xavier 的泛化。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

实验结果与分析

人体姿态估计准确性

本文在 MPII 和 LSP、LSPEt 数据集上进行训练,使用 PCK (Percentage of Correct Keypoints) 和 PCKh 进行评估,PCK 计算估计的关键点与真实值间的归一化距离小于设定阈值的比例,PCKh 则以头部长度为参考的归一化。实验结果如下,可以看到使用 PRM-B 的 PyraNet 在所有对比的方法中都取得了最好的准确率。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

控制变量比较

在网络结构的对比实验中可以看到,相比于 Baseline 即普通的 Stacked Hourglass Network,PyraNet 使用的特征金字塔和多分支参数初始化方案都有提高结果的准确性。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

其他实验

本文作者使 PRM 替代相应网络的残差模块在 CIFAR-10 上进行训练,得到最低的 Top-1 测试误差,但网络的大小和运算量稍有增加。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

总结

本文的主题虽然是人体姿态估计,但提出的改进和创新较为普适,在其他任务上也可以进尝试。主要思想有如下:

1. 本提出了特征金字塔残差模块,增强了深度神经网络的尺度不变性;

2. 本文提出了多分支参数初始化方案,使得网络训练更顺利;

3. 本文提出了通过在短接层增加一次卷积来减少残差模块输出方差积累的问题。

PaddleFluid模型复现

注:代码中的 bn_relu_convn*n 是对依次使用 PaddleFluid 的 batch norm、relu 和卷积核为 n 的 conv2d 的封装。

1. 定义特征金字塔模块:特征金字塔首先将输入进行不够规模的下采样,再进行特征提取,然后将下采样后提取的特征上采样回输入大小。原文使用了 Fraction pool 进行下采样,使得下采样更加平滑,而 PaddleFluid 并没有实现 Fraction pool,故只能使用简单的二线性插值 Resize bilinear 进行代替。

def pyramid(input, out_ch, ngroup):
output_res = input.shape[-1]
scale_base = pow(2.0, 1.0/ngroup)
# extract features in different resolution
features = []

for i in range(1, ngroup+1):
# subsample
scale = round(1.0/pow(scale_base, i),4)
feature = resize_bilinear(input, scale=scale)
# extract the feature
feature = bn_relu_conv3x3(feature,out_ch)
# upsample
feature = resize_bilinear(feature, out_shape=[output_res, output_res])
features.append(feature)
# sum up features
output = features[0]

for i in range(1, ngroup):
output = elementwise_add(output, features[i])
return output

2. 定义 PRM 特征金字塔残差块:在一般的 ResNet 残差模块的基础上进行扩展,在进行完 3*3 的卷积后再加入一个特征金字塔,这里实现了上述的 PRM-B,即所有特征金字塔分支使同一个输入。

def conv_block(input, out_ch, type='prm-b', base_width=6, cardinality=30):
# 1*1 conv
conv_out = bn_relu_conv1x1(input,out_ch//2)
# 3*3 conv
conv_out = bn_relu_conv3x3(conv_out,out_ch//2)
if type == 'res':
output = bn_relu_conv1x1(conv_out,out_ch)
return output
elif type == 'prm-b':
pyra_depth = out_ch//base_width
ngroup = cardinality
# extract feature pyramid
# 1 branch in, ngroup branches out
pyra_out = bn_relu_conv1x1(input, pyra_depth,in_branches=1,out_branches=ngroup)
pyra_out = pyramid(pyra_out, pyra_depth, ngroup)
# ngroup braches in, 1 branch out
pyra_out = bn_relu_conv1x1(pyra_out, out_ch//2,in_branches=ngroup,out_branches=1)
# 2 branches in, 1 branch out
output = elementwise_add(conv_out, pyra_out)
output = bn_relu_conv1x1(output, out_ch,in_branches=2,out_branches=1)
return output

# TODO: PRM-A/PRM-C/PRM-D
return output

3. 按照 Stacked Hourglass Network 的方式定义沙漏模块和堆叠沙漏模块(代码略)。值得注意的是 Hourglass 是一个递归的结构,因此可以使用递归函数来建立网络结构。

4. 定义初始化方案 Branch initializer,笔者使用 Xavier 进行泛化,加入了输入输出分支数。

def branch_initializer(in_units=1,out_units=1,in_branches=1,
out_branches=1,act='relu',uniform=False,seed=0):
# it might be alpha instead of alpha**2 in formula.15
# in this case, when in_branches=out_branches=1, it degenrates to Xavier
alphax2 = 0.5*2 if act=='relu' else 1.0*2
fan_in = in_units*in_branches*alphax2
fan_out = out_units*out_branches*alphax2
return Xavier(uniform,fan_in,fan_out)

5. 网络训练:

实验使用 PaddleFluid v0.14 环境,Titan Xp 单 GPU,在 MPII 数据集上进行训练,训练图片 20k 张,测试图片 2k 张,训练时进行了数据增强。PyraNet 堆叠沙漏数 nstack=2,残差模块使用 PRM-B 结构,特征金字塔分支数 cardinality=4,通道基数 base_width=9,批大小 batch_size=8,训练轮述 epoch=150,使用 Adam 优化器,学习率 2.5*10^-4 且每 10 轮衰减至 90%,初始化使用 Xavier 泛化后的多分支初始化。对照组除了残差模块为普通 res 模块其他参数均相同。

6. 实验结果:本次复现结果使用 PRM-B 模块的 PyraNet 并没有比使用 Res 模块的堆叠沙漏网络效果要好。准确率使用 [email protected] 进行评估。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

准确率曲线如下:使用 PRM-B 由于发生了过拟合,在 Epoch=110 处进行了早停,而使用 Res 则在 Epoch=110 时接近收敛。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

7. 结果对比分析:复现结果本应是使用 PRM-B 模块的 PyraNet 要好于使用 Res 模块的堆叠沙漏网络,但结果却相反。

在训练时发现一个问题,即 PyraNet 很容易过拟合,调整多次都没有得到很好的结果,而普通的堆叠沙漏网络训练则非常稳定。推测是由于加入了特征金字塔结构,分支数太多,网络变得复杂,所以难以训练。由于时间关系,也没有将网络调试到最好状态。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

8. 结果可视化:下面是几个使用 Res 模块的堆叠沙漏网络实验结果的可视化,可以看到预测出了基本的人体姿势。

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计

经典论文复现|PyraNet:基于特征金字塔网络的人体姿态估计



分享到:


相關文章: