图卷积网络(Graph Convolutional Network,GCN)是一种深度学习模型,专门用于处理图结构数据,如社交网络、推荐系统中的用户-物品关系等。GCN 可以学习节点在图中的表示,并利用这些表示进行节点分类、链接预测等任务。它的核心思想是通过卷积操作在图结构上进行信息传递和聚合,从而捕捉节点之间的关系和特征。
推荐阅读文章何时能懂你的心——图卷积神经网络(GCN)
举例说明
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch_geometric.datasets import Planetoid
from torch_geometric.data import DataLoader
from torch_geometric.nn import GCNConv
# 加载一个小规模的图数据集(这里使用Cora数据集)
dataset = Planetoid(root='.', name='Cora', transform=None, pre_transform=None)
data = dataset[0]
# 定义一个简单的GCN模型
class GCN(nn.Module):
def __init__(self, in_channels, hidden_channels, out_channels):
super(GCN, self).__init__()
self.conv1 = GCNConv(in_channels, hidden_channels)
self.conv2 = GCNConv(hidden_channels, out_channels)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return F.log_softmax(x, dim=1)
# 定义模型、损失函数和优化器
model = GCN(in_channels=dataset.num_node_features, hidden_channels=16, out_channels=dataset.num_classes)
criterion = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 将数据加载器包装在PyTorch的DataLoader中
loader = DataLoader(dataset, batch_size=64, shuffle=True)
# 训练模型
model.train()
for epoch in range(200):
for batch in loader:
optimizer.zero_grad()
output = model(batch.x, batch.edge_index)
loss = criterion(output[batch.train_mask], batch.y[batch.train_mask])
loss.backward()
optimizer.step()
# 测试模型
model.eval()
with torch.no_grad():
pred = model(data.x, data.edge_index).argmax(dim=1)
correct = pred[data.test_mask] == data.y[data.test_mask]
accuracy = correct.sum() / data.test_mask.sum().item()
print(f'Test Accuracy: {accuracy:.4f}')
这段代码实现了一个简单的图卷积网络(GCN)模型,并在Cora数据集上进行训练和测试。以下是对代码的主要解释:
-
导入必要的库:
import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torch_geometric.datasets import Planetoid from torch_geometric.data import DataLoader from torch_geometric.nn import GCNConv
这里使用了PyTorch作为深度学习框架,以及Torch Geometric库,该库专门用于处理图结构数据。
-
加载Cora数据集:
dataset = Planetoid(root='.', name='Cora', transform=None, pre_transform=None) data = dataset[0]
使用Planetoid类加载Cora数据集,并获取第一个图数据(Cora只包含一个图)。
data
对象包含节点特征、边索引、训练/验证/测试集的掩码等信息。 -
定义GCN模型:
class GCN(nn.Module): def __init__(self, in_channels, hidden_channels, out_channels): super(GCN, self).__init__() self.conv1 = GCNConv(in_channels, hidden_channels) self.conv2 = GCNConv(hidden_channels, out_channels) def forward(self, x, edge_index): x = self.conv1(x, edge_index) x = F.relu(x) x = F.dropout(x, training=self.training) x = self.conv2(x, edge_index) return F.log_softmax(x, dim=1)
这是一个两层的GCN模型,每一层包含一个GCNConv层和一个ReLU激活函数。模型的最后一层使用log_softmax来输出预测结果。
-
定义模型、损失函数和优化器:
model = GCN(in_channels=dataset.num_node_features, hidden_channels=16, out_channels=dataset.num_classes) criterion = nn.NLLLoss() optimizer = optim.Adam(model.parameters(), lr=0.01)
创建GCN模型实例,选择负对数似然损失(NLLLoss)作为损失函数,使用Adam优化器进行参数优化。
-
数据加载器:
loader = DataLoader(dataset, batch_size=64, shuffle=True)
将数据集包装成PyTorch的DataLoader,以便进行批量训练。
-
训练模型:
model.train() for epoch in range(200): for batch in loader: optimizer.zero_grad() output = model(batch.x, batch.edge_index) loss = criterion(output[batch.train_mask], batch.y[batch.train_mask]) loss.backward() optimizer.step()
在训练循环中,模型经过多个epoch的训练,通过计算损失并反向传播来更新模型参数。
-
测试模型:
model.eval() with torch.no_grad(): pred = model(data.x, data.edge_index).argmax(dim=1) correct = pred[data.test_mask] == data.y[data.test_mask] accuracy = correct.sum() / data.test_mask.sum().item() print(f'Test Accuracy: {accuracy:.4f}')
在测试模式下,通过使用测试集进行预测,计算准确率并输出测试准确率。
总体而言,这段代码展示了如何使用PyTorch和Torch Geometric实现一个基本的GCN模型,并在图数据集上进行训练和测试。
可视化
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
# 将GCN模型的中间层输出(节点表示)提取出来
model.eval()
with torch.no_grad():
node_representations = model.conv1(data.x, data.edge_index).numpy()
# 使用t-SNE进行降维
tsne = TSNE(n_components=2)
node_embeddings_2d = tsne.fit_transform(node_representations)
# 可视化节点嵌入
plt.figure(figsize=(8, 8))
plt.scatter(node_embeddings_2d[:, 0], node_embeddings_2d[:, 1], c=data.y, cmap='jet', s=10)
plt.title('t-SNE Visualization of Node Embeddings')
plt.show()
这段代码使用t-SNE对GCN模型中间层的节点表示进行降维,并通过散点图展示节点在二维空间的分布。这有助于观察节点之间的关系和模型的学习效果。