MXNet 实现与实战指南)
DGL 中的 APPNPPersonalized PageRank 图神经网络MXNet 实现与实战指南【免费下载链接】dglPython package built to ease deep learning on graph, on top of existing DL frameworks.项目地址: https://gitcode.com/gh_mirrors/dg/dgl导读APPNPApproximate Personalized Propagation of Neural Predictions近似个性化神经预测传播是 2018 年提出的经典图神经网络方法其核心思想是先预测、后传播Predict then Propagate先用普通 MLP 对节点特征做预测再用近似个性化 PageRank 在图上传播预测结果从而在降低模型深度需求的同时获得可控的接收域。本篇文章基于 DGL 仓库中的 MXNet 官方示例 examples/mxnet/appnp/appnp.py 及其配套 README完整讲解 APPNP 的原理、模型实现、数据预处理、训练流程与超参数调优并深入到 DGL 内置的APPNPConv卷积层源码帮助你在 Cora、Citeseer、Pubmed 等引文网络数据集上快速复现并跑通完整实验。背景从 Personalized PageRank 到 APPNPAPPNP 对应的论文为Predict then Propagate: Graph Neural Networks meet Personalized PageRankarXiv:1810.05997。与 GCN 等传统 GNN 将特征变换与邻域聚合逐层交替叠加不同APPNP 将二者解耦预测步骤Predict仅由参数化的 MLP 完成对每个节点独立地基于其特征生成预测分布传播步骤Propagate借助个性化 PageRank 的幂次迭代把预测结果沿图结构传播得到一个与个性化 PageRank 相关联的传播后的预测。这种解耦带来了两个好处模型不再依赖堆叠更多图卷积层来扩大感受野因而在深层场景下更不易过平滑over-smoothing同时传播过程本身不携带可训练参数近似个性化 PageRank 的迭代次数k可以直接控制感受野大小。示例 README 与代码中直接复用了这一思想下文会结合仓库源码逐层展开。环境依赖与安装按照 examples/mxnet/appnp/README.md 的说明运行该示例需要MXNet 1.5作为后端深度学习框架DGL 的 MXNet 后端要求requests用于数据集下载。README 中给出的安装命令为pip install torch requests需要说明的是示例代码 examples/mxnet/appnp/appnp.py 实际导入的是mxnet及其gluon、nd模块并未直接使用 PyTorch该安装命令主要保证环境中有 DGL 所需的依赖库可用。更稳妥的做法是同时确保 MXNet 版本不低于 1.5例如pip install mxnet1.5 requests适用前提DGL 通过环境变量DGLBACKEND选择后端本示例需要将后端显式指定为mxnet见下文运行方式。当前仓库的 DGL 同时维护了 PyTorch 与 TensorFlow 版本的APPNPConvpython/dgl/nn/pytorch/conv/appnpconv.py、python/dgl/nn/tensorflow/conv/appnpconv.py因此同样的网络结构在三个后端下均可复现。数据集与预处理支持的引文网络数据集示例支持三个公开引文网络数据集通过--dataset参数指定分别对应 DGL 内置数据集类参数值数据集类说明coraCoraGraphDatasetCora 引文网络citeseerCiteseerGraphDatasetCiteseer 引文网络pubmedPubmedGraphDatasetPubmed 引文网络以CoraGraphDataset为例python/dgl/data/citation_graph.py 中的文档字符串给出了该数据集的完整统计信息节点论文2708边引用关系10556类别数7标签划分训练 140 个样本、验证 500 个样本、测试 1000 个样本每个节点具有 1433 维的预定义特征且特征经过行归一化row-normalized。这些数据集会自动下载到本地默认缓存目录为~/.dgl/首次运行需要联网。数据集加载后data[0]返回一个DGLGraph对象其中ndata[feat]为节点特征、ndata[label]为节点标签、ndata[train_mask]/ndata[val_mask]/ndata[test_mask]分别为训练/验证/测试掩码。--dataset参数本身由 DGL 提供的工具函数register_data_args注册其实现位于 python/dgl/data/init.pydef register_data_args(parser): parser.add_argument( --dataset, typestr, requiredFalse, helpThe input dataset. Can be cora, citeseer, pubmed, syn(synthetic dataset) or reddit, )示例代码在main()中根据args.dataset选择对应的数据集类未知数据集会抛出ValueErrorif args.dataset cora: data CoraGraphDataset() elif args.dataset citeseer: data CiteseerGraphDataset() elif args.dataset pubmed: data PubmedGraphDataset() else: raise ValueError(Unknown dataset: {}.format(args.dataset))设备与图预处理代码支持 CPU 与 GPU 两种运行方式--gpu为-1时使用 CPUmx.cpu(0)否则使用mx.gpu(args.gpu)并将整张图迁移到对应设备if args.gpu 0: cuda False ctx mx.cpu(0) else: cuda True ctx mx.gpu(args.gpu) g g.to(ctx)随后从图中取出特征、标签与三个掩码并打印数据集统计信息边数、类别数、各划分的样本数。在建模之前示例对图做了关键预处理——先移除自环再添加自环g dgl.remove_self_loop(g) g dgl.add_self_loop(g)这一步保证了邻接矩阵中每条节点都包含指向自身的一条边从而与 APPNP 传播公式中以Ã A I作为带自环邻接矩阵的设定保持一致详见下文原理分析。模型结构预测 传播两阶段模型定义在 examples/mxnet/appnp/appnp.py 的APPNP(nn.Block)类中整体由两大部分组成。阶段一MLP 预测器构造阶段依次添加若干nn.Dense全连接层层数由hiddens对应命令行参数--hidden_sizes决定第一层in_feats - hiddens[0]中间层hiddens[i-1] - hiddens[i]输出层hiddens[-1] - n_classes。forward中的预测部分如下h features h self.feat_drop(h) h self.activation(self.layers0) for layer in self.layers[1:-1]: h self.activation(layer(h)) h self.layers-1)即输入特征先做 dropout--in-drop默认 0.5经过中间层时使用激活函数示例传入nd.relu输出层之前再做一次 dropout。这个 MLP 的预测结果h将作为个性化 PageRank 传播的初始分布H^0。阶段二APPNPConv 传播器self.propagate APPNPConv(k, alpha, edge_drop)传播步骤直接调用 DGL 内置的图卷积层APPNPConvfrom dgl.nn.mxnet.conv import APPNPConv。在forward末尾h self.propagate(self.g, h) return h这里 MLP 输出的预测被送入传播层经过k次个性化 PageRank 迭代后得到最终输出。值得注意的是传播层不包含任何可训练参数模型的可学习参数全部集中在 MLP 中。完整前向流程def forward(self, features): # prediction step h features h self.feat_drop(h) h self.activation(self.layers0) for layer in self.layers[1:-1]: h self.activation(layer(h)) h self.layers-1) # propagation step h self.propagate(self.g, h) return hAPPNPConv 的数学原理与源码实现DGL 在 python/dgl/nn/mxnet/conv/appnpconv.py 中提供了 MXNet 后端的APPNPConv其迭代公式为H^0 X H^{l1} (1 - α) · (D̃^{-1/2} Ã D̃^{-1/2} H^l) α · H^0其中Ã A I带自环的邻接矩阵D̃为对应的度矩阵α为 teleport传送概率。该公式刻画的是每一步传播当前分布以(1-α)的概率沿图扩散、以α的概率回到初始预测H^0因此当迭代次数足够大时输出将逼近个性化 PageRank 的解且天然带有残差连接、可缓解深层传播的过平滑问题。APPNPConv的构造函数签名如下def __init__(self, k, alpha, edge_drop0.0): super(APPNPConv, self).__init__() self._k k self._alpha alpha with self.name_scope(): self.edge_drop nn.Dropout(edge_drop)参数含义参数类型默认值说明kint必填传播迭代次数K即近似个性化 PageRank 的幂次迭代轮数直接控制感受野alphafloat必填传送概率α决定每一步传播中回到初始预测的比例edge_dropfloat0.0边 dropout 概率用于对节点收到的消息做随机丢弃起正则化作用forward的核心实现MXNet 版本如下with graph.local_scope(): norm mx.nd.power( mx.nd.clip(graph.in_degrees().astype(feat.dtype), a_min1, a_maxfloat(inf)), -0.5, ) shp norm.shape (1,) * (feat.ndim - 1) norm norm.reshape(shp).as_in_context(feat.context) feat_0 feat for _ in range(self._k): # normalization by src node feat feat * norm graph.ndata[h] feat graph.edata[w] self.edge_drop(nd.ones((graph.num_edges(), 1), ctxfeat.context)) graph.update_all(fn.u_mul_e(h, w, m), fn.sum(m, h)) feat graph.ndata.pop(h) # normalization by dst node feat feat * norm feat (1 - self._alpha) * feat self._alpha * feat_0 return feat逐段解读对称归一化系数利用in_degrees()计算每个节点的度d并取d^{-0.5}度为零时通过clip下限为 1 避免除零。由于采用u_mul_e消息函数与sum聚合这里度归一化系数在源端消息发出前与目的端消息聚合后各乘一次等价于对邻接矩阵施加D̃^{-1/2} Ã D̃^{-1/2}的双向对称归一化。边 dropout为每条边构造全 1 的权重向量w经过self.edge_dropnn.Dropout随机置零从而在聚合时随机屏蔽部分邻居消息实现边层面的正则化。消息传递graph.update_all(fn.u_mul_e(h, w, m), fn.sum(m, h))表示将源节点特征h与边权重w相乘得到消息m再对每个目的节点求和聚合完成一次图传播。传送项与残差每次迭代结束后执行feat (1 - α) * feat α * feat_0其中feat_0是迭代前的初始预测实现公式中的α · H^0传送项。局部作用域整段计算包在graph.local_scope()内中间写入的ndata[h]、edata[w]不会污染外部图对象保证多次调用之间状态隔离。PyTorch 后端python/dgl/nn/pytorch/conv/appnpconv.py的实现逻辑完全一致并额外支持通过edge_weight传入自定义边权重使用EdgeWeightNorm做归一化方便在带权图上使用。训练流程与评估损失函数与优化器示例使用 MXNet Gluon 的SoftmaxCELoss作为多分类交叉熵损失并在每个 epoch 内只计算train_mask所覆盖样本的损失最后除以训练样本数得到平均损失loss_fcn gluon.loss.SoftmaxCELoss() trainer gluon.Trainer( model.collect_params(), adam, {learning_rate: args.lr, wd: args.weight_decay}, ) ... with mx.autograd.record(): pred model(features) loss loss_fcn(pred, labels, mx.nd.expand_dims(train_mask, 1)) loss loss.sum() / n_train_samples loss.backward() trainer.step(batch_size1)优化器为Adam学习率与权重衰减分别由--lr默认1e-2与--weight-decay默认5e-4控制由于是全图前向、单步更新trainer.step(batch_size1)中的批次大小取 1 即可。训练循环与指标输出示例默认训练 200 个 epoch--n-epochs。从第 3 个 epoch 起统计每轮耗时并打印每轮的时间、损失、验证集准确率以及吞吐量ETputs(KTEPS)每秒处理千条边数n_edges / mean(dur) / 1000Epoch {:05d} | Time(s) {:.4f} | Loss {:.4f} | Accuracy {:.4f} | ETputs(KTEPS) {:.2f}.format(...)训练结束后在测试掩码上计算最终准确率并打印acc evaluate(model, features, labels, test_mask) print(Test accuracy {:.2%}.format(acc))evaluate函数对模型输出取argmax得到预测类别再与标签比较并加权掩码后求平均def evaluate(model, features, labels, mask): pred model(features).argmax(axis1) accuracy ((pred labels) * mask).sum() / mask.sum().asscalar() return accuracy.asscalar()运行方式与完整命令行参数在仓库根目录下运行示例目录为 examples/mxnet/appnpDGLBACKENDmxnet python3 examples/mxnet/appnp/appnp.py --dataset cora --gpu 0DGLBACKENDmxnet用于显式指定 DGL 使用 MXNet 后端--dataset cora选择数据集可选cora、citeseer、pubmed--gpu 0指定使用 0 号 GPU若改为--gpu -1则退化为 CPU 训练。appnp.py支持的全部命令行参数来自 examples/mxnet/appnp/appnp.py 的 argparse 定义汇总如下参数类型默认值说明--datasetstr无数据集名称cora/citeseer/pubmed由register_data_args注册--in-dropfloat0.5输入特征 dropout 概率--edge-dropfloat0.5边传播 dropout 概率--gpuint-1使用的 GPU 编号-1表示 CPU--lrfloat1e-2学习率--n-epochsint200训练轮数--hidden_sizesint可多值[64]MLP 隐藏层大小可传多个值构造多层 MLP--kint10个性化 PageRank 传播步数--alphafloat0.1传送概率teleport probability--weight-decayfloat5e-4L2 权重衰减系数其中--hidden_sizes支持多个取值例如--hidden_sizes 64 64会构造两层隐藏层--k与--alpha是 APPNP 的两个核心超参数--k越大感受野越大、--alpha越大则最终预测越接近初始 MLP 输出残差占比越高。实验结果与复现注意事项README 给出了该实现分别在三个数据集上的测试准确率并与原论文报告值对照数据集本实现DGL 复现论文报告值cora0.83700.850citeseer0.7130.757pubmed0.7980.797README 特别强调这些实验是在 DGL 数据集采用 GCN 设置上完成的与原论文实现所使用的数据设置不同两者存在差距的原因在原论文的实验章节中有详细说明例如数据划分方式、训练样本数量、归一化方式等差异。因此在复现对比时应当保持同数据集、同划分前提避免将不同设置下的数字直接横向比较。小结通过本文你可以掌握APPNP先预测、后传播的建模思想与个性化 PageRank 的数学形式DGL MXNet 示例 examples/mxnet/appnp/appnp.py 中 MLP 预测器与APPNPConv传播器的完整实现与训练流程DGL 内置APPNPConv层python/dgl/nn/mxnet/conv/appnpconv.py的源码级原理对称度归一化、边 dropout、u_mul_e sum消息传递与α传送项Cora / Citeseer / Pubmed 数据集的加载方式与全部命令行参数的调优含义。如果想进一步深入可以继续阅读 PyTorch 与 TensorFlow 版本的APPNPConv实现python/dgl/nn/pytorch/conv/appnpconv.py、python/dgl/nn/tensorflow/conv/appnpconv.py对比不同后端下 API 的差异并将本示例迁移到自己的图数据上做节点分类实验。【免费下载链接】dglPython package built to ease deep learning on graph, on top of existing DL frameworks.项目地址: https://gitcode.com/gh_mirrors/dg/dgl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考