创作不易,您的打赏、关注、点赞、收藏和转发是我坚持下去的动力!
图卷积网络(Graph Convolutional Networks, GCN)是一种能够直接在图结构数据上进行操作的神经网络模型。它能够处理不规则的数据结构,捕获节点之间的依赖关系,广泛应用于社交网络分析、推荐系统、图像识别、化学分子分析等领域。
主流的图卷积网络包括以下几种:
1. 经典图卷积网络(GCN)
经典GCN使用图拉普拉斯算子将卷积操作推广到图数据中,具体而言,它通过对图的邻接矩阵进行归一化操作来进行信息传播。GCN的核心思想是通过卷积操作在每一层中聚合节点邻居的信息,最终对节点进行表示。
示例代码:
import torch
import torch.nn as nn
import torch.nn.functional as F
import networkx as nx
import numpy as np
class GCNLayer(nn.Module):
def __init__(self, in_features, out_features):
super(GCNLayer, self).__init__()
self.weight = nn.Parameter(torch.FloatTensor(in_features, out_features))
nn.init.xavier_uniform_(self.weight)
def forward(self, X, adj):
support = torch.mm(X, self.weight)
output = torch.mm(adj, support)
return output
class GCN(nn.Module):
def __init__(self, in_features, hidden_features, out_features):
super(GCN, self).__init__()
self.layer1 = GCNLayer(in_features, hidden_features)
self.layer2 = GCNLayer(hidden_features, out_features)
def forward(self, X, adj):
X = self.layer1(X, adj)
X = F.relu(X)
X = self.layer2(X, adj)
return F.log_softmax(X, dim=1)
# 创建一个简单的图
G = nx.karate_club_graph()
adj = nx.adjacency_matrix(G).todense()
adj = torch.FloatTensor(adj + np.eye(adj.shape[0])) # 添加自环
degree = np.diag(np.power(np.array(adj.sum(1)), -0.5).flatten())
adj_normalized = torch.FloatTensor(degree @ adj @ degree)
# 节点特征
features = torch.eye(adj.shape[0])
# 创建模型
model = GCN(in_features=adj.shape[0], hidden_features=16, out_features=2)
output = model(features, adj_normalized)
print(output)
2. 图注意力网络(Graph Attention Network, GAT)
GAT是另一种流行的图卷积网络,它通过注意力机制对邻居节点赋予不同的权重,从而实现更灵活的信息聚合。GAT的核心思想是计算目标节点与其邻居节点之间的注意力系数,将邻居节点信息加权求和。
公式:
[ H^{(l+1)}i = \sigma\left( \sum{j \in \mathcal{N}(i)} \alpha_{ij} W H^{(l)}j \right) ]
其中,(\alpha{ij}) 是节点 (i) 和 (j) 之间的注意力系数,(W) 是可训练的权重矩阵。
示例代码:
class GATLayer(nn.Module):
def __init__(self, in_features, out_features, alpha, concat=True):
super(GATLayer, self).__init__()
self.in_features = in_features
self.out_features = out_features
self.alpha = alpha
self.concat = concat
self.W = nn.Parameter(torch.empty(size=(in_features, out_features)))
nn.init.xavier_uniform_(self.W.data, gain=1.414)
self.a = nn.Parameter(torch.empty(size=(2*out_features, 1)))
nn.init.xavier_uniform_(self.a.data, gain=1.414)
self.leakyrelu = nn.LeakyReLU(self.alpha)
def forward(self, h, adj):
Wh = torch.mm(h, self.W) # [N, out_features]
a_input = self._prepare_attentional_mechanism_input(Wh)
e = self.leakyrelu(torch.matmul(a_input, self.a).squeeze(2))
zero_vec = -9e15*torch.ones_like(e)
attention = torch.where(adj > 0, e, zero_vec)
attention = F.softmax(attention, dim=1)
h_prime = torch.matmul(attention, Wh)
if self.concat:
return F.elu(h_prime)
else:
return h_prime
def _prepare_attentional_mechanism_input(self, Wh):
N = Wh.size()[0]
Wh_repeated_in_chunks = Wh.repeat_interleave(N, dim=0)
Wh_repeated_alternating = Wh.repeat(N, 1)
all_combinations_matrix = torch.cat([Wh_repeated_in_chunks, Wh_repeated_alternating], dim=1)
return all_combinations_matrix.view(N, N, 2 * self.out_features)
class GAT(nn.Module):
def __init__(self, nfeat, nhid, nclass, dropout, alpha, nheads):
super(GAT, self).__init__()
self.dropout = dropout
self.attentions = [GATLayer(nfeat, nhid, alpha=alpha, concat=True) for _ in range(nheads)]
for i, attention in enumerate(self.attentions):
self.add_module('attention_{}'.format(i), attention)
self.out_att = GATLayer(nhid * nheads, nclass, alpha=alpha, concat=False)
def forward(self, x, adj):
x = F.dropout(x, self.dropout, training=self.training)
x = torch.cat([att(x, adj) for att in self.attentions], dim=1)
x = F.dropout(x, self.dropout, training=self.training)
x = self.out_att(x, adj)
return F.log_softmax(x, dim=1)
# 实例化并使用GAT模型
model_gat = GAT(nfeat=features.shape[1], nhid=8, nclass=2, dropout=0.6, alpha=0.2, nheads=8)
output_gat = model_gat(features, adj_normalized)
print(output_gat)
以上两个示例展示了GCN和GAT的基础实现。GCN适合对图结构信息进行卷积聚合,而GAT则通过引入注意力机制使得信息的聚合更为灵活。这些方法都能很好地应用于节点分类、链接预测等任务。