内蒙网站建设赫伟创意星空科技,自动的微信小程序开发,虚拟币 wordpress,seo服务顾问从0到1用PyG创建异构图异构图创建异构图电影评分数据集MovieLens建立二分图数据集转换为可训练的数据集建立异构图神经网络以OGB数据集为例HeteroData中常用的函数将简单图神经网络转换为异质图神经网络GraphGym的使用PyG中常用的卷积层参考资料在现实中需要对
多种类型的节点以…
从0到1用PyG创建异构图异构图创建异构图电影评分数据集MovieLens建立二分图数据集转换为可训练的数据集建立异构图神经网络以OGB数据集为例HeteroData中常用的函数将简单图神经网络转换为异质图神经网络GraphGym的使用PyG中常用的卷积层参考资料在现实中需要对
多种类型的节点以及这些
节点之间多种类型的边进行处理这就需要
异构图的概念在异构图中
不同类型的边描述不同类型节点之间
不同的关系
异构图神经网络的任务就是在这种图结构上学习出节点或者整个异构图的特征表示。异构图
异构图的准确定义如下异构图Heterogeneous Graphs一个异构图GGG有一组节点Vv1,v2,...,vnVv_1,v_2,...,v_nVv1,v2,...,vn和一组边Ee1,e2,...,emEe_1,e_2,...,e_mEe1,e2,...,em组成其中每个节点和每条边都对应着一种类型用TvT_vTv表示节点类型的集合TeT_eTe表示边类型的集合一个异构图有两个映射函数分别将每个节点映射到其对应的类型ϕv:V→Tv\phi_v:V\rightarrow T_vϕv:V→Tv每条边映射到其对应的类型ϕe:E→Te\phi_e:E\rightarrow T_eϕe:E→Te。
创建异构图
电影评分数据集MovieLens
这里以一个电影评分数据集MovieLens为例逐行示例如何创建异构图。MovieLens包含了600个用户对于电影的评分利用这个数据集构建一个二分图包含电影、用户两种类型的节点一种类型的边含有多种类型节点所以可以看作一个异质图。
MovieLens中的movies.csv文件描述了电影的信息包括电影在数据集中唯一的ID电影名电影所属的类型 MovieLens中的ratings.csv包含了用户对于电影的评分
建立二分图数据集
首先下载一个Python库sentence_transformers。SentenceTransformers 是一个可以用于句子、文本和图像嵌入的Python库。 可以为 100 多种语言计算文本的嵌入并且可以轻松地将它们用于语义文本相似性、语义搜索和同义词挖掘等常见任务。该框架基于 PyTorch 和 Transformers并提供了大量针对各种任务的预训练模型。 还可以很容易根据自己的模型进行微调。
pip install -U sentence-transformers首先导入依赖库
import os.path as ospimport torch
import pandas as pd
from sentence_transformers import SentenceTransformerfrom torch_geometric.data import HeteroData, download_url, extract_zip
from torch_geometric.transforms import ToUndirected, RandomLinkSplit然后设定数据集 利用Pandas查看数据集 1利用嵌入模型将每个电影名用向量表示Embedding
# 将电影名那列用嵌入模型将每个电影名用向量表示Embedding
class SequenceEncoder(object):# 初始化指定使用的embedding module和设备def __init__(self, model_nameall-MiniLM-L6-v2, deviceNone):# 使用的设备self.device device# 使用的嵌入模型名self.model SentenceTransformer(model_name, devicedevice)# 嵌入模型不参与后续图神经网络的训练torch.no_grad()def __call__(self, df):x self.model.encode(# 要进行嵌入的值df.values,# 显示处理进度show_progress_barTrue,# 转换为Pytorch的张量convert_to_tensorTrue,# 使用的设备deviceself.device)return x.cpu()2将电影类型也进行嵌入表示
# 将电影类型那列也进行嵌入表示
class GenresEncoder(object):# 默认分隔符为|def __init__(self, sep|):self.sep sepdef __call__(self, df):genres set(g for col in df.values for g in col.split(self.sep))# 将电影类型用数字表示mapping {genre: i for i, genre in enumerate(genres)}# 用multi-hot形式表示电影的类型x torch.zeros(len(df), len(mapping))for i, col in enumerate(df.values):for genre in col.split(self.sep):x[i, mapping[genre]]1return x3从CSV文件中读取信息建立二分图中的节点信息
# 从csv中读取信息建立二分图中节点的信息
def load_node_csv(path, index_col, encodersNone, **kwargs)::param path: CSV文件路径:param index_col: 文件中的索引列也就是节点所在的列:param encoders: 节点嵌入器:param kwargs:return:df pd.read_csv(path, index_colindex_col, **kwargs)# 将索引用数字表示mapping {index: i for i, index in enumerate(df.index.unique())}# 节点属性向量矩阵x None# 如果嵌入器非空if encoders is not None:# 对相应的列进行嵌入获取嵌入向量表示xs [encoder(df[col]) for col, encoder in encoders.items()]x torch.cat(xs, dim-1)return x, mapping4获取节点信息
# 处理movies.csv表将电影名电影类型列转换为嵌入向量的表示形式
movie_x, movie_mapping load_node_csv(movie_path, index_col movieId, encoders {title:SequenceEncoder(),genres:GenresEncoder()})
# 处理rating.csv表将用户ID用PyTorch中的张量表示
user_x, user_mapping load_node_csv(rating_path, index_coluserId)
# 建立异质图这里是一个二分图
data HeteroData() # HeteroData是PyG中内置的一个表示异质图的数据结构
# 加入不同类型节点的信息
# 加入用户信息用户没有属性信息 只需要告诉PyG有多少个用户节点就可以
data[user].num_nodes len(user_mapping)
# 告诉PyG 电影的属性向量矩阵PyG会根据x推断出电影节点的个数
data[movie].x movie_x
print(data)5建立用户和电影之间的边的信息
# 将用户对电影的评分转换为PyTorch的张量
class IdentityEncoder(object):def __init__(self, dtypeNone):self.dtype dtypedef __call__(self, df):return torch.from_numpy(df.values).view(-1, 1).to(self.dtype)6建立二分图边的连接信息
# 建立二分图边的链接信息
def load_edge_csv(path, src_index_col, src_mapping, dst_index_col, dst_mapping, encodersNone, **kwargs)::param path: CSV表的路径:param src_index_col: 二分图左边节点来源于CSV表的哪一列比如user_id这列:param src_mapping:将user_id映射为节点编号我们前面定义的user_mapping:param dst_index_col:同理二分图右边电影节点:param dst_mapping::param encoders:边的嵌入器:param kwargs::return:df pd.read_csv(path, **kwargs)# 建立连接信息src [src_mapping[index] for index in df[src_index_col]]dst [dst_mapping[index] for index in df[dst_index_col]]# 注意这里edge_index维度为[2, 边数]edge_index torch.tensor([src, dst])# 边的属性信息edge_attr None# 如果嵌入器非空if encoders is not None:edge_attrs [encoder(df[col]) for col, encoder in encoders.items()]edge_attr torch.cat(edge_attrs, dim-1)return edge_index, edge_attr7获取二分图边的信息
# 获取二分图边的信息
edge_index, edge_label load_edge_csv(rating_path,# 二分图左边是用户src_index_coluserId,src_mappinguser_mapping,# 右边是电影dst_index_colmovieId,dst_mappingmovie_mapping,encoders{rating: IdentityEncoder(dtypetorch.long)})8将二分图中的边命名为(‘user’, ‘rates’, ‘movie’) 到此我们的异构图数据集实际上是一个二分图就构建完毕了。下面还要将其转换为一个可以进行训练的数据集
转换为可训练的数据集
这里我们将构建的异构图数据集转换为一个可训练的无向图数据集。 1转换为无向图同时删除相反方向边的属性信息
data ToUndirected()(data)
# 删除相反方向边的属性信息因为没有电影对用户的评分数据
del data[movie, rev_rates, user].edge_label2按照比例分割数据集为训练集、测试集、验证集
# 按照一定比例分割数据集为训练集、测试集和验证集
transform RandomLinkSplit(num_val0.05, num_test0.1,# 负采样比率# 不用负采样全部输入进行训练neg_sampling_ratio 0.0,# 告诉PyG边的连接关系edge_types[(user, rates, movie)],rev_edge_types[(movie, rev_rates, user)],)
# 分割数据集
train_data, val_data, test_data transform(data)
print(train_data)
print(val_data)
print(test_data)至此一个可训练的数据集已经构建完毕。
建立异构图神经网络
以OGB数据集为例
在OGB数据集中包含4种类型的节点author、paper、institution、field of study4种类型的边
writesauthor和paper之间的连接关系affiliated with:author和institution之间的连接关系cites:paper和paper之间的关系has topic:paper和field of study之间的关系
OGB数据集上的任务是预测论文在整个关系网中所属的位置。下面代码示例如何表示这个异质图
from torch_geometric.data import HeteroData# HeteroData是PyG自带的一个异质图数据结构
data HeteroData()# 添加节点的信息
data[paper].x ... # [num_papers, num_features_paper]
data[author].x ... # [num_authors, num_features_author]
data[institution].x ... # [num_institutions, num_features_institution]
data[field_of_study].x ... # [num_field, num_features_field]# 添加边的连接信息
data[paper, cites, paper].edge_index ... # [2, num_edges_cites]
data[author, writes, paper].edge_index ... # [2, num_edges_writes]
data[author, affiliated_with, institution].edge_index ... # [2, num_edges_affiliated]
data[paper, has_topic, field_of_study].edge_index ... # [2, num_edges_topic]# 添加边的属性信息
data[paper, cites, paper].edge_attr ... # [num_edges_cites, num_features_cites]
data[author, writes, paper].edge_attr ... # [num_edges_writes, num_features_writes]
data[author, affiliated_with, institution].edge_attr ... # [num_edges_affiliated, num_features_affiliated]
data[paper, has_topic, field_of_study].edge_attr ... # [num_edges_topic, num_features_topic]这样上面的异质图就建立完成了我们可以将它输入到一个异质图神经网络中
# 异质图神经网络
model HeteroGNN(...)
# 获取异构图神经网络的输出
# 注意异质图神经网络的输入是 ..._dict
output model(data.x_dict, data.edge_index_dict, data.edge_attr_dict)如果PyG中包含你想用的异质图可以直接这样导入
from torch_geometric.datasets import OGB_MAG# 导入数据集
dataset OGB_MAG(root./data, preprocessmetapath2vec)
data dataset[0]这样上面的异质图就建立完成了我们可以将它输入到一个异质图神经网络中
HeteroData中常用的函数
下面介绍一下HeteroData中常用的函数
获取异质图中的某种节点或边
paper_node_datadata[paper]
cites_edge_datadata[paper,cites,paper]如果边的连接节点集合或者边的命名是唯一的还可以这样写
#使用连接端点获取边
cites_edge_datadata[paper,paper]
#使用边的名字获取
cites_edge_datadata[cites]给节点添加新属性
data[paper].year...删除节点的某些属性
def data[field_of_study]通过metadata获取异质图中所有类型的信息
node_types,edge_typesdata.metadata()所有类型的节点
print(node_types)所有类型的边
print(edge_types)判断异质图自身的一些属性
print(data.has_isolated_nodes())如果不同类型信息之间维度匹配还可以将异质图融合为一个简单图
homogeneous_datadata.to_homogeneous()对异质图进行变换
import torch_geometric.transforms as T#变为无向图
dataT.ToUndirected()(data)
#添加到自身的环
dataT.AddSelfLoops()(data)将简单图神经网络转换为异质图神经网络
PyG可以通过torch_geometric.nn.to_hetero(),或者torch_geometric.nn.to_hetero_with_bases()将一个简单图神经网络转换成异质图的形式。
import torch_geometric.transforms as T
from torch_geometric.datasets import OGB_MAG
from torch_geometric.nn import SAGEConv, to_hetero# 导入数据集
dataset OGB_MAG(root./data, preprocessmetapath2vec, transformT.ToUndirected())
data dataset[0]# 定义一个普通的图神经网络
class GNN(torch.nn.Module):def __init__(self, hidden_channels, out_channels):super().__init__()self.conv1 SAGEConv((-1, -1), hidden_channels)self.conv2 SAGEConv((-1, -1), out_channels)def forward(self, x, edge_index):x self.conv1(x, edge_index).relu()x self.conv2(x, edge_index)return x# 实例化我们定义的图神经网络
model GNN(hidden_channels64, out_channelsdataset.num_classes)
# 将其转换为异质图形式
model to_hetero(model, data.metadata(), aggrsum)PyG的to_hetero具体工作方式是这样的: 它根据我们的异质图数据结构自动将我们定义的简单图神经网络结构中的层结构进行了复制并添加了信息传递路径。 然后创建的模型可以像往常一样进行训练:
def train():model.train()optimizer.zero_grad()out model(data.x_dict, data.edge_index_dict)mask data[paper].train_maskloss F.cross_entropy(out[paper][mask], data[paper].y[mask])loss.backward()optimizer.step()return float(loss)异构卷积包装器torch_geometry.nn.conv.HeteroConv允许定义自定义异构消息和更新函数以从头开始为异构图构建任意MP-GNN。虽然to_hetero的自动转换器对所有边类型使用相同的运算符但包装器允许为不同的边类型定义不同的运算符。在这里HeteroConv将子模块的字典作为输入图数据中的每个边缘类型都有一个子模块。以下示例显示了如何应用它。
import torch_geometric.transforms as T
from torch_geometric.datasets import OGB_MAG
from torch_geometric.nn import HeteroConv, GCNConv, SAGEConv, GATConv, Lineardataset OGB_MAG(root./data, preprocessmetapath2vec, transformT.ToUndirected())
data dataset[0]class HeteroGNN(torch.nn.Module):def __init__(self, hidden_channels, out_channels, num_layers):super().__init__()self.convs torch.nn.ModuleList()for _ in range(num_layers):conv HeteroConv({(paper, cites, paper): GCNConv(-1, hidden_channels),(author, writes, paper): SAGEConv((-1, -1), hidden_channels),(paper, rev_writes, author): GATConv((-1, -1), hidden_channels,add_self_loopsFalse),}, aggrsum)self.convs.append(conv)self.lin Linear(hidden_channels, out_channels)def forward(self, x_dict, edge_index_dict):for conv in self.convs:x_dict conv(x_dict, edge_index_dict)x_dict {key: x.relu() for key, x in x_dict.items()}return self.lin(x_dict[author])model HeteroGNN(hidden_channels64, out_channelsdataset.num_classes,num_layers2)我们可以通过调用一次来初始化模型有关延迟初始化的更多详细信息请参阅此处
with torch.no_grad(): # Initialize lazy modules.out model(data.x_dict, data.edge_index_dict)GraphGym的使用
PyG 2.0 现在通过 torch_geometric.graphgym 正式支持 GraphGym。总的来说GraphGym 是一个平台用于通过高度模块化的 pipeline 从配置文件中设计和评估图神经网络
GraphGym 是开始学习标准化 GNN 实现和评估的最佳平台GraphGym 提供了一个简单的接口来并行尝试数千个 GNN 架构以找到适合特定任务的最佳设计GraphGym 可轻松进行超参数搜索并可视化哪些设计选择更好。 对于GraphGym更多资料参考https://pytorch-geometric.readthedocs.io/en/latest/modules/graphgym.html
PyG中常用的卷积层 参考资料
PyG创建自定义异构图Heterogeneous Graphs数据集Pytorch图神经网络库——PyG创建自己的数据集Pytorch图神经网络库——PyG异构图学习异质图的建立《图深度学习》 马耀、汤继良著SentenceTransformers 库介绍GraphGym