赞
踩
图卷积操作(Graph Convolution Operation)是一种针对图结构数据的特殊卷积操作。
在卷积神经网络(CNN)中,卷积操作常在网格数据(如图片)上进行。相比之下,图卷积操作是为了处理不规则的图结构数据而设计的。
在图卷积操作中,节点的特征表示是根据邻居节点的特征和自身的特征来更新的。这个过程可以视为在图上的信息传播和聚合操作。
具体来说,一个节点的新特征是其邻居节点特征的加权平均,权重通常由节点之间的连接和它们的度(即连接数)决定。
给定一个节点 ii,其嵌入
h
i
h_i
hi 表达为:
h
i
=
1
deg
(
i
)
∑
j
∈
N
(
i
)
x
j
W
T
h_i=\frac{1}{\deg(i)}\sum_{j\in N(i)}x_jW^T
hi=deg(i)1j∈N(i)∑xjWT
其中
x
j
x_j
xj 是邻居节点的输入特征,
W
T
W^T
WT 是转置的GCN权重矩阵,
deg
(
⋅
)
\deg(\cdot)
deg(⋅)是某点的度数,
N
(
⋅
)
N(\cdot)
N(⋅)返回该点的邻居节点。
为了在Python中实现GCN,我们可以使用PyTorch和PyTorch Geometric:
import torch from torch_geometric.nn import GCNConv # 定义图卷积层 class GraphConvolutionLayer(torch.nn.Module): def __init__(self, in_features, out_features): super(GraphConvolutionLayer, self).__init__() self.conv = GCNConv(in_features, out_features) def forward(self, x, edge_index): x = self.conv(x, edge_index) return x # 示例:输入特征和边索引 in_features = 2 out_features = 64 edge_index = torch.tensor([[0, 1], [1, 2], [2, 0]], dtype=torch.long).t().contiguous() x = torch.rand((3, in_features)) # 3个节点,每个节点2个特征 # 创建图卷积层实例 gcn_layer = GraphConvolutionLayer(in_features, out_features) output = gcn_layer(x, edge_index) print(output)
不带归一化的矩阵乘法形式可以表示为:
H
=
A
~
X
W
T
H=\tilde A XW^T
H=A~XWT
在这里,
H
H
H 代表输出,即这张图的节点特征新表示,
A
~
=
A
+
I
\tilde A= A + I
A~=A+I 是邻接矩阵加上自环,
X
X
X是节点特征矩阵,
W
T
W^T
WT是转置的权重矩阵。
接下来是GCN的另一种实践,比PyTorch Geometric更灵活,特别是在处理基于骨架的动作识别这种灵活的图结构建模问题:
import torch import torch.nn as nn class SpatialGraphConvolution(nn.Module): def __init__(self, in_channels, out_channels, s_kernel_size=1): super().__init__() self.s_kernel_size = s_kernel_size # 空间核大小 # 由于下面的卷积层是一个1x1卷积,因此它实际上是对特征进行线性变换(即对应上文式子里的W) self.conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels * s_kernel_size, kernel_size=1) def forward(self, x, A): """ A的维度维度:空间核大小, 图的节点数, 图的节点数 A应当之前就被正则化完毕 """ # 应用1x1卷积进行特征变换 x = self.conv(x) n, kc, t, v = x.size() # 获取输出特征的维度:小批次数据样本数、节点特征通道、时间步、顶点数 # 重塑特征以匹配空间核的维度 x = x.view(n, self.s_kernel_size, kc // self.s_kernel_size, t, v) # 使用爱因斯坦求和约定来进行张量运算。这里执行的是图卷积操作。 # 'nkctv,kvw->nctw'表示对n(批大小)、k(空间核)、c(通道)、t(时间步)、v(顶点数)、w(邻接矩阵维度)的张量进行操作 x = torch.einsum('nkctv,kvw->nctw', (x, A)) # 返回连续的内存布局的张量,有助于后续操作的性能优化 return x.contiguous()
参考资料:
https://arxiv.org/pdf/1801.07455.pdf
https://github.com/ugrkilc/ST-GCN/tree/main
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。