图神经网络(GNNs,Graph Neural Networks)是一类专为图结构数据设计的弱小神经网络,长于捕捉数据之间的复杂咨询和相关。
相较于传统神经网络,GNN在解决相互关联的数据点时更具优点,比如在社交网络剖析、分子结构建模或交通系统提升等畛域,GNN能够施展出出色的功能。
1 GNN概述
图神经网络是近年来新兴的一类深度学习模型,长于解决图形数据。
传统神经网络解决的是像数字列表这样的便捷数据,而图神经网络能解决更复杂的图形数据,比如由很多点(称为节点)和衔接这些点的线(称为边)组成的图形,并且能从这些图形中找出关键的消息。
其**机制是让图中的每个节点经过与临近节点的消息替换,来学习自己在全体图形中的位置和个性。这种基于消息传递的方法,让图神经网络能够极速捕捉到图形里的结构和相关。
这种技术在很多畛域都大放异彩,比如社交网络剖析、分子结构预测、常识图谱构建等等。
随着迷信家们始终地钻研和翻新,图神经网络也在蓬勃开展,衍生出多种新模型,为机器学习在图形数据畛域的运行开拓了新的或者性。
2 图卷积网络(Graph Convolutional Networks)
便捷来说,图卷积网络(GCN)跟传统神经网络一样,是由多层结构重叠而成的。
在深度学习中,图卷积网络(GCN)的**是图卷积层,其上班机制与卷积神经网络(CNN)的卷积层颇为相似。
在CNN中,卷积层担任捕捉图像中部分区域的像素消息,这个环节称之为“感触野”(Receptive Field),经过它,咱们可以提取出图像的简化和低维特色。
GCN层的上班原理与之相似,不过不是解决像素,而是解决图中的节点消息。它经过搜集每个节点及其相邻节点的消息,来构建节点的示意,从而捕捉图中的结构特色。
3 推导GCN方程式
来聊聊图卷积网络(GNN)的数学原理。
首先,GNN的输入是一个图,这个图可以用节点特色的矩阵和邻接矩阵来示意。邻接矩阵里的1代表两个节点之间有衔接,0则示意没有衔接。
这个例子的邻接矩阵是这样的:
节点 1 -- 节点 2|节点 3
当咱们用A乘以节点特色矩阵X,获取的结果是每个节点的街坊对每个特色的奉献总和。便捷来说,就是把每个节点i的街坊j的特色加起来:
但是,咱们不应漠视节点自身的特色。为了将节点自身的特色也思考出去,可以在邻接矩阵A的对角线上参与1,这在数学上相当于引入了单位矩阵I。
这样:
但是,还有一个疑问:节点的街坊数量或者不一样。有的节点有几百个街坊,有的或者只要一两个。为了偏心起见,咱们须要对总和启动归一化。
一种方法是用每个节点的街坊数(也就是节点的度)来除以这个总和。可以创立一个对角线上是节点度的对角度矩阵D,而后归一化方程:
这样:
直观地说,行归一化就是取街坊特色的平均值,而列归一化则思考了街坊的街坊数。
为了两者统筹,驳回对称归一化:
这思考了节点的街坊数和街坊的街坊数。
这样一来,咱们的方程式就越来越完整了!
最后,咱们须要一些参数来训练机器学习模型,就像在线性回归中那样,可以便捷地拔出一个权重矩阵。
而且,咱们知道参与非线性可以提供更好的特色示意,所以还可以在下面加一个ReLU激活函数。
最后:
4 PyTorch 成功
接上去,看看如何在 PyTorch 中成功图卷积网络。
首先,在类的初始化方法__init__中,咱们会设置好邻接矩阵A、度矩阵D和权重矩阵W。
而后,在模型的前向流传环节中,应用这些组件来构建节点的新特色矩阵H。
import torchimport torch.nn as nnimport torch.nn.functional as Fclass GCNLayer(nn.Module):"""GCN 层参数:input_dim (int): 输入的维度output_dim (int): 输入的维度(softmax 散布)A (torch.Tensor): 2D 邻接矩阵"""def __init__(self, input_dim: int, output_dim: int, A: torch.Tensor):super(GCNLayer, self).__init__()self.input_dim = input_dimself.output_dim = output_dimself.A = A# A_hat = A + Iself.A_hat = self.A + torch.eye(self.A.size(0))# 创立对角度矩阵 Dself.ones = torch.ones(input_dim, input_dim)self.D = torch.matmul(self.A.float(), self.ones.float())# 提取对角元素self.D = torch.diag(self.D)# 创立一个新张量,对角线上是元素,其余中央是零self.D = torch.diag_embed(self.D)# 创立 D^{-1/2}self.D_neg_sqrt = torch.diag_embed(torch.diag(torch.pow(self.D, -0.5)))# 初始化权重矩阵作为参数self.W = nn.Parameter(torch.rand(input_dim, output_dim))def forward(self, X: torch.Tensor):# D^-1/2 * (A_hat * D^-1/2)support_1 = torch.matmul(self.D_neg_sqrt, torch.matmul(self.A_hat, self.D_neg_sqrt))# (D^-1/2 * A_hat * D^-1/2) * (X * W)support_2 = torch.matmul(support_1, torch.matmul(X, self.W))# ReLU(D^-1/2 * A_hat * D^-1/2 * X * W)H = F.relu(support_2)return Hif __name__ == "__main__":# 示例用法input_dim = 3# 假定输入维度是 3output_dim = 2# 假定输入维度是 2# 示例邻接矩阵A = torch.tensor([[1., 0., 0.],[0., 1., 1.],[0., 1., 1.]])# 创立 GCN 层gcn_layer = GCNLayer(input_dim, output_dim, A)# 示例输入特色矩阵X = torch.tensor([[1., 2., 3.],[4., 5., 6.],[7., 8., 9.]])# 前向传递output = gcn_layer(X)print(output)# tensor([[ 6.3438,5.8004],#[13.3558, 13.7459],#[15.5052, 16.0948]], grad_fn=<ReluBackward0>)
本文转载自,作者: