Skeleton-Based Action Recognition with Directed Graph Neural Networks是Lei Shi等人的另一篇文章,和之前的2s-AGCN以及Skeleton-Based Action Recognition with Multi-Stream Adaptive Graph Convolutional Networks(

文献理解

),还有改名之前的Non-local都是对骨骼动作进行识别,作者还是做了很多相关工作。本文主要是介绍directed acyclic graph(有向无环图)




Abstract

骨架数据能够很好地适应动态环境和复杂背景,因此在动作识别中得到了广泛的应用。在现有的方法中,骨骼数据中的关节和骨骼信息对动作识别任务都有很大的帮助。然而,如何将这两种类型的数据结合起来,以便更好地利用关节和骨骼之间的关系,仍然是一个有待解决的问题。在这项工作中,我们根据人体关节和骨骼之间的运动相关性,将骨骼数据表示为

有向无环图

(DAG)。设计了一种新的有向图神经网络,用于提取关节、骨骼及其相互关系的信息,并根据提取的特征进行预测。另外,为了更好地适应动作识别任务,在训练过程的基础上,对图的拓扑结构进行了自适应(Adaptive),使其得到了显著的改进。在双流框架下,利用骨架序列的运动信息,结合空间信息,进一步提高性能。我们的最终模型在两个大型数据集NTU-RGBD和Kinetics上进行了测试,在这两个数据集上SOTA。



Introduction

动作识别任务在很多方面都有应用,其中,人体骨架信息有很多优势,比如对尺度变化、背景干扰等具有很强的鲁棒性,而且骨架信息很容易通过硬件设备(kinect)或者软件(openpose)获得。传统的基于骨架的动作识别通常手动设计特征来表示骨架,现有的基于深度学习的方法分为三种:RNN、CNN、GCN,其中连接点信息分别被表示成向量序列、伪图像、图。骨头信息,表征着人体骨头的方向和长度,它和关节点坐标信息是互补的,骨头和关节点是紧密相连的。(从人体骨骼自然结构说明了构造有向图的必要性)现有的基于图的方法通常把骨骼信息表示成一个无向图,并且用两个网络对骨头和关节点进行建模,这样不能将骨头和关节点之间的依赖关系完全探索出来。因此,作者以关节点为节点、骨头为边设计出了一个有向无环图,还设计了一个有向图卷积网络来对构造的图进行建模,这样提取到的特征不仅包含每个关节点和骨头信息,而且还有他们之间的依赖关系,促进了动作识别。另外一个问题是原始的骨架结构是手动设计的,不能根据动作识别任务进行优化,作者提出了一个自适应的图结构代替原始的固定的图结构,并且使用一个简单有效的方法一方面保证了训练过程的稳定性,另一方面有不失灵活,在性能上带来了显著提升。双流网络给基于RGB的动作识别带来了性能上的提升,作者也采用双流结构将空间流和时间流的结果融合来增强算法性能。

最后的模型在基于骨骼的动作识别任务的两个大规模数据集(NTURGBD和骨骼动力学)上进行了评估,两者的性能都超过了最新水平。本文的主要工作包括:

  • 据我们所知,这是第一个将骨骼数据表示为有向无环图来模拟关节和骨骼之间的依赖关系的工作。设计了一种新的有向图神经网络来提取这些依赖关系,用于最终的动作识别任务。
  • 采用自适应学习的图形结构,在训练过程中结合模型参数进行训练和更新,以更好地适应动作识别任务。
  • 提取连续帧间的运动信息进行时间信息建模。空间和运动信息都被输入到一个双流框架中,用于最终的识别任务。
  • 在基于骨架的动作识别的两个大规模数据集上,我们的模型以显著的优势超过了最新的性能。



