前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >图神经网络入门示例:使用PyTorch Geometric 进行节点分类

图神经网络入门示例:使用PyTorch Geometric 进行节点分类

作者头像
deephub
发布于 2024-05-20 06:52:27
发布于 2024-05-20 06:52:27
46500
代码可运行
举报
文章被收录于专栏:DeepHub IMBADeepHub IMBA
运行总次数:0
代码可运行

基于图的神经网络是强大的模型,可以学习网络中的复杂模式。在本文中,我们将介绍如何为同构图数据构造PyTorch Data对象,然后训练不同类型的神经网络来预测节点所属的类。这种类型的预测问题通常被称为节点分类。

我们将使用来自Benedek Rozemberczki, Carl Allen和Rik Sarkar于2019年发布的“Multi-scale Attributed Node Embedding”论文中的Facebook Large Page-Page Network¹数据集。

该数据集包含22,470个Facebook页面,按主题分为四类。由不同大小的特征向量表示。数据集还包含Facebook pages 上跟随其他page的信息。网络中有171,992个链接或边。

数据集

第一步是从URL下载数据集。如果手动下载也是可以的,我们这里是为了方便演示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 wget https://snap.stanford.edu/data/facebook_large.zip

解压后的数据集包含三个独立的文件:

musae_facebook_edges.csv:该文件包含具有两列的Facebook页面之间的连接图,表示id_1和id_2列是相互连接的,最直接的说法就是图的边。

musae_facebook_target.csv:该文件包含数据集中22,470个Facebook Page的描述和类型。我们试图预测的标签是page_type列,这是一个多类标签,它将每个Facebook页面分为四个类之一,这就是我们图数据的节点。

musae_facebook_features.json:这个文件包含每个Facebook Page的特征向量。键是上面文件的节点id,值是特征向量。

创建PyTorch同构数据对象

为了在PyTorch中训练神经网络,我们必须创建一个数据对象。由于我们的数据集包含相同类型的所有节点,我们将创建一个描述同构图的数据对象。

说明:如果数据集包含多种类型的节点或边,则需要创建一个描述异构图的HeteroData数据对象。

第一步是使用pandas读取CSV文件中的节点数据作然后从json文件中提取特征

但是我们导入JSON文件后发现特征向量大小不一致,嵌入的大小从3到31个不等。

一半情况下模型都期望节点属性或特征具有一致的大小,因此我们需要一些特征转操作。我们将从节点特征中创建张量。由于嵌入的最大大小是31,所以以最大值为例

如果一个节点的特征小于31,将用值0填充剩余的元素。然后,对每个节点的特征进行归一化。下面是所有的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 from torch.nn.utils.rnn import pad_sequence
 
 def load_node_csv(path, index_col, **kwargs):
   df = pd.read_csv(path, **kwargs)
   mapping = {i: node_id for i, node_id in enumerate(df[index_col].unique())}
 
   # Load node features
   with open(os.path.join(data_dir, "musae_facebook_features.json"), "r") as json_file:
     features_data = json.load(json_file)
 
   xs = []
   for index, node_id in mapping.items():
     features = features_data.get(str(index), [])
     if features:
       # Create tensor from feature vector
       features_tensor = torch.tensor(features, dtype=torch.float)
       xs.append(features_tensor)
     else:
       xs.append(torch.zeros(1, dtype=torch.float))
     
   # Pad features to have vectors of the same size
   padded_features = pad_sequence([torch.tensor(seq) for seq in xs], batch_first=True, padding_value=0)
   mask = padded_features != 0 # mask to indicate which features were padded
   
   # Create tensor of normaized features for nodes
   mean = torch.mean(padded_features[mask].float())
   std = torch.std(padded_features[mask].float())
 
   x = (padded_features - mean) / (std + 1e-8)  # final x tensor with normalized features
 
   return x
 
 x = load_node_csv(path=os.path.join(data_dir, "musae_facebook_target.csv"), index_col="facebook_id")

上面创建了包含22,470个Facebook Page的特征向量的张量x。

下面就是加载边的数据,也就是建立节点直接的连接

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def load_edge_csv(path, src_index_col, dst_index_col, **kwargs):
   df = pd.read_csv(path, **kwargs)
 
   src = df[src_index_col].values
   dst = df[dst_index_col].values
   edge_index = torch.tensor([src, dst])
 
   return edge_index
 
 edge_index = load_edge_csv(path=os.path.join(data_dir, "musae_facebook_edges.csv"), src_index_col="id_1", dst_index_col="id_2")

