ST-GCN简介
传统深度学习方法将骨架数据表示为矢量序列或二维网格,但并不能表达关节之间的依赖关系。图卷积网络(graph convolutional networks, GCNs)将卷积从图像推广到图。它基于人体关节的自然连接构造一个时空图,并在连续帧中添加相应关节之间的时间边缘。
ST-GCN的缺陷
ST-GCN打破了传统骨架的定义,更好地表述了关节之间的依赖关系,但它也存在三个缺陷:
- 所使用的骨架图是预定义的,仅仅能够代表人体的物理结构。
- GCNs的结构是分层的,不同的层包含不同的语义信息,而GCNs将语义信息固定在所有的层,缺乏灵活性。
- 对于不同动作类别的样本,一个固定的图结构可能不是最优的。
以下是openpose骨架图的定义以及st-gcn源代码graph.py中对于邻接节点(neighbor_link)的定义。
def get_edge(self, layout):
if layout == 'openpose':
self.num_node = 18 #openpose节点总数为18
self_link = [(i, i) for i in range(self.num_node)] #每个节点自身的link关系
neighbor_link = [(4, 3), (3, 2), (7, 6), (6, 5), (13, 12), (12,11), #关节点之间的link关系
(10, 9), (9, 8), (11, 5), (8, 2), (5, 1), (2, 1),
(0, 1), (15, 0), (14, 0), (17, 15), (16, 14)]
self.edge = self_link + neighbor_link #edge=关节点自身link+ 关节点之间的link
self.center = 1 #设置姿态中心关节点
elif layout == 'ntu-rgb+d':
self.num_node = 25
self_link = [(i, i) for i in range(self.num_node)]
neighbor_1base = [(1, 2), (2, 21), (3, 21), (4, 3), (5, 21),
(6, 5), (7, 6), (8, 7), (9, 21), (10, 9),
(11, 10), (12, 11), (13, 1), (14, 13), (15, 14),
(16, 15), (17, 1), (18, 17), (19, 18), (20, 19),
(22, 23), (23, 8), (24, 25), (25, 12)]
neighbor_link = [(i - 1, j - 1) for (i, j) in neighbor_1base]
self.edge = self_link + neighbor_link
self.center = 21 - 1
elif layout == 'ntu_edge':
self.num_node = 24
self_link = [(i, i) for i in range(self.num_node)]
neighbor_1base = [(1, 2), (3, 2), (4, 3), (5, 2), (6, 5), (7, 6),
(8, 7), (9, 2), (10, 9), (11, 10), (12, 11),
(13, 1), (14, 13), (15, 14), (16, 15), (17, 1),
(18, 17), (19, 18), (20, 19), (21, 22), (22, 8),
(23, 24), (24, 12)]
neighbor_link = [(i - 1, j - 1) for (i, j) in neighbor_1base]
self.edge = self_link + neighbor_link
self.center = 2
对于第一、三两个缺陷。我的理解是st-gcn对于边的定义局限在相邻节点内,对于识别“鼓掌”、“阅读”这种需要双手参与的工作,st-gcn就很难捕获双手之间的依赖关系;对于不同的行为动作,st-gcn的识别应该有所侧重,而不是一个固定的图结构。
AGCN
1.图的改进
针对st-gcn的缺点,定义了2S-AGCN。2S-AGCN参数化了两种类型的图。一种是全局图,表示所有数据的公共模式;另一种是单个图,表示每个数据的唯一模式。这种方式增加了图的灵活性。
另外值得注意的是,st-gcn中只包含了连接到每个顶点的特征向量,而特征向量中只包含骨骼的2D或3D坐标信息,例如(x,y,confidence),这些只是骨骼的一阶信息;但是骨骼的长度和方向作为二阶信息,往往更能识别动作,却被忽略了。例如可以将骨骼的长度和方向表示为从源节点指向目标节点的矢量,矢量被输入自适应图卷积网络来预测动作标签。
图的结构仍然遵循st-gcn的图结构。
2.构造的改进
提出了一种双流框架来融合一阶信息和二阶信息以进一步提高性能。
其中,
A
k
\Alpha_k
Ak表示邻接矩阵,确定两个顶点之间是否有连接,
M
k
M_k
Mk表示掩码,确定连接的强度。邻接矩阵由三部分构成:
A
k
\Alpha_k
Ak、
B
k
B_k
Bk、
C
k
C_k
Ck。
A
k
\Alpha_k
Ak表示人体的物理结构。
B
k
B_k
Bk是参数化和优化过的
N
×
N
N \times N
N×N的邻接矩阵,它是完全根据训练数据学习的,不仅表示了两个节点之间连接的存在,而且表明了连接的强度。
C
k
C_k
Ck指的是唯一图,它为每个样本学习一个唯一的图。使用归一化嵌入高斯函数来计算两个顶点之间的相似度以确定两个顶点之间是否存在连接以及连接的强度。相对于st-gcn的输入和输出的构造公式:
M
k
M_k
Mk注意力矩阵点乘
A
k
\Alpha_k
Ak的方式有着很大的改进。例如,如果
A
k
\Alpha_k
Ak中存在值为0的元素,输出将始终为零,此时
M
k
M_k
Mk将会失效。这意味着,对于“鼓掌”,“翻书”这些关节点不相连的肢体完成的动作,st-gcn的检测精度不高。
下图展示了自适应图卷积层的结构,只有的当
C
i
n
C_{in}
Cin和
C
o
u
t
C_{out}
Cout不一致的时候才需要用到残差框。
使用
A
k
\Alpha_k
Ak+
B
k
B_k
Bk+
C
k
C_k
Ck的方式来构造输出矩阵而不是直接用
B
k
B_k
Bk或
C
k
C_k
Ck直接替换
A
k
\Alpha_k
Ak,这种方式增强了模型的灵活性。
下图展示的是一个block的结构,一个基本块由一个空间GCN(Convs),一个时间GCN(Convt)以及一个额外的dropout层(采样概率设为0.5)构成。空间GCN和时间GCN后面都跟着一个批处理规范化层(BN)和一个RELU层
而AGCN就是这些基本块的堆叠,一个AGCN共有9个block。每个块的输出通道数为64、64、64、128、128、128、256、256、256。开头添加BN层规范化数据,最后执行一个全局平均池化(Globalavgpool),将不同样本的特征映射池化到相同大小。最后输出被发送到一个softmax分类器作预测。
对应的代码块如下:
self.l1 = TCN_GCN_unit(3, 64, A, residual=False)
self.l2 = TCN_GCN_unit(64, 64, A)
self.l3 = TCN_GCN_unit(64, 64, A)
self.l4 = TCN_GCN_unit(64, 64, A)
self.l5 = TCN_GCN_unit(64, 128, A, stride=2)
self.l6 = TCN_GCN_unit(128, 128, A)
self.l7 = TCN_GCN_unit(128, 128, A)
self.l8 = TCN_GCN_unit(128, 256, A, stride=2)
self.l9 = TCN_GCN_unit(256, 256, A)
self.l10 = TCN_GCN_unit(256, 256, A)
self.fc = nn.Linear(256, num_class)
nn.init.normal_(self.fc.weight, 0, math.sqrt(2. / num_class))
bn_init(self.data_bn, 1)
2S-AGCN(增加双流)
二阶信息,即骨骼信息,往往被忽略了。我们定义靠近骨架重心的关节为源关节,远离重心的关节为目标关节。每一块骨头都被表示为从源关节指向目标关节的向量。关节的数量比骨头的数量多1。分别用J-Stream和B-Stream表示关节网络和骨骼网络,将关节数据和骨骼数据分别输入J-Stream和B-Stream。然后将两个流的数据分别做预测,并将softmax分数相加来预测动作标签。
实验部分
1.数据集
下图展示了两个数据集对于人体骨架的定义:左图是KInetics-Skeleton、右图是NTU-RCB_D。
NTU-RGB_D:目前最广泛使用的室内动作识别数据集。包含60个动作类中的56000个动作片段,每一个动作由3个摄像头在相同的高度,从
−
4
5
o
-45^o
−45o,
0
o
0^o
0o,
4
5
o
45^o
45o三个不同的水平视角拍摄的。该数据集提供了Kinect深度传感器检测到的每一帧的三维关节位置。每个主体有25个关节。训练集是由37920个摄像头2和摄像头3捕获的视频,验证集是由18960个摄像头1捕获的视频。
Kinetics-Skeleton:大规模人类动作数据集,包含400个课程中的30万个视频剪辑,但只提供没有骨架数据的原始视频剪辑。我们可以使用openpose工具箱来估计每一帧剪辑中18个关节的位置。数据集分为训练集(24000个剪辑)和验证集(20000个剪辑)
2.训练细节
所有实验都是基于PyTorch深度学习框架,随机梯度下降算法的动量设置为0.9,batch_size大小设置为64。选择交叉熵作为反向传播梯度的损失函数。对于NTU-RGB_D数据集,每个样本的最大帧数为300,学习率设置为0.1,训练过程在第50个epoch结束。
对于Kinetics-Skeleton数据集,输入张量设置为150帧,每一帧含有2个人体。从输入骨架序列中随机选择150帧,并通过随机选择的选择和平移操作对关节坐标做轻微干扰。学习率设置为0.1,训练过程在第65个epoch结束。
3.学习图的可视化
下图是学习图的可视化,其中从左往右分别表示图5的第3、5、7层。其中每个圆代表一个关节,其大小代表当前关节与第25个关节的连接强度。从图中可以直观地感受到,第三层的骨架图更关注物理中相邻的节点;第五层同一臂的关节紧密相连;第七层学习出左右手之间的联系。有理由相信更高层应该包含更高层次的信息。
4.一些验证
通过实验数据表明:双流的效果比任何一种单流的效果要好。
下图是一些相关的验证。