Related work

  1. 基于骨架的动作识别

    现有的方法主要分为三类:基于序列的方法、基于图像的方法、基于图的方法。基于序列的方法将骨架信息表示成有着设计好的遍历规则的骨架序列,然后用RNN进行动作识别;基于图像的方法通常把骨架信息表示成伪图像;基于图的方法用图来表示骨架信息,天然地保留了人体骨架信息。
  2. 图网络

    图结构是比图像和序列更一般化的数据结构,它不能直接用深度学习模块,比如CNN、RNN直接进行建模。用图网络结构来解决问题已经被探索了很多年了。



Method

通常,原始骨架数据是一系列帧,每个帧都包含一组关节坐标。给定骨骼序列,首先根据关节的二维或三维坐标提取骨骼信息。然后,将每个帧中的关节和骨骼(空间信息)表示为有向无环图中的顶点和边缘,并将其输入有向无环图神经网络(DGNN)中提取特征进行动作识别。最后,在双流框架下提取运动信息,并与空间信息结合,进一步提高了性能。



Bone Information

以往的研究已经表明了将关节信息和骨骼信息结合起来进行基于骨骼的动作识别的重要性。骨骼表示为两个连接关节之间的坐标差。以三维骨骼数据为例:原始数据中的关节被表示为具有三个元素的向量,即其x坐标、y坐标和z坐标。给定两个关节



v

1

=

(

x

1

,

y

1

,

z

1

)

v_1=(x_1,y_1,z_1)







v










1




















=








(



x










1


















,





y










1


















,





z










1


















)









v

2

=

(

x

2

,

y

2

,

z

2

)

v_2=(x_2,y_2,z_2)







v










2




















=








(



x










2


















,





y










2


















,





z










2


















)





,从



v

1

v_1







v










1

























v

2

v_2







v










2





















连接的骨骼被表示为两个关节向量的差,即



e

v

1

v

2

=

(

x

1

x

2

y

1

y

2

z

1

z

2

)

e_{v_1,v_2}=(x_1−x_2,y_1−y_2,z_1−z_2)







e












v










1






















v










2





































=








(



x










1






















x










2






















y










1






















y










2






















z










1






















z










2


















)







Graph Construction

传统的方法总是将骨架数据建模为一个向量序列或一个伪图像,由RNNs或CNNs处理。但是,这些表示忽略了关节和骨骼之间的运动相关性。在人类分析中,骨骼数据总是根据人体的物理结构建模为基于树的图形结构。在这项工作中,我们将骨骼数据表示为一个有向非循环图(DAG),其中关节为顶点,骨骼为边。每条边的方向由顶点和根顶点之间的距离确定,其中离根顶点较近的顶点指向离根顶点较远的顶点。这里,根顶点被定义为骨架的重心。图1显示了一个骨架及其对应的有向图表示的示例,其中顶点1是根顶点。这种表现是直观的,因为人体是一个自然的关节系统。离人体中心较远的关节总是由离中心较近的相邻关节进行物理控制。例如,手腕的位置由肘部的位置和前臂的形状决定。这样,我们将前臂表示为从肘部指向手腕的定向边。

形式上,对于每个顶点



v

i

v_i







v










i





















,我们将指向它的边定义为传入边



e

i

e^-_i







e










i






























,从它指出的边为传出边



e

i

+

e^+_i







e










i








+





















。类似地,对于定向边



e

j

e_j







e










j





















,我们定义它是从源顶点



v

j

s

v^s_j







v










j








s





















到目标顶点



v

j

t

v^t_j







v










j








t





















的向量。如果



v

i

v_i







v










i

























e

j

e_j







e










j





















的目标(源)顶点,则



e

j

e_j







e










j

























v

i

v_i







v










i





















的传入(传出)边,反之亦然。例如,如图2(a)所示,



v

1

v_1







v










1

























v

2

v_2







v










2





















分别是



e

1

e_1







e










1





















的源顶点和目标顶点。



e

1

e_1







e










1

























v

2

v_2







v










2





















的传入边。



e

2

e_2







e










2

























e

3

e_3







e










3

























v

2

v_2







v










2





















的outgoing edges。请注意,每条边只有一个源顶点和一个目标顶点。对于一个顶点,其传入边和传出边的数目是不同的。我们用