得到了一个长度为2的PyTorch张量,一个用于源节点,另一个用于目标节点,总计171,002条边。

清理完数据并将其转换为正确的类型后,我们现在可以为同构图创建PyTorch data对象了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 # Create homogeneous graph using PyTorch's Data object
 data = Data(x=x, edge_index=edge_index, y=y)

结果数据对象包含22,470个节点,每个节点由大小为31的特征向量表示,在删除重复项和自循环后,节点之间有171,002条边:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 >>> Data(x=[22470, 31], edge_index=[2, 171002], y=[22470])

分割数据

为了训练和验证,数据集被分成70%用于训练和30%用于测试,前15,728个节点用于训练,最后6,742个节点用于测试集。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 # Calculate no. of train nodes
 num_nodes = data.num_nodes
 train_percentage = 0.7
 num_train_nodes = int(train_percentage * num_nodes)
 
 # Create a boolean mask for train mask
 train_mask = torch.zeros(num_nodes, dtype=torch.bool)
 train_mask[: num_train_nodes] = True
 
 # Add train mask to data object
 data.train_mask = train_mask
 
 # Create a boolean mask for test mask
 test_mask = ~data.train_mask
 data.test_mask = test_mask

我们使用mask来标识训练和验证集

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 >>> Data(
   x=[22470, 31], 
   edge_index=[2, 171002], 
   y=[22470], 
   num_classes=4, 
   train_mask=[22470], 
   test_mask=[22470]
 )

训练神经网络

我们现在已经可以训练模型了。下面将训练两种不同类型的神经网络,并对它们进行比较。

在训练模型之前我们可以先可视化节点是什么样的

在上面的图表中,似乎有两个大团,但类别区分并不明显。

1、多层感知网络(MLP)

作为对比,我们先训练一个最基础的mlp看看表现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 from torch.nn import Linear
 import torch.nn.functional as F
 
 class MLP(torch.nn.Module):
   def __init__(self):
     super().__init__()
     torch.manual_seed(123)
     self.lin1 = Linear(data.num_features, 32)
     self.lin2 = Linear(32, 32)
     self.lin3 = Linear(32, 16)
     self.lin4 = Linear(16, 8)
     self.lin5 = Linear(8, data.num_classes)
 
   def forward(self, x):
     x = self.lin1(x)
     x = F.relu(x)
     x = self.lin2(x)
     x = F.relu(x)
     x = self.lin3(x)
     x = F.relu(x)
     x = self.lin4(x)
     x = F.relu(x)
     x = self.lin5(x)
     x = torch.softmax(x, dim=1)
 
     return x

创建对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class_weights = torch.tensor([1 / i for i in df_agg_classes["proportion"].values], dtype=torch.float)
 model = MLP()
 criterion = torch.nn.CrossEntropyLoss(weight=class_weights)
 optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

最终的结构如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 >>> MLP(
   (lin1): Linear(in_features=31, out_features=32, bias=True)
   (lin2): Linear(in_features=32, out_features=32, bias=True)
   (lin3): Linear(in_features=32, out_features=16, bias=True)
   (lin4): Linear(in_features=16, out_features=8, bias=True)
   (lin5): Linear(in_features=8, out_features=4, bias=True)
 )

训练循环:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def train():
   model.train()
   optimizer.zero_grad()  # Clear gradients
   out = model(data.x)  # Perform a single forward pass
   loss = criterion(out[data.train_mask], data.y[data.train_mask])  # Compute loss from training data
   loss.backward()  # Derive gradients
   optimizer.step()  # Update parameters 
   return loss

我们训练1000个epoch

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 for epoch in range(1, 1001):
   loss = train()
   print(f"Epoch: {epoch:03d}, loss: {loss:.4f}")

然后是验证代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def test():
   model.eval()
   out = model(data.x)
   pred = out.argmax(dim=1)  # Select class with the highest probability
   test_correct = pred[data.test_mask] == data.y[data.test_mask]  # Compare to ground truth labels
   test_acc = int(test_correct.sum()) / int(data.test_mask.sum())  # Calculate fraction of correct predictions
   return test_acc

在测试集上,MLP模型的准确率得分为0.4562,因此该模型能够正确分类46%的节点。

