看这儿,运用docker布置图深度学习结构GraphLearn运用说明
最近几年,图深度学习(Graph DNN) 火的如火如荼,图以其强大的 关系建模 能力和 可解释 能力,逐步在Embedding 算法设计技能中展露头角。在曾经的两篇文章 graphSage还是HAN ?吐血力作综述Graph Embeding 经典好文 和 一文揭开图机器学习的面纱,你确定不来看看吗 ? 中,作者分别对图的基础知识和 Graph Embeding 进行了解说,让咱们对图的基础概念有了大致的了解。其中,文章结尾有引荐到运用练习图深度的学习模型算法需求凭借在 深度学习结构 之上开发的 图深度学习结构 这项技能。
咱们都知道 tensorflow 或则 pytorch 是现在十分流行的两种 DNN深度学习结构,而完结 Graph Embeding 算法则需求运用 图深度学习/机器学习结构。现实学习工作中,很多人对tensorflow 的运用有着十分大的偏爱,这儿作者也是不能免俗气,十分乐意运用依据tensorflow相关的产品。在作者开端了解依据图深度学习结构的时分,就发现了Graph learn 这个产品。
GraphLearn 曾经也叫 AliGraph, 是阿里巴巴于2020年左右开源的一款简化 图神经网络(Graphic Nuaral Network, GNN) 应用的新结构。该结构底层兼容 tensorflow 和pytorch, 能够 依据docker进行环境建立,十分便利上手。
但是作者在实践实践的进程中,却实实在在的踩了一堆坑,很多当地依照官方的文档确实没办法对结构进行运用,所以就自己摸索了一番,整理了一下搜集到的资料和结构运用相关的知识共享给咱们~
(1) GraphLearn 的docker进程
注意:graph learn 结构布置成功的一款装备参数是:
python===2.7
tensorflow==1.13.1
选用 pip2 install xxx
进行python软件包的装置 。
(1.1) 常用文档
在这儿贴上 graph learn 相关的一些文档链接:
官方文档 : graph-learn.readthedocs.io/zh_CN/lates…
Github途径: github.com/alibaba/gra…
阿里云开发者社区文档: developer.aliyun.com/article/752…
从上面的文档中,咱们能够了解到更多graph learn 运用相关的底层运用相关的东西。
(1.2) docker 装置运用Graph Learn
当然,运用graph learn也能够自己去装置装备,但是中途坑太多而且很多 错误太隐晦 ,不知道去哪里查找。所以这儿引荐运用docker进行装置运用。
关于 docker 东西自身的装置能够参考作者曾经的一篇文章: docker 快速实战指南 ,里面详细介绍了dock运用的基础知识。
(1.2.1) 拉取 graph learn镜像
咱们能够运用以下指令去docker hub中拉取阿里巴巴官方打包好的镜像:
sudo docker pull graphlearn/graphlearn:1.0.0-tensorflow1.13.0rc1-cpu
这儿以依据tensorflow 的 cpu 版别为栗。 要运用gpu的版别的,也能够拉取 1.0.0-torch1.8.1-cuda10.2-cudnn7
相关版别,从姓名咱们能够看到它仅仅支撑torch。暂时作者也没有找到支撑tensorflow 的GPU版别,其中 docker hub 的链接如下:https://hub.docker.com/
, 查找关键子是:graphlearn/graphlearn 。
履行完这个指令之后,咱们就在本机器上能够看到当时镜像了。如下图所示:
(1.2.2) 启动 graph learn 实例
上一步咱们现已拉取好镜像了,下面咱们能够运用下面的指令启动它:
sudo docker run -d -it --name graph_m -v /home/local_machine/workspace:/root/workspace graphlearn/graph-learn
注意: 这儿咱们能够把咱们要运用的代码和数据放入到当时的目录中,通过虚拟卷的映射绑定映射到docker内部。
在后文,我会把自己运用代码和数据上传,读者能够把放到自己本地机器的 /home/local_machine/workspace
途径下。 如下图所示:
(1.2.3) 进入graph leanr 实例
由于咱们需求运用docker 装好的环境,所以咱们是需求登录到docker内部去履行指令练习模型的。 这儿咱们能够采这个指令进入 docker实例 :
sudo docker exec -it 6c1c2dda75f9 /bin/bash
如下图所示:
(1.2.4) 开端运用 graph learn 结构练习图机器学习模型
在这儿,咱们把练习模型需求的数据下载到 自己机器上的 /home/local_machine/workspace
这个途径下(能够改为你设置的途径,上面第二条-v 冒号前面的那个途径也要同步改掉)。
然后进入到镜像里面,开端练习模型了,输入数据和履行的代码选择 /root/workspace
这个途径。 然后履行:
python train_tg_unsupervised.py
这样,就能够开端咱们的模型练习之旅了。
练习效果图如下:
注意: 咱们这儿是运用镜像的graph learn 环境,运用咱们的数据,练习自己的模型。
当然,很多同学大概率会遇到这个问题:
假如呈现这个问题,不必怀疑,大概率是数据(节点或则边)的格局不对,而且大概率是由于中心的TAB空格不对。这儿必须是 Linux下的TAB键,假如同学你用多个空格键替代TAB键,那恭喜同学,你会收到意想不到的惊喜,不说了,这些经验都是血与泪!!!
(2) 代码韶光
talk is cheap , show me the code !!!
下面的代码是运用tensorflow来构建模型结构,中心支撑了 metapath节点采样,支撑图上的 node embeding导出。 在下面供给了完整的代码和数据下载的方法,代码的注解十分详细,具有极高的参考价值与可重用性,有问题欢迎评论~
该工程完整代码和练习数据,能够去算法全栈之路公众号回复 “阿里图结构源码” 下载。
@欢迎重视微信公众号:算法全栈之路
#-*-coding:utf-8-*-
from__future__importprint_function
importgraphlearnasgl
importtensorflowastf
importgraphlearn.python.nn.tfastfg
fromego_sageimportEgoGraphSAGE
defload_graph(config):
#数据包括极点数据和边数据,极点数据和边均能够有特点,而且极点种类和边种类能够有多个,仅仅type字段不能相同
#读取图参数,构建一个Graph逻辑目标,后续一切的操作都在这个Graph目标进步行。
#GL图数据格局灵活,支撑float,int,string类型的特点,支撑带权重、标签。
#数据源载入和拓扑描绘:同构、异构、多数据源,统统支撑
#GL供给了node和edge两个简略的接口来支撑极点和边的数据源载入,同时在这两个接口中描绘图的拓扑结构,比方“buy”边的源极点类型是“user”,
#目的极点类型是“item”。这个拓扑结构在异构图中十分重要,是后续采样途径meta-path的依据,也是查询的实体类型的基础。
data_dir=config['dataset_folder']
g=gl.Graph()\
.node(data_dir+'unsupervised_node.txt',node_type='i',
decoder=gl.Decoder(attr_types=['float']*config['features_num'],
attr_dims=[0]*config['features_num']))\
.edge(data_dir+'unsupervised_edge.txt',edge_type=('i','i','train'),
decoder=gl.Decoder(weighted=True),directed=False)
returng
defmeta_path_sample(ego,ego_name,nbrs_num,sampler):
#构建metapath采样器
"""createsthemeta-mathsampleroftheinputego.
config:
ego:Aqueryobject,theinputcentricnodes/edges
ego_name:Astring,thenameof`ego`.
#街坊个数,每一跳选择几个街坊
nbrs_num:Alist,thenumberofneighborsforeachhop.
sampler:Astring,thestrategyofneighborsampling.
"""
#src_hop_i
#下流拜访的时分依据alist去拜访
alias_list=[ego_name+'_hop_'+str(i+1)foriinrange(len(nbrs_num))]
fornbr_count,aliasinzip(nbrs_num,alias_list):
#这儿将ego采样后赋值给ego,完结二跳的采样
#在下流用alias进行数据拜访
ego=ego.outV('train').sample(nbr_count).by(sampler).alias(alias)
returnego
defquery(graph,config):
#拿到一切label叫做train的边,然后进行batch的shuffle
seed=graph.E('train').batch(config['batch_size']).shuffle(traverse=True)
#得到batch之后的边,outv是出极点,src是out对应的极点
#当时batch一切的边里一切的出另一个极点,由于是有向图,所以有区分出度入度
src=seed.outV().alias('src')
#inv,整个图是入度图,dst是in对应的极点
#当时batch里极点的,一切的入极点
dst=seed.inV().alias('dst')
#运用alias能够在下流拜访当时次查询输出的成果
#每种采样操作都有不同的完结策略,例如随机、边权等
neg_dst=src.outNeg('train').sample(config['neg_num']).by(config['neg_sampler']).alias('neg_dst')
#异构图,meta_path采样,这个[10,5]作为
#输入当时批次一切的src,然后进行采样
src_ego=meta_path_sample(src,'src',config['nbrs_num'],config['sampler'])
#输入当时批次一切dst,进行采样
dst_ego=meta_path_sample(dst,'dst',config['nbrs_num'],config['sampler'])
#GL也供给了负采样,只需求将示例中的outV改为outNeg即可
#输出outNeg,采样neg_num条,in_degree,依据入度进行采样
#负采样,依据输入极点,对不直接衔接的极点进行采样。负采样经常被用作监督学习的重要东西。
dst_neg_ego=meta_path_sample(neg_dst,'neg_dst',config['nbrs_num'],config['sampler'])
#一批一批的边的选择值,values是sink操作,表示查询现已结束
returnseed.values()
deftrain(graph,model,config):
#configtrain练习形式,超参
tfg.conf.training=True
#依据config从图上按批次取得数据,并得到对应的一些采样数据
query_train=query(graph,config)
#窗口,当时batch,由于是依据边采样,所以下流的src和dst的embeding应该是一一对应
#graphlearn.Dataset接口,用于将Query的成果结构为Numpy组成的graphlearn.Nodes/graphlearn.Edges或graphlearn
#window.Thedatasetwillbeprefetchedasynchronously,windowisthesizeoftheprefetcheddata.
#完结numpy到tensor的转化
dataset=tfg.Dataset(query_train,window=10)
#得到开始边和结束边
#OriganizesthedatadictasEgoGraphsandthencheckandreturnthespecified`EgoGraph`.
#将包括固定巨细样本的GSL成果转化为EgoGraph格局。您能够EgoGraph通过别名取得egograph
src_ego=dataset.get_egograph('src')
dst_ego=dataset.get_egograph('dst')
neg_dst_ego=dataset.get_egograph('neg_dst')
#在图上跑模型,得到三个logit
#这儿模型的forword其实就是结点特征的聚合,聚合完了之后就核算得到logit
src_emb=model.forward(src_ego)
dst_emb=model.forward(dst_ego)
neg_dst_emb=model.forward(neg_dst_ego)
#usesampledsoftmaxlosswithtemperature.
#温度值,应该是类似度到sigmoid值之间的那个转化方法
#无监督类型网络,有边相连的,就比较近,没有边相连的,随机采样,距离应该比较远
loss=tfg.unsupervised_softmax_cross_entropy_loss(src_emb,dst_emb,neg_dst_emb,
temperature=config['temperature'])
returndataset.iterator,loss
#node_embedding(g,u_model,'u',config)
defnode_embedding(graph,model,node_type,config):
"""savenodeembedding.
Args:
node_type:'u'or'i'.
Return:
iterator,ids,embedding.
"""
tfg.conf.training=False
ego_name='save_node_'+node_type
seed=graph.V(node_type).batch(config['batch_size']).alias(ego_name)
nbrs_num=config['nbrs_num']ifnode_type=='u'elseconfig['nbrs_num']
query_save=meta_path_sample(seed,ego_name,config['nbrs_num'],config['sampler']).values()
dataset=tfg.Dataset(query_save,window=1)
ego_graph=dataset.get_egograph(ego_name)
emb=model.forward(ego_graph)
returndataset.iterator,ego_graph.src.ids,emb
defdump_embedding(sess,iter,ids,emb,emb_writer):
sess.run(iter.initializer)
whileTrue:
try:
outs=sess.run([ids,emb])
#[B,],[B,dim]
feat=[','.join(str(x)forxinarr)forarrinouts[1]]
forid,featinzip(outs[0],feat):
emb_writer.write('%d\t%s\n'%(id,feat))
excepttf.errors.OutOfRangeError:
print('Savenodeembeddingsdone.')
break
defrun(config):
#graphinputdata
#load现已界说好的图
g=load_graph(config=config)
#GL供给单机的版别,通过init接口快速启动GraphEngine,至此,图目标现已结构结束
#查询、采样操作就能够在Graph进步行了。
g.init()
#DefineModel
#依据读入的参数进行模型各层的参数,初始第一层是每个结点的特征个数或则embeding维度。
#后面层是对街坊结点做卷积或则说是每2跳之间结点特征聚合的进程,每次聚合需求用到2跳结点的特征.
#dims=[128,128,10,5,128]
dims=[config['features_num']]+[config['hidden_dim']]*(len(config['nbrs_num'])-1)+[config['output_dim']]
#graphsage,隐藏层参数的多少
#界说一个模型,该模型内部,进行了featurecolumn的embeding化
#这个维度第一层是features_nums,也就是结点的初始特征值,初始特征或许需求运用featurecolumn通过transform,
#初始特征是通过多层的聚合,维度会逐步变小,图上的每个结点是需求初始的embeding的,或则很多维数特征
#每一个embeding,通过几层神经网络之后,维度变成1dim,核算出logit,这儿看ego_gnn里的源码
#graphsage,图迭代几回,就运用几跳的结点数据进行sage操作
model=EgoGraphSAGE(dims,
agg_type=config['agg_type'],
dropout=config['drop_out'])
#train
iterator,loss=train(g,model,config)
optimizer=tf.train.AdamOptimizer(learning_rate=config['learning_rate'])
train_op=optimizer.minimize(loss)
train_ops=[loss,train_op]
#保存下来embeding
i_save_iter,i_ids,i_emb=node_embedding(g,model,'i',config)
withtf.Session()assess:
sess.run(tf.local_variables_initializer())
sess.run(tf.global_variables_initializer())
sess.run(iterator.initializer)
step=0
print("StartTraining...")
foriinrange(config['epoch']):
try:
whileTrue:
ret=sess.run(train_ops)
print("Epoch{},Iter{},Loss{:.5f}".format(i,step,ret[0]))
step+=1
excepttf.errors.OutOfRangeError:
sess.run(iterator.initializer)#reinitializedataset.
print("Startsavingembeddings...")
i_emb_writer=open('i_emb.txt','w')
i_emb_writer.write('id:int64\temb:string\n')
dump_embedding(sess,i_save_iter,i_ids,i_emb,i_emb_writer)
g.close()
if__name__=="__main__":
#模型练习超参
config={'dataset_folder':'./data/tg_graph/',
'batch_size':2,
'features_num':3,
'hidden_dim':3,
'output_dim':3,
'nbrs_num':[1],
'neg_num':1,
'learning_rate':0.0001,
'epoch':1,
'agg_type':'mean',
'drop_out':0.0,
'sampler':'random',
'neg_sampler':'in_degree',
'temperature':0.07
}
run(config)
到这儿,快看!运用docker布置图深度学习结构GraphLearn运用说明 就写完了,有问题欢迎留言评论哦~
宅男民工码字不易,你的重视是我持续输出的最大动力。
接下来作者会持续共享学习与工作中一些有用的、有意思的内容,点点手指头支撑一下吧~
欢迎扫码重视作者的公众号: 算法全栈之路
- END –