ε

i

\varepsilon^-_i







ε










i


































ε

i

+

\varepsilon^+_i







ε










i








+





















分别表示顶点



v

i

v_i







v










i





















的传入边集和传出边集。这样,基于骨架的帧可以表示为有向图



G

=

(

V

E

)

G=(V,E)






G




=








(


V





E


)





,其中



V

V






V





是一组顶点(关节),



E

E






E





是一组有向边(骨骼)。基于骨架的视频是一系列帧,可以表示为



S

=

G

1

G

2

G

T

S={G_1,G_2,···,G_T}






S




=










G










1






















G










2








































G










T






















,其中



T

T






T





表示视频的长度。

在这里插入图片描述

在这里插入图片描述



Directed graph neural network

由于我们将骨骼数据表示为有向图,现在的问题在于如何提取图中包含的信息进行动作分类,特别是如何利用图中关节和骨骼之间的依赖关系。本文提出了一种有向图神经网络(DGNN)来解决这一问题。网络包含多个层,每个层都有一个包含顶点和边的属性的图,并输出具有更新属性的同一个图。这里,属性表示编码为向量的顶点和边的属性。在每一层中,顶点和边的属性根据其相邻的边和顶点进行更新。在底层,每个顶点或边只能从其相邻边或顶点接收属性。这些层中的模型旨在在更新属性时提取顶点和边的局部信息。例如,模型可以提取关节的角度信息,只需要一个关节及其两个相连骨骼的信息。在顶层,来自彼此距离较远的关节和骨骼的消息可以累积在一起。因此,所提取的信息对于识别任务来说更具有全局性和语义性。这个概念类似于卷积神经网络的原理,即层次表示和局部性。与CNN相比,DGNN是为有向无环图设计的,该图可以对骨架数据的基于树的结构进行建模。这种设计也类似于以往基于骨骼的动作识别中的“身体部位”概念,其目的是限制人体局部关节的建模。但是,我们的方法不需要手工设计分割策略,并且取得了比这些方法更好的性能。



Directed graph network block

有向图网络(DGN)块是有向图神经网络的基本块,它包含两个更新函数



h

v

h_v







h










v

























h

e

h_e







h










e





















,两个聚合函数



g

e

g^{e^-}







g












e



































g

e

+

g^{e^+}







g












e










+




















。更新函数用于根据顶点和边的连接边和顶点更新顶点和边的属性。聚合函数用于聚合连接到一个顶点的多个传入(传出)边中包含的属性。这是因为连接到每个顶点的传入(传出)边的数目是可变的,而参数的数目是固定的。由于这些边没有明显的顺序,聚合函数应该对其输入的排列保持不变,并且可以接受可变数量的参数,例如平均池化、最大池化和元素级求和。从形式上讲,这个过程如下:





e

ˉ

i

=

g

e

(

ε

i

)

(

1

)

\bar e_i^-=g^{e^-}(\varepsilon^-_i)\qquad\qquad\qquad(1)














e






ˉ















i





























=









g












e




























(



ε










i



























)








(


1


)










e

ˉ

i

+

=

g

e

+

(

ε

i

+

)

\bar e_i^+=g^{e^+}(\varepsilon^+_i)\qquad\qquad\qquad














e






ˉ















i








+




















=









g












e










+

















(



ε










i








+


















)
















v

i

=

h

v

(

[

v

i

,

e

ˉ

j

,

e

ˉ

j

+

]

)

v_i’=h^v([v_i,\bar e_j^-,\bar e_j^+])\qquad\qquad







v










i































=









h










v









(


[



v










i


















,












e






ˉ















j



























,












e






ˉ















j








+


















]


)














e

j

=

h

e

(

[

e

j

,

v

j

s

,

v

j

t

]

)

e_j’=h^e([e_j,v_j^{s’},v_j^{t’}])\qquad\qquad







e










j































=









h










e









(


[



e










j


















,





v










j










s







































,





v










j










t







































]


)