我们可以通过使用TSNE将预测转换为二维并绘制出来,从而将其可视化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def visualize(h, color):
   z = TSNE(n_components=2).fit_transform(h.detach().cpu().numpy())
   plt.figure(figsize=(10, 10))
   plt.xticks([])  # create an empty x axis
   plt.yticks([])  # create an empty y axis
   plt.scatter(z[:, 0], z[:, 1], s=70, c=color, cmap="Set2")

可以看到用MLP模型预测的类别之间没有明显的分离。这里的MLP模型是基于特征向量进行训练的,并且不包含节点之间链接的任何信息。

2、图卷积网络(GCN)

让我们看看如果我们保持大多数参数相同,训练一个图卷积网络(GCN)模型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 from torch_geometric.nn import GCNConv
 
 class GCN(torch.nn.Module):
   def __init__(self):
     super().__init__()
     torch.manual_seed(123)
     self.conv1 = GCNConv(data.num_features, 32)
     self.conv2 = GCNConv(32, 32)
     self.conv3 = GCNConv(32, 16)
     self.conv4 = GCNConv(16, 8)
     self.conv5 = GCNConv(8, data.num_classes)
 
   def forward(self, x, edge_index):
     x = self.conv1(x, edge_index)
     x = F.relu(x)
     x = self.conv2(x, edge_index)
     x = F.relu(x)
     x = self.conv3(x, edge_index)
     x = F.relu(x)
     x = self.conv4(x, edge_index)
     x = F.relu(x)
     x = self.conv5(x, edge_index)
     x = F.log_softmax(x, dim=1)
     return x

剩下的代码基本类似

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 model = GCN()
 criterion = torch.nn.CrossEntropyLoss(weight=class_weights)
 optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
 
 def train():
   model.train()
   optimizer.zero_grad()  # Clear gradients
   out = model(data.x, data.edge_index)  # Perform a single forward pass
   loss = criterion(out[data.train_mask], data.y[data.train_mask])  # Compute losses from training data
   loss.backward()  # Derive gradients
   optimizer.step()  # Update parameters
   return loss
 
 for epoch in range(1, 1001):
   loss = train()
   print(f"Epoch: {epoch:03d}, Loss: {loss:.4f}")

模型验证

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def test():
   model.eval()
   out = model(data.x, data.edge_index)  # Pass in features and edges
   pred = out.argmax(dim=1)  # Get predicted class
   test_correct = pred[data.test_mask] == data.y[data.test_mask]  # Count correct predictions
   test_acc = int(test_correct.sum()) / int(data.test_mask.sum())  # Get proportion of correct predictions
   return test_acc

GCN模型能对测试集中80%的节点进行正确分类!让我们把它画出来:

可以看到显示了很好的颜色/类别分离,特别是在图表的中心到右边。这表明带有特征和边缘数据的GCN模型能够较好地对节点进行分类。

总结

在本文中,我们将一个CSV文件转换为数据对象,然后使用PyTorch为节点分类任务构建基于图的神经网络。并且训练了两种不同类型的神经网络——多层感知器(MLP)和图卷积网络(GCN)。结果表明,GCN模型在该数据集上的表现明显优于MLP模型。

本文介绍的主要流程是我们训练图神经网络的基本流程,尤其是前期的数据处理和加载,通过扩展本文的基本流程可以应对几乎所有图神经网络问题。

