ViTPose:用于人体姿态估计的简单视觉Transformer基线.

Vison Transformer在视觉识别任务中效果优秀,但还没有工作在姿态估计任务上验证这种结构的有效性。本文提出了用于姿态估计的Transformer网络ViTPose,使用ViT结构作为Backbone,结合一个轻量级的Decoder,在MS COCO关键点估计bechmark上达到SOTA

1. ViTPose的结构

ViTPose的网络结构设计比较简单,整体采用ViT backbone + decoder的形式。

ViT Backbone分为patch embedding和多个transformer模块。patch embedding将图像分为$d\times d$的patch块。而每个transformer层包含 multi-head self-attention(MHSA)feed-forward network (FFN) 模块。多个transformer层堆叠,构成了backbone

backbone根据计算量大小可以分别选用Vit-B, ViT-L,ViT-H以及ViTAE-G

decoder的选取上,作者选择了两种结构进行了对比:

  1. 经典Decoder结构,两个Deconv(+BN+ReLU) + 1x1conv,每个deconv上采样2倍,最终输出feature map大小为输入的$1/4$倍;
  2. 简单Decoder结构,双线性差值上采样$4$倍,然后是ReLU+3x3conv

方案1非线性更高,因此在CNN的结构中使用比较多。ResNet系列在方案1上的结果远高于方案2,说明CNN结构的学习能力需要强有力的decoder来进一步加强。由于Transformer强大的学习能力,方案2这样的的简单decoder也能达到很高的精度。

实验采用姿态估计中Top-Down的方案,即先用一个检测器检测出单个人体框,然后用ViTPose对人体框进行姿态估计。第一步的检测器在COCOval集上用的是SimpleBaseline,而在最后的COCO test-dev集上与SOTA方案的比较实验中,采用了BigdetSOTA结果是在576x432输入,采用1B参数量的ViTAE-G作为backbone,使用MS COCO + AI Challenger训练的情况下获得的。

2. ViTPose的特性

⚪ 预训练的灵活性

一般情况下backbone都需要ImageNet上预训练。本文提出了三种预训练方案:

  1. 采用ImageNet预训练分类任务,比较经典的方法,数据集总共1M图片
  2. 采用MS COCO预训练MAE任务,将$75\%$的patch随机mask掉,然后让网络学习恢复这些patch,数据集共150K图片
  3. 任务框架同方案2,不过数据集采用MS COCO + AI Challenger,共500K图片

由于ViTPose是单人检测模型,因此将MS COCOAI Challenger中的单个人体crop出来,与ImageNet单个object的数据分布保持一致。然后在3个数据集上分别训练1600epoch,再在MS COCOfine tune 210epoch

采用VitPose-B结构,在MS COCO val set上,三种预训练方案的结果如下。可以看到使用MS COCO + AI Challenger,在只有一半数据量的情况下,可以达到比ImageNet更好的效果。

⚪ 分辨率的灵活性

ViTPose可以通过使用更大的输出尺寸来训练,也可以通过减小backbone中的下采样来构造更大尺度的feature map,这两种操作都能提高精度,具体如下:

分辨率越大结果越高。

⚪ 注意力的灵活性

Transformer中的Attention的计算量是Feature map尺寸的平方,因此是很大的,而且显存占用也很大。因此作者用了Shift WindowPooling Window两种方案来缓解这个问题。

⚪ 微调的灵活性

NLP任务中一样,作者验证了只固定MHSA模块的参数,精度下降不多,而固定FFN的参数,则精度下降明显,因此作者认为MHSA更偏向与任务无关,而FFN则更具体任务关系更密切。

⚪ 多任务的灵活性

作者还尝试了采用同一个backbone,多个decoder,每个decoder对应一个数据集的任务,实验验证一次训练,多个数据集上的结果都能比较好,且比单个数据集精度有提升:

⚪ 蒸馏

作者提出了一个基于Transformer的蒸馏方法,与常见的用损失来监督TeacherStudent网络的思路不太一样,具体如下:

  1. 在大模型的patch embedding后的visual token后面增加一个知识token模块,并进行随机初始化
  2. 固定大模型的参数,只训练知识token模块
  3. 将训练好的知识token模块接到小模型的visual token后面,且固定知识token的参数,只训练小模型的其他参数

通过这样的流程,将所有的知识都融合到了知识token模块的参数里面,并且从大模型传递到小模型。