其中[·]表示连接操作。



v

v’







v





























e

e’







e

























分别是



v

v






v









e

e






e





的更新版本。该过程包括四个步骤:

  1. 对于每个顶点



    v

    i

    v_i







    v










    i





















    ,指向该顶点的所有边都由传入的聚合函数



    g

    e

    g^{e^-}







    g












    e































    处理,该函数返回聚合结果



    e

    ˉ

    i

    \bar e_i^-














    e






    ˉ















    i






























  2. 与步骤1类似,所有从



    v

    i

    v_i







    v










    i





















    发出的边都由传出的聚合函数



    g

    e

    +

    g^{e^+}







    g












    e










    +




















    处理,该函数返回聚合结果



    e

    ˉ

    i

    +

    \bar e_i^+














    e






    ˉ















    i








    +
























  3. v

    i

    v_i







    v










    i

























    e

    ˉ

    i

    +

    \bar e_i^+














    e






    ˉ















    i








    +





















    连接并输入到顶点更新函数



    h

    v

    h^{v}







    h











    v













    中,其中返回值



    v

    i

    v_i’







    v










    i




































    v

    i

    v_i







    v










    i





















    的更新。

  4. 对于每个边



    e

    j

    e_j







    e










    j





















    ,其源顶点、目标顶点和自身被连接起来并由边更新函数



    h

    e

    h^e







    h










    e












    处理。函数返回



    e

    j

    e’_j







    e










    j
































    ,这是边



    e

    j

    e_j







    e










    j





















    的更新版本。

    如图2所示,该过程也可以概括为顶点更新过程,接着是边更新过程。通过大量的实验,我们选择了平均池化作为传入边和传出边的聚合函数,并选择了单一的完全连接层作为更新函数



Implementation of the DGN block

在实现DGN块时,顶点的输入数据实际上形成



C

×

T

×

N

v

C×T×N_v






C




×








T




×









N










v





















的tensor



f

v

f_v







f










v





















,其中C是通道数,T是帧数。



n

v

n_v







n










v





















表示骨架图中顶点的数目。同样,边的数据形成一个



C

×

T

×

N

e

C×T×N_e






C




×








T




×









N










e





















张量



f

e

f_e







f










e





















,其中



N

e

N_e







N










e





















是图中边的个数。用这种形式的输入数据实现DGN块是不令人满意的。根据最后一节,实现DGN块的关键是找到每个顶点的传入边和传出边(即



ε

i

\varepsilon^-_i







ε










i


































ε

i

+

\varepsilon^+_i







ε










i








+





















),并找到每个边的源顶点和目标顶点(即



v

j

s

v^s_j







v










j








s

























v

j

t

v^t_j







v










j








t





















)。为此,我们使用图的关联矩阵。给定一个有



N

v

N_v







N










v





















顶点和



N

e

N_e







N










e





















边的有向图,A的关联矩阵是



N

v

×

N

e

N_v×N_e







N










v




















×









N










e





















矩阵,其元素(



A

i

,

j

,

i

=

1

,

.

.

.

,

N

v

;

j

=

1

,

.

.

.

,

N

e

)

A_ {i,j},i=1,…,N_v;j=1,…,N_e)







A











i


,


j



















,




i




=








1


,




.


.


.


,





N










v


















;




j




=








1


,




.


.


.


,





N










e


















)





表示对应顶点(



v

j

v_j







v










j





















)和边(



e

i

e_i







e










i





















)之间的关系。具体来说,如果



v

i

v_i







v










i

























e

j

e_j







e










j





















的源顶点,那么



A

i

j

=

1

A_{ij}=-1







A











i


j





















=











1





。如果



v

i

v_i







v










i

























e

j

e_j







e










j





















的目标顶点,则



A

i

j

=

1

A_{ij}=1







A











i


j





















=








1





。如果



v

i

v_i







v










i

























e

j

e_j







e










j





















之间没有连接,则



A

i

j

=

0

A_{ij}=0







A











i


j





















