deep graph library

deep graph library,第1张

文章目录
      • 边索引
      • 异构图
      • 采样器
      • with g.local_scope()
      • add_reverse_edges
      • copy_u以及copy_e
      • 常用api

本文先讲解一些基础概念与机制,然后有了这些理解之后,我再直接列出常用api。

import dgl
边索引
src=[1,2,3]
dst=[3,4,1]
g=dgl.graph((src,dst))

注意上述,默认就是(1,3)的边索引为0,其他依次类推。

异构图

异构图就是节点有不同类型,边有不同类型的图。举个例子如下:

data_dict = {
    ('user', 'follows', 'user'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
    ('user', 'follows', 'topic'): (torch.tensor([1, 1]), torch.tensor([1, 2])),
    ('user', 'plays', 'game'): (torch.tensor([0, 3]), torch.tensor([3, 4]))
}
g = dgl.heterograph(data_dict)
g

上面可能就有人懵逼了,啥跟啥啊。其实上面表示说节点有

user,topic,game

3种类型,边有:

follows,plays

2种类型。以第一个为例:

 ('user', 'follows', 'user'): (torch.tensor([0, 1]), torch.tensor([1, 2]))

其表示就是说有两条边,(0,1)(1,2),然后这两条边的头实体都是user,尾实体也是user,边类型是follows。

注意:不同节点类型,编码是不同的,例如上述

    ('user', 'follows', 'user'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
    ('user', 'follows', 'topic'): (torch.tensor([1, 1]), torch.tensor([1, 2])),

可以看到,在第一行中,0,1,2都是user。
但是在第二行中,1是user,1,2是topic。也就是说,这个topic的1,2是在该节点类型下的独立编码。从这里我们可以推断,topic至少有3个,因为还有0!

下面是我们之前定义异构图返回的结果。

Graph(num_nodes={‘game’: 5, ‘topic’: 3, ‘user’: 4},
num_edges={(‘user’, ‘follows’, ‘topic’): 2, (‘user’, ‘follows’, ‘user’): 2, (‘user’, ‘plays’, ‘game’): 2},
metagraph=[(‘user’, ‘topic’, ‘follows’), (‘user’, ‘user’, ‘follows’), (‘user’, ‘game’, ‘plays’)])

我们来分析一下,这个节点数量就是推断的结果,指各个节点类型的节点数量,其实就是索引的max然后加1。至于边数量就很好理解了,一目了然。元图则表示一共有几种类型的边。

这个节点数量推断的结果,我们也可以显示指定,如下:

data_dict = {
    ('user', 'follows', 'user'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
    ('user', 'follows', 'topic'): (torch.tensor([1, 1]), torch.tensor([1, 2])),
    ('user', 'plays', 'game'): (torch.tensor([0, 3]), torch.tensor([3, 4]))
}
nodes_num={'user': 20, 'game': 10,"topic":10}#有20个user节点
g = dgl.heterograph(data_dict,nodes_num)
g

结果如下:

Graph(num_nodes={‘game’: 10, ‘topic’: 10, ‘user’: 20},
num_edges={(‘user’, ‘follows’, ‘topic’): 2, (‘user’, ‘follows’, ‘user’): 2, (‘user’, ‘plays’, ‘game’): 2},
metagraph=[(‘user’, ‘topic’, ‘follows’), (‘user’, ‘user’, ‘follows’), (‘user’, ‘game’, ‘plays’)])

采样器

比如,对于一个图,给定一个源节点1,我们希望采样一些假的目标节点,从而构成一些假边。这个官方也是有api的,不过,这个东西其实不用官方api,我们自己也可以实现。这里由于是介绍,所以还是介绍一下api。

g = dgl.graph(([0, 1, 2], [1, 2, 3]))
neg_sampler = dgl.dataloading.negative_sampler.Uniform(2)#2表示每一个节点采样两个假目标节点。
neg_sampler(g, torch.tensor([0, 1]))

结果如下:

(tensor([0, 0, 1, 1]), tensor([1, 0, 2, 3]))

可以看到,对于源节点0,采样了1,0两个假目标节点。那么有人就会说了,不是采样假目标节点吗?这里怎么采样了1这个真节点?注意,他这个官方api是从所有节点里面均匀分布抽取的,而不是去掉0的邻居之后再均匀分布。

with g.local_scope()

这个玩意可以使得除了In-place *** 作之外的 *** 作不会对原图进行修改。(inplace *** 作就是例如a=[1],a[0]=1(inplace),a=[2]不是)

def foo(g):
    with g.local_scope():
        g.edata['h'] = torch.ones((g.num_edges(), 3))
        g.edata['h2'] = torch.ones((g.num_edges(), 3))
        return g.edata['h']
g = dgl.graph((torch.tensor([0, 1, 1]), torch.tensor([0, 0, 2])))
g.edata['h'] = torch.zeros((g.num_edges(), 3))
newh = foo(g)
print(g.edata['h'])  # still get tensor of all zeros
'h2' in g.edata      # new feature set in the function scope is not found
add_reverse_edges

给一个图复制一倍(边反向),其特征之类的也会被复制。注意一个问题,(0,1)复制后变成(1,0),但是他们的边id是相同的,因为边id并不是索引。

copy_u以及copy_e

这两个东西分别对节点和边进行 *** 作。例如:

fn.copy_e('timestamp', 'times')

就是将edata的一个属性'timestamp'复制一遍,再生成一个属性'times'

常用api
用途代码
给定边的id,找到边g.find_edges([0,2])
给定一个或者多个图,进行压缩并且重新编码,例如对于一个图,可能节点索引不是从0开始的,对于多个图,我们要将其合并,并重新编码dgl.compact_graphs(g)/dgl.compact_graphs([g1,g2])
给定边的id以及是否重新编码,得到子图dgl.edge_subgraph(g, [0, 2])
图有什么边的类型g.etypes
图有什么(节点,边,节点)的类型组合g.canonical_etypes
图有什么类型的节点g.ntypes

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/741563.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存