赞
踩
关注微信公众号【七步编程】,专注Python、AI、大数据,原创文章第一时间推送!
之前有过两篇文章分别介绍了GCN模型PinSage和图神经网络框架DGL,本文就利用DGL来逐步实现PinSage模型,让熟悉DGL的使用过程中加深对PinSage的理解。
上次的帖子分析了DGL这个框架,最后的地方提到DGL给出的示例中并不是所有的模型都是用消息传递的方式来编写的,比如著名的推荐模型PinSage,正巧这个模型在去年的帖子中也有过介绍(可见我这个人有多么拖沓,早就应该介绍模型实现,竟然拖了一年),PinSage并没有官方开源代码,所以这次就介绍一下DGL的实现方式,也给其他小伙伴一些启示吧。
如果对PinSage模型不太熟悉的,可以查看之前的一篇文章:PinSage:GCN在商业推荐系统首次成功应用
首先模型在DGL项目的位置是:examples/pytorch/recommendation。模型是基于movielens数据集(https://grouplens.org/datasets/movielens/)实现的,数据中包含用户id,电影id,电影名字,时间戳,用户对电影评分等。DGL将数据集中用户和电影看作两种类型的节点,评分做为边,构成了用户和电影之间的二分图。大家都知道,在图神经网路中,节点的初始特征是十分重要的,而DGL为用户提供了两种选择一是利用节点初始特征(python3 main.py --opt Adam --lr 1e-3 --use-feature),另一种是节点特征由初始化得到(python3 main.py --opt Adam --lr 1e-3)。DGL通过stanfordnlp结合训练好的nlp模型来生成节点初始特征,但是十分不好意思,在use-feature=True这个选项下我并没有把模型跑起来。不过已经给DGL提了issue,团队也表示会跟进,想了解进展的同学可以去看这个issue(https://github.com/dmlc/dgl/issues/1345)。所以这次只能给大家介绍在use-feature=False下的情况了,不过这个不影响整体思路。另外想要把这个模型跑起来,有几个坑需要注意,首先要去下载数据集,readme已经给出了地址;其次要安装一些package,包括,
最后代码中有一些地方要修改,具体修改可以参考https://github.com/dmlc/dgl/issues/1345,在这个issue我给出了修改方式。
目前商用的图神经网络模型基本都包含两个步骤:
针对movielens数据集,DGL分mini-batch的整体思路是,先将点分为五个部分,具体实现(examples/pytorch/recommendation/rec/datasets/movielens.py)见图1中line 183:
图1 节点划分训练集
而每个部分,又根据边,再次被切分,具体实现(examples/pytorch/recommendation/main.py)见图2中line 86,
图2 边划分训练集
在得到一个mini-batch中的边之后,可以通过边得到该mini-batch中正样本中的用户和电影,具体实现(examples/pytorch/recommendation/main.py)见图3中line 95,
图3 mini-batch中target node
这里需要额外介绍的是,在构图阶段,用户电影的二分图是一个无向图,那么如何保证见图3中line 95的操作后,src是用户而dst是电影呢,这是因为作者在examples/pytorch/recommendation/main.py中line 220、221行对边进行了过滤,只保留了用户指向电影的连边。从图3 line 97~99中可以看到,负样本是在所有电影中随机选取的(这样难道不会和正样本有冲突么,个人理解因该排除正样本)。图3 line 106~109是在排除孤立点,到 line 111,一个mini-batch中的target node生成完毕。而采样生成子图具体实现(examples/pytorch/recommendation/rec/model/pinsage.py) 见图4 line 141、142,
图4 PinSage前向计算
randomwalk这部分操作的具体实现是由底层C++部分实现,具体实现(src/graph/sampler/randomwalk.cc)见图5,
图5 多跳random walk
额外需要解释的是,DGL中randomwalk的点都是相同类型,即对于用户randomwalk之后trace中的节点都是user,而对于电影randomwalk之后trace中的节点都是电影。每条trace中的节点根据访问次数被排序,并选取top10作为子图节点。
子图生成后就可以进行模型训练,PinSage中核心部分是图卷积,而图卷积的具体实现(examples/pytorch/recommendation/rec/model/pinsage.py)见图6,
图6 PinSage图卷积
通过图6我们可以看到,这里都是通过张量计算实现的,并没有图上的信息传递(估计DGL也觉得用消息传递实现很麻烦)。这里可能会有同学问,那节点的初始特征是什么,这部分是在examples/pytorch/recommendation/rec/model/pinsage.py中line 109实现的,DGL随机初始化了一个大小为节点个数乘以输入特征为度的矩阵,其中输入特征为度是一个可以调节的超参。训练过程中根据节点id去这个矩阵中进行索引,以得到对应节点的特征,值得注意的是,这个参数矩阵是可以被训练的,这也要求,在图卷积中要求输出节点embedding的纬度与输入的节点特征是一致的,否则在更新过程中会出现纬度不匹配的情况。
这篇文章简要的介绍了DGL中PinSage的实现过程,如果介绍的有不正确的地方欢迎小伙伴们指正,作者只想起一个抛砖引玉的作用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。