=








0







为了分离源顶点和目标顶点,我们使用



A

s

A^s







A










s












表示源顶点的关联矩阵,它只包含小于0的A元素的绝对值。类似地,我们定义



A

t

A^t







A










t












为目标顶点的关联矩阵,它只包含A中大于0的元素。例如,对于图1(a)所示的图,等式2示出关联矩阵及其对应的



A

s

A^s







A










s
















A

t

A^t







A










t


















A

=

[

1

1

0

0

0

1

1

0

0

1

0

1

]

T

A

s

=

[

1

0

0

0

0

1

0

0

0

1

0

0

]

T

A

t

=

[

0

1

0

0

0

0

1

0

0

0

0

1

]

T

(

2

)

\begin{gathered} A = \begin{bmatrix} -1 & 1 & 0 & 0 \\ 0 & -1 & 1 & 0 \\ 0 & -1 & 0 & 1\end{bmatrix}^T \\ A^s = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 1 & 0 & 0\end{bmatrix}^T \quad \\ A^t = \begin{bmatrix} 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{bmatrix}^T \quad \\ \end{gathered}(2)
















A




=
























































1








0








0





























1











1











1





























0








1








0





























0








0








1

































































T
















A










s











=





















































1








0








0





























0








1








1





























0








0








0





























0








0








0

































































T


















A










t











=





















































0








0








0





























1








0








0





























0








1








0





























0








0








1

































































T




























(


2


)







其中



T

T






T





表示矩阵的转置运算。给定一个输入张量和关联矩阵,我们现在可以过滤所需的边和顶点,并通过矩阵乘法来执行聚合函数。例如,给定



f

v

f_v







f










v

























A

s

A^s







A










s












,我们首先将



f

v

f_v







f










v





















重塑为



C

T

×

N

v

CT×N_v






C


T




×









N










v





















矩阵;然后,



f

v

f_v







f










v

























A

s

A^s







A










s












的乘法能够提供一个



C

T

×

N

e

CT×N_e






C


T




×









N










e





















张量。根据矩阵乘法的定义,该张量的每个元素对应于对应边的源顶点之和。注意,本文中使用的聚合函数是平均池化操作,关联矩阵需要规范化。具体地说,我们定义



A

~

=

A

Λ

1

\tilde A=A\Lambda^{-1}













A






~









=








A



Λ














1













是A的标准化版本,其中



Λ

\Lambda






Λ





是对角矩阵,



Λ

i

i

=

j

A

i

j

+

ϵ

\Lambda_{ii}=\sum_jA_{ij}+\epsilon







Λ











i


i





















=




















j





















A











i


j





















+








ϵ









ϵ

\epsilon






ϵ





是一个避免被零除的小数字。通过这些修改,等式1被转换为




f

v

=

H

v

(

[

f

v

,

f

e

A

~

s

T

,

f

e

A

~

t

T

]

)

f

e

=

H

e

(

[

f

e

,

f

v

A

~

s

,

f

v

A

~

t

]

)

(

3

)

\begin{gathered} f_v’=H_v([f_v,f_e\tilde A^{s^T},f_e\tilde A^{t^T}]) \\ f_e’=H_e([f_e,f_v\tilde A^{s},f_v\tilde A^{t}]) \end{gathered}(3)

















f










v































=





H










v


















(


[



f










v


















,





f










e


























A






~

















s










T

















,





f










e


























A






~

















t










T

















]


)









f










e































=





H










e


















(


[



f










e


















,





f










v


























A






~
















s










,





f










v


























A






~
















t










]


)



















(


3


)






其中H表示单层完全连接层,即公式1中的更新函数。与传统的卷积层类似,我们在每个DGN块之后添加BN层和ReLU层



Adaptive DGN block