作者:Claudia Ng

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DeepHub IMBA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Weka机器学习使用介绍(数据+算法+实战)
Weka是怀卡托智能分析环境(Waikato Environment for Knowledge Analysis)的英文字首缩写,新西兰怀卡托大学用Java开发的数据挖掘著名开源软件。功能有数据处理、特征选择、分类、回归、可视化等,支持多种数据文件格式,如arff、xrff、csv等,主流的数据格式是csv和arff。
Minerva
2020/07/01
15.1K2
Weka机器学习使用介绍(数据+算法+实战)
数据挖掘系列(4)使用weka做关联规则挖掘
前面几篇介绍了关联规则的一些基本概念和两个基本算法,但实际在商业应用中,写算法反而比较少,理解数据,把握数据,利用工具才是重要的,前面的基础篇是对算法的理解,这篇将介绍开源利用数据挖掘工具weka进行管理规则挖掘。 weka数据集格式arff arff标准数据集简介   weka的数据文件后缀为arff(Attribute-Relation File Format,即属性关系文件格式),arff文件分为注释、关系名、属性名、数据域几大部分,注释用百分号开头%,关系名用@relation申明,属性用@
小莹莹
2018/04/23
2.9K2
数据挖掘系列(4)使用weka做关联规则挖掘
WEKA的使用指南
“借着年终总结,回顾个好用的数据挖掘工具。” WEKA是一个貌似比较小众的数据挖掘工具,在应用的普遍性上远远不如R、Python等软件。我在机缘巧合之下,从一门课程里学到这个工具,其轻便性、用户友好性
企鹅号小编
2018/02/24
2.2K0
WEKA的使用指南
5种无需数学背景也可理解机器学习算法的技巧
在一种自顶向下的研究机器学习的方法中,理论应立足于何处?
Bon
2018/02/06
1.2K1
5种无需数学背景也可理解机器学习算法的技巧
如何在Weka中加载CSV机器学习数据
原文地址:https://machinelearningmastery.com/load-csv-machine-learning-data-weka/
花落花飞去
2018/02/08
8.8K0
如何在Weka中加载CSV机器学习数据
Azure 机器学习 - 使用无代码 AutoML 训练分类模型
Azure 机器学习工作区是云中的基础资源,用于试验、训练和部署机器学习模型。 它将 Azure 订阅和资源组关联到服务中一个易于使用的对象。
TechLead
2023/11/08
3210
Azure 机器学习 - 使用无代码 AutoML 训练分类模型
【盘点】掌握机器学习的5条必由之路(附学习资料推荐)
【新智元导读】作者在本文提出一种5步入门并应用机器学习的方法。它不是传统的方法。传统的机器学习方法提倡从下往上学,先从理论和数学开始,然后是算法实现,最后让你去解决现实世界的问题。 作者提倡的掌握机器
新智元
2018/03/26
7480
【盘点】掌握机器学习的5条必由之路(附学习资料推荐)
3 机器学习入门——决策树之天气预报、鸢尾花
前面我们简单学习了线性回归、逻辑回归,不知道有没有做一个总结,那就是什么时候该用逻辑回归?
天涯泪小武
2019/01/17
1.6K0
25个Java机器学习工具&库
本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法。这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用。Weka包括一系列的工具,如数据预处理、分类、回归、聚类、关联规则以及可视化。 2.Massive Online Analysis(MOA)是一个面向数据流挖掘的流行开源框架,有着非常活跃的成长社区。它包括一系列的机器学习算法(分类、回归、聚类、异常检测、概念漂移检测和推荐系统)和评估工具。关联了WEKA项目,MOA也是用Java编写的,其扩展性更强。
CSDN技术头条
2018/02/11
1.5K0
基于TensorFlow的机器学习速成课程25讲视频全集(23-25讲)
【导读】前些日子,大家都知道,Google 上线了基于 TensorFlow 的机器学习速成课程,它包含 40 多项练习、25 节课程以及 15 个小时的紧凑学习内容。 基于TensorFlow的机
WZEARW
2018/06/05
4080
资源 | Intel发布AI免费系列课程3部曲:机器学习基础、深度学习基础以及TensorFlow基础
翻译 | AI科技大本营 校对 | 成龙 编辑 | 明明 Intel于近期发布了三门AI系列的免费课程,分别是关于机器学习基础、深度学习基础、TensorFlow基础三个方面。据悉,该系列免费课程主要针对研究生阶段的学生,营长将三门课程概要及链接整理如下。 ▌课程1:机器学习基础 概要 本课程介绍了Intel架构中的机器学习基础知识。涵盖的主题包括: 回顾了机器学习可以解决的问题类型 理解机器学习算法中的各组成模块 学习在机器学习中构建模型的基础知识 探索关键算法 在本课程结束时,学生将了解以下内容
AI科技大本营
2018/04/26
8170
资源 | Intel发布AI免费系列课程3部曲:机器学习基础、深度学习基础以及TensorFlow基础
从机器学习开始的4个步骤:初学者开始和实践的自上而下的策略
在这篇文章中,我向你展示了采用自顶向下的策略来入门应用机器学习的方法。我可以看到这个方法分为四个步骤。你应该对这些步骤他们感到熟悉,因为它可能跟你用来学习编程的自上而下的方法相同,亦即,掌握基础知识,大量练习,然后在你找到感觉、进入状态后再深入细节。
花落花飞去
2018/02/05
1.8K0
机器学习入门——使用python进行监督学习
什么是监督学习? 在监督学习中,我们首先要导入包含训练特征和目标特征的数据集。监督式学习算法会学习训练样本与其相关的目标变量之间的关系,并应用学到的关系对全新输入(无目标特征)进行分类。 为了说明如何
AiTechYun
2018/03/02
1.5K0
机器学习入门——使用python进行监督学习
数据太大爆内存怎么办?七条解决思路 | 机器学习开发手册
Jason Brownlee 在研究、应用机器学习算法的经历中,相信大伙儿经常遇到数据集太大、内存不够用的情况。 这引出一系列问题: 怎么加载十几、几十 GB 的数据文件? 运行数据集的时候算法崩溃了,怎么办怎么处理内存不足导致的错误? 本文将讨论一些常用的解决办法,供大家参考。 处理大型 ML 数据文件的七种思路 1. 分配更多内存 有的机器学习工具/库有默认内存设置,比如 Weka。这便是一个限制因素。 你需要检查一下:是否能重新设置该工具/库,分配更多内存。 对于 Weka,你可以在打开
AI研习社
2018/03/19
3.6K0
数据太大爆内存怎么办?七条解决思路 | 机器学习开发手册
如何透彻的掌握一门机器学习算法
机器学习算法都是一个个复杂的体系,需要通过研究来理解。学习算法的静态描述是一个好的开始,但是这并不足以使我们理解算法的行为,我们需要在动态中来理解算法。 机器学习算法的运行实验,会使你对于不同类型问题得出的实验结论,并对实验结论与算法参数两者的因果关系有一个直观认识。 在这篇文章中,你将会知道怎么研究学习一个机器学习算法。你将会学到5个简单步骤,你可以用来设计和完成你的第一个机器学习算法实验 你会发现机器学习实验不光是学者们的专利,你也可以;你也会知道实验是通往精通的必经之路,因为你可以从经验中学到因果关系
机器学习AI算法工程
2018/03/09
6150
【机器学习】吴恩达机器学习Deeplearning.ai
机器学习已经强大到可以独立成为人工智能的一个子领域。 可以通过对机器编程实现比如执行网络搜索、理解人类语言、通过x光诊断疾病,或制造自动驾驶汽车。
天天Lotay
2023/04/04
6310
【机器学习】吴恩达机器学习Deeplearning.ai
bigML中提升树模型的6个步骤
BigML将提升树模型(Boosted Trees)带入我们日益增长的监督式学习技术套件中。Boosting是一个变体,旨在减少偏见,可能会导致比Bagging或随机决策森林更好的表现。
用户1652466
2018/05/30
2.3K0
数据报告分享|WEKA贝叶斯网络挖掘学校在校人数影响因素数据分类模型
本文着眼普通高等学校在校学生人数,提出了不同种类学校的在校人数可能存在的影响关系从而探究教育现状的因素,建立分类模型,探求这几个因素间的数量关系(点击文末“阅读原文”获取完整代码数据)。
拓端
2023/08/31
2260
数据报告分享|WEKA贝叶斯网络挖掘学校在校人数影响因素数据分类模型
【机器学习】机器学习算法预览
在这篇文章中,我要带大家预览一下机器学习中最热门的算法。预览主要的机器学习算法可在某种程度上给你这样的一种感觉,让你知道什么样的方法是可靠的。 这里有很多算法都是可靠的,这也许会让你感觉吃不消,看到这么多算法的名字的时候,你也许只能感觉到它叫什么而且它出自哪个地方。 在这篇文章中,我会提供2个方法来帮助你思考和分类这些算法,而这些你也许能用得上。 我们首先可以按照算法的类型进行分组。 我们可以根据函数类型的相似度进行分组(就像对很多小动物进行分组那样)。 这些方法都是有用的,但是在这篇文
陆勤_数据人网
2018/02/27
9850
【机器学习】机器学习算法预览
Azure 机器学习 - 无代码自动机器学习的预测需求
本教程将在 Azure 机器学习工作室中创建自动化 ML 试验运行。机器学习工作室是一个整合的 Web 界面,其中包含的机器学习工具可让各种技能水平的数据科学实践者执行数据科学方案。 Internet Explorer 浏览器不支持此工作室。
TechLead
2023/11/08
3300
Azure 机器学习 - 无代码自动机器学习的预测需求
推荐阅读
相关推荐
Weka机器学习使用介绍(数据+算法+实战)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档