&emps;&emps;DGN块的输入图是根据人体的自然结构手工设计的。我们认为此配置可能不适用于动作识别任务。例如,左手和右手之间没有联系;但是,对于许多动作,如拍手和拥抱,双手之间的关系对于识别很重要。为了使图的构造更加灵活,传统的方法是在训练过程中通过学习图结构的拓扑结构来构造一个自适应图。例如,AAAI2018 ST-GCN在原始邻接矩阵上应用注意图,为不同的边指定不同的重要性级别。如果使用



A

o

A_o







A










o





















表示原始邻接矩阵,则新的邻接矩阵A由



A

=

P

A

o

A=P A_o






A




=








P



A










o





















计算,其中P的元素初始化为1,并在训练过程中更新。然而,乘法运算不能改变原始邻接矩阵中为0的元素,这意味着这种方法只能改变现有边的重要性,并且不能添加新边,例如双手之间的边。与ST-GCN不同,CVPR2019 2s-AGCN直接将邻接矩阵设置为网络参数。为了稳定训练过程,他们设置



A

=

A

o

+

P

A=A_o+P






A




=









A










o




















+








P





,其中P的大小与



A

o

A_o







A










o





















相同,并用0初始化。这样,在学习过程中,如果需要,可以通过参数P添加新的边。尽管如此,由于



A

o

A_o







A










o





















是不可修改的,我们不能删除我们不想要的边,这也降低了模型的灵活性。但是,如果去掉



A

o

A_o







A










o





















,直接学习没有任何限制的图结构会降低性能。

在这项工作中,我们发现有或没有



A

o

A_o







A










o





















的情况之间的区别主要在于训练过程的开始(注意,这里A表示关联矩阵,而不是前面工作中的邻接矩阵)。由于训练过程开始时存在较多的不确定性,该结果是直观的;因此,该模型约束较少,但参数较多,容易收敛到局部最优。增加一个固定拓扑图相当于基于人体先验知识对模型进行正则化,有助于模型收敛到全局最优。在此基础上,我们提出了一个简单有效的策略来解决这个问题。我们直接将A作为模型的参数,但在前几个训练阶段对其进行了修正。早期固定图形结构可以减轻训练的难度,后期不固定图形结构可以为图形构建提供更大的灵活性。



Temporal information modeling

通常,动作被记录为基于骨架的帧序列。上面介绍的DGN块仅能处理单个帧的空间信息,因此,我们现在进入了在骨架序列中建模时间动态的任务。pseudo-3D-CNN[23]在基于RGB的动作识别领域显示了其优越性,它先用二维卷积对空间信息进行建模,然后用一维卷积对时间信息进行建模。伪三维CNN通过将时空维度分离,可以更经济有效地对时空信息进行建模。受此启发,在更新每个DGN块中关节和骨骼的空间信息后,我们应用一维卷积方法对时间信息进行建模。这很容易实现,因为所有帧中的相同关节或骨骼可以自然地组织为1D序列。

与DGN块类似,每个1D卷积层后面跟着BN层和ReLU层以形成时间卷积块(TCN)。有向图神经网络(DGNN)的总体结构有9个单元,每个单元包含一个DGN块和一个TCN块。单元的输出通道为64,64,64,128,128,256,256和256。在类预测的末尾添加一个全局平均池层和一个softmax层。



Two-Stream Framework

作者提取了关节的运动和骨骼的变形来帮助识别。由于骨架数据被表示为关节的坐标,因此关节的运动很容易被计算为沿时间维度的坐标差。类似地,骨骼的变形表示为连续帧中同一骨骼的向量差。

双流结构与2s-GCN相同,都是利用骨骼长度和方向信息作为第二类信息,和节点信息组成双流结构,最后用加和进行融合产生最后的打分值。



Experiments

1.消融实验

2s-ST-GCN表示节点和骨头信息双流结构应用在ST-GCN上

1s-ST-GCN表示节点和骨头信息合为一流结构应用在ST-GCN上

在这里插入图片描述

2.自适应的DGN

在这里插入图片描述

3.双流网络对比

在这里插入图片描述

4.和state-of-the-art对比

在这里插入图片描述



版权声明:本文为qq_33331451原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_33331451/article/details/105688740