DGL学习笔记——第一章 图

news2025/1/11 18:29:35

提示:DGL用户指南学习中

文章目录

  • 一、关于图的基本概念?
  • 二、图、节点和边
  • 三、节点和边的特征
    • 四、从外部源创建图
    • 1、从Scipy稀疏矩阵中构建图示例
    • 2、从networkx中构建图示例
    • 3、从csv中构建图结构
  • 总结


一、关于图的基本概念?

图是用以表示实体及其关系的结构,记为 𝐺=(𝑉,𝐸) 。图由两个集合组成,一是节点的集合 𝑉 ,一个是边的集合 𝐸 。 在边集 𝐸 中,一条边 (𝑢,𝑣) 连接一对节点 𝑢 和 𝑣 ,表明两节点间存在关系。关系可以是无向的, 如描述节点之间的对称关系;也可以是有向的,如描述非对称关系。例如,若用图对社交网络中人们的友谊关系进行建模,因为友谊是相互的,则边是无向的; 若用图对Twitter用户的关注行为进行建模,则边是有向的。图可以是有向的无向的,这取决于图中边的方向性。

图可以是加权的未加权的 。在加权图中,每条边都与一个标量权重值相关联。例如,该权重可以表示长度或连接的强度。

图可以是同构的 或是异构的 。在同构图中,所有节点表示同一类型的实体,所有边表示同一类型的关系。 例如,社交网络的图由表示同一实体类型的人及其相互之间的社交关系组成。

相对地,在异构图中,节点和边的类型可以是不同的。例如,编码市场的图可以有表示”顾客”、”商家”和”商品”的节点, 它们通过“想购买”、“已经购买”、“是顾客”和“正在销售”的边互相连接。二分图是一类特殊的、常用的异构图, 其中的边连接两类不同类型的节点。例如,在推荐系统中,可以使用二分图表示”用户”和”物品”之间的关系。

在多重图中,同一对节点之间可以有多条(有向)边,包括自循环的边。例如,两名作者可以在不同年份共同署名文章, 这就带来了具有不同特征的多条边。

二、图、节点和边

DGL使用一个唯一的整数来表示一个节点,称为点ID;并用对应的两个端点ID表示一条边。同时,DGL也会根据边被添加的顺序, 给每条边分配一个唯一的整数编号,称为边ID。节点和边的ID都是从0开始构建的。在DGL的图里,所有的边都是有方向的, 即边 (𝑢,𝑣) 表示它是从节点 𝑢 指向节点 𝑣 的。

创建一个 DGLGraph 对象的一种方法是使用 dgl.graph() 函数。它接受一个边的集合作为输入。DGL也支持从其他的数据源来创建图对象。

import dgl
import torch
import networkx as nx
import matplotlib.pyplot as plt


u, v = torch.tensor([0, 0, 0, 1]), torch.tensor([1, 2, 3, 4])
g = dgl.graph((u, v))
print(g)


nx_G = g.to_networkx().to_undirected()
pos = nx.kamada_kawai_layout(nx_G)
nx.draw(nx_G, pos, with_labels=True, node_color=[[.7, .7, .7]])
plt.savefig('casual.png')
plt.show()

在这里插入图片描述

# 图中节点的数量是DGL通过给定的图的边列表中最大的点ID推断所得出的
print(g)
'''
Graph(num_nodes=5, num_edges=4,
      ndata_schemes={}
      edata_schemes={})
'''

#获取节点的ID
print(g.nodes())
#tensor([0, 1, 2, 3, 4])

#获取边的对应端点
print(g.edges())
#(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 4]))
#获取边的对应端点和边ID
print(g.edges(form='all'))
#(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 4]), tensor([0, 1, 2, 3]))
#如果有最大ID的节点没有边,在创建图的时候,用户需要明确地指明节点的数量
g1 = dgl.graph((u, v), num_nodes=8)

nx_G = g1.to_networkx().to_undirected()
pos = nx.kamada_kawai_layout(nx_G)
nx.draw(nx_G, pos, with_labels=True, node_color=[[.7, .7, .7]])
plt.savefig('max_id_no_edge.png')
plt.show()

在这里插入图片描述
从图中我们可以看出,如果设置了5个节点之间有边,但是一共有8个节点,会有三个节点是孤立的。

对于无向的图,用户需要为每条边都创建两个方向的边。可以使用 dgl.to_bidirected() 函数来实现这个目的。 如下面的代码段所示,这个函数可以把原图转换成一个包含反向边的图。

bg = dgl.to_bidirected(g)
print(bg.edges())
#(tensor([0, 0, 0, 1, 1, 2, 3, 4]), tensor([1, 2, 3, 0, 4, 0, 0, 1]))

DGL支持使用 32 位或 64 位的整数作为节点ID和边ID。节点和边ID的数据类型必须一致。如果使用 64 位整数, DGL可以处理最多 263−1 个节点或边。不过,如果图里的节点或者边的数量小于 263−1 ,用户最好使用 32 位整数。 这样不仅能提升速度,还能减少内存的使用。DGL提供了进行数据类型转换的方法,如下例所示。

edges = torch.tensor([2, 5, 3]), torch.tensor([3, 5, 0])
#边2->3  5->5  3—>0
g64 = dgl.graph(edges) #DGL默认使用int64
print(g64.idtype)
#torch.int64

g32 = dgl.graph(edges, idtype=torch.int32) #使用int32构建图
print(g32.idtype)
#torch.int32

g64_2 = g32.long() #转换成int64
print(g64_2.idtype)
#torch.int64

g32_2 = g64_2.int() #转换成int32
print(g32_2.idtype)
#torch.int32

三、节点和边的特征

DGLGraph 对象的节点和边可具有多个用户定义的、可命名的特征,以储存图的节点和边的属性。 通过 ndata 和 edata 接口可访问这些特征。 例如,以下代码创建了2个节点特征和1个边特征。

import dgl
import torch

g = dgl.graph(([0, 0, 1, 5], [1, 2, 2, 0])) #6个节点,4条边
print(g)
'''
Graph(num_nodes=6, num_edges=4,
      ndata_schemes={}
      edata_schemes={})
'''

g.ndata['x'] = torch.ones(g.num_nodes(), 3)
g.edata['x'] = torch.ones(g.num_edges(), dtype=torch.int32)
print(g)

'''
Graph(num_nodes=6, num_edges=4,
      ndata_schemes={'x': Scheme(shape=(3,), dtype=torch.float32)} #长度为3的节点特征
      edata_schemes={'x': Scheme(shape=(), dtype=torch.int32)}) #标量模型特征
'''

#不同名称的特征可以具有不同的形状
g.ndata['y'] = torch.randn(g.num_nodes(), 5)
'''
Graph(num_nodes=6, num_edges=4,
      ndata_schemes={'x': Scheme(shape=(3,), dtype=torch.float32)}
      edata_schemes={'x': Scheme(shape=(), dtype=torch.int32)})
'''

print(g.ndata['x'][1]) #获取节点1的特征
#tensor([1., 1., 1.])
print(g.edata['x'][torch.tensor([0, 3])]) #获取边0和3的特征
#tensor([1, 1], dtype=torch.int32)

#1、定义边
edges = torch.tensor([0, 0, 0, 1]), torch.tensor([1, 2, 3, 3])
#2、定义边的权重
weights = torch.tensor([0.1, 0.6, 0.9, 0.7]) #每条边的权重
#3、画图
g = dgl.graph(edges)
#4、将边的权重赋值到图上
g.edata['w'] = weights
print(g)
'''
Graph(num_nodes=4, num_edges=4,
      ndata_schemes={}
      edata_schemes={'w': Scheme(shape=(), dtype=torch.float32)})
'''

关于 ndata 和 edata 接口的重要说明:

1、仅允许使用数值类型(如单精度浮点型、双精度浮点型和整型)的特征。这些特征可以是标量、向量或多维张量;
2、每个节点特征具有唯一名称,每个边特征也具有唯一名称。节点和边的特征可以具有相同的名称(如上述示例代码中的 ‘x’ );
3、通过张量分配创建特征时,DGL会将特征赋给图中的每个节点和每条边。该张量的第一维必须与图中节点或边的数量一致。 不能将特征赋给图中节点或边的子集;
4、相同名称的特征必须具有相同的维度和数据类型;
5、特征张量使用”行优先”的原则,即每个行切片储存1个节点或1条边的特征(参考上述示例代码的第16和18行)。

四、从外部源创建图

1、从Scipy稀疏矩阵中构建图示例

import dgl
import torch
import scipy.sparse as sp
import networkx as nx


spmat = sp.rand(100, 100, density=0.05) #5%非零项
g = dgl.from_scipy(spmat)
print(g)
'''
Graph(num_nodes=100, num_edges=500,
      ndata_schemes={}
      edata_schemes={})
'''

2、从networkx中构建图示例

nx_g = nx.path_graph(5)  #一条链路0-1-2-3-4
g_ = dgl.from_networkx(nx_g)
print(g_)
'''
Graph(num_nodes=5, num_edges=8,
      ndata_schemes={}
      edata_schemes={})
'''

注意,当使用 nx.path_graph(5) 进行创建时, DGLGraph 对象有8条边,而非4条。 这是由于 nx.path_graph(5) 构建了一个无向的NetworkX图 networkx.Graph ,而 DGLGraph 的边总是有向的。 所以当将无向的NetworkX图转换为 DGLGraph 对象时,DGL会在内部将1条无向边转换为2条有向边。 使用有向的NetworkX图 networkx.DiGraph 可避免该行为。

nxg = nx.DiGraph([(2, 1), (1, 2), (2, 3), (0, 0)])
g__ = dgl.from_networkx(nxg)
print(g__)
'''
Graph(num_nodes=4, num_edges=4,
      ndata_schemes={}
      edata_schemes={})
'''

3、从csv中构建图结构

The nodes.csv stores every club members and their attributes.
The edges.csv stores the pair-wise interactions between two club members
请添加图片描述

五、创建异构图

请添加图片描述

在DGL中,一个异构图由一系列子图构成,一个子图对应一种关系。每个关系由一个字符串三元组 定义 (源节点类型, 边类型, 目标节点类型) 。由于这里的关系定义消除了边类型的歧义,DGL称它们为规范边类型。

import dgl
import torch

#创建一个具有3种节点类型和3种边类型的异构图
graph_data = {
   ('drug', 'interacts', 'drug'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
   ('drug', 'interacts', 'gene'): (torch.tensor([0, 1]), torch.tensor([2, 3])),
   ('drug', 'treats', 'disease'): (torch.tensor([1]), torch.tensor([2]))
}

g = dgl.heterograph(graph_data)
print(g.ntypes)
#['disease', 'drug', 'gene']
print(g.etypes)
#['interacts', 'interacts', 'treats']
print(g.canonical_etypes)
#[('drug', 'interacts', 'drug'), ('drug', 'interacts', 'gene'), ('drug', 'treats', 'disease')]
print(g)
'''
Graph(num_nodes={'disease': 3, 'drug': 3, 'gene': 4},
      num_edges={('drug', 'interacts', 'drug'): 2, ('drug', 'interacts', 'gene'): 2, ('drug', 'treats', 'disease'): 1},
      metagraph=[('drug', 'drug', 'interacts'), ('drug', 'gene', 'interacts'), ('drug', 'disease', 'treats')])
'''
print(g.metagraph().edges())
#[('drug', 'drug'), ('drug', 'gene'), ('drug', 'disease')]

#获取图种所有节点的数量
print(g.num_nodes())
#10

#获取drug种节点的数量
print(g.num_nodes('drug'))
#3

#不同类型的节点都有单独的ID,因此,没有指定节点类型就没有明确的返回值
print(g.nodes())
DGLError: Node type name must be specified if there are more than one node types.

print(g.nodes('drug'))
#tensor([0, 1, 2])

#设置/获取'drug'类型的节点'hv'tezh
g.nodes['drug']. data['hv'] = torch.ones(3, 1)
print(g.nodes['drug']. data['hv'])
'''
tensor([[1.],
        [1.],
        [1.]])
'''


#设置/获取'treats'类型的边的'he'特征
g.edges['treats'].data['he'] = torch.zeros(1, 1)
print(g.edges['treats'].data['he'] )
#tensor([[0.]])

如果图里只有一种节点或边类型,则不需要指定节点或边的类型。

g_ = dgl.heterograph({
   ('drug', 'interacts', 'drug'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
   ('drug', 'is similar', 'drug'): (torch.tensor([0, 1]), torch.tensor([2, 3]))
})

print(g_.nodes())
#tensor([0, 1, 2, 3])

#设置/获取但一类型的节点或边特征,不必使用新的语法
g_.ndata['hv'] = torch.ones(4, 1)
print(g_.ndata['hv'])
'''
tensor([[1.],
        [1.],
        [1.],
        [1.]])
'''

注意,同构图和二分图只是一种特殊的异构图,它们只包括一种关系。

#同构图和二分图只是一种特殊的异构图,它们只包括一种关系。
#一个同构图
g1 = dgl.heterograph({('node_type', 'edge_type', 'node_type'):(u, v)})

#一个二分图
g2 = dgl.heterograph({('source_type', 'edge_type', 'destination_type'): (u,v)})

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/24984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【推荐系统学习笔记】-- 1、推荐系统架构

根本解决的问题:在信息过载的情况下,用户如何高效获取感兴趣的信息。 1 逻辑架构 推荐系统要处理的问题就可以被形式化地定义为:对于某个用户U(User),在特定场景C(Context)下&…

区块链 - 各个国家Web3的现状与趋势

​潜力博主推荐,点上面关注博主↑↑↑ 2022年,元宇宙、NFT 、GameFi、DAO、DeFi 等 Web3 时代的新生事物,正在彻底改写传统商业模式,重塑全球数字商业的版图,一个全新的数字时代正在开启。 美国、欧洲官方开始在 Web…

【构建ML驱动的应用程序】第 4 章 :获取初始数据集

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

C语言——指针初阶详解

🐒博客名:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 目录 1. 指针是什么 2. 指针和指针类型 2.1指针类型的第一个意义 2.2指针类型的第二个意义 3. 野指针 3.1 野指针成因 3.2 如何…

零基础自学javase黑马课程第十六天

零基础自学javase黑马课程第十六天 ✨欢迎关注🖱点赞🎀收藏⭐留言✒ 🔮本文由京与旧铺原创,csdn首发! 😘系列专栏:java学习 💻首发时间:🎞2022年11月21日&…

三菱FX3U——ST编程点动与自锁

通过赋值 : 操作符,可以控制元件的状态; Y0:1,使Y0得电, Y0:0,使Y0失电; Y0:TRUE,使Y0得电, Y0:FALSE,使Y0失电; Y2:M0,通过M0的状态来控制Y2; NOT 取反操作, 状态取反&#xff…

活动现场大屏幕互动系统(微信墙)修复版完美PHP源码,带完整素材包和详细使用文档

源码收集于网络,觉得不错,2022-11-18亲测了源码,顺手修复了原来的几处bug。网上的这个源码有个重大bug,就是后台系统配音没法上传音乐文件。我理了一下代码,修复了这个问题,现在后台可以分别给每个模块上传…

CTFHub技能树 Web-文件上传详解

文章目录0x01 无验证0x02 前端验证0x03 .htaccess0x04 MIME绕过0x05 00截断0x06 双写后缀0x07 文件头检查0x08 其他摘抄0x01 无验证 介绍&#xff1a;直接上传后缀是php的文件即可 文件上传 <?php eval($_POST[777]);?> 进行连接 查找flag 0x02 前端验证 介…

智慧住建解决方案-最新全套文件

智慧住建解决方案-最新全套文件一、建设背景目前智慧住建的信息化现状&#xff1a;1、系统重叠建设&#xff0c;标准规范不统一2、信息应用水平不均衡&#xff0c;资源共享待提升3、应用系统众多&#xff0c;用户操作体验不佳4、原有架构难以适应“互联网”的新要求二、总体设计…

计算机中的第三个伟大发明

本节我们学习了控制计算机跳转指令的第三个发明的由来&#xff0c;以及清除指令。并且展示了计算机的整体控制部分的布线图。 第三个发明 对于跳转指令&#xff0c;有时它会跳转&#xff0c;有时不会。跳或不跳只是两种可能性&#xff0c;所以只需要一个bit就可以确定哪一种会…

【Kubernetes快速实战】

K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ 文章目录前言一、K8S核心特性二、K8S集群安装1.安装K8S集群1、关闭防火墙2、关闭 selinux3、关闭 swap4、给三台机器分别设置主机名5、在 k8s‐master机器添加hosts&#xff0c;执行如下命令&#xff0c;ip需要修改…

全球最受欢迎的「数字游民」城市竟然是它?

相信你已经或多或少听说过「数字游民」这个词汇了。 「数字游民」译自英文词组Digital Nomad&#xff0c;是指那些没有办公室等固定工作场所&#xff0c;利用互联网从事远程工作&#xff0c;实现地域和时间的相对自由&#xff0c;在全球范围内移动生活的人群。 想想看&#x…

STM32实战总结:HAL之电机

电机基础知识参考&#xff1a; 51单片机外设篇&#xff1a;电机_路溪非溪的博客-CSDN博客 无刷电机和有刷电机 先详细了解有刷电机&#xff1a; 带你了解&#xff08;有刷&#xff09;电机工作原理_哔哩哔哩_bilibili 再详细了解无刷电机&#xff1a; 无刷直流电机工作原理_哔哩…

MySQL在centos上的安装

去mysql官网下载mysql 通过mysql官网的download界面&#xff0c;找到community server&#xff0c;然后选择对应linux版本下载对应的安装包 这里直接上链接 https://downloads.mysql.com/archives/community/ 可以通过cat /etc/centos-release命令找到当前centos对应的版本 下…

[附源码]java毕业设计小区供暖收费管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

重磅上市《精通Neo4j》

重磅上市《精通Neo4j》重磅上市《精通Neo4j》一、写在前面的话二、主要内容三、更多介绍Here’s the table of contents:重磅上市《精通Neo4j》 《精通Neo4j》是继《Neo4j权威指南》之后第二本由中国人原创的图数据库领域专业书籍。由清华大学出版社于2022年11月出版&#xff0…

【菜菜的sklearn课堂笔记】逻辑回归与评分卡-步长的进一步理解和max_iter

视频作者&#xff1a;菜菜TsaiTsai 链接&#xff1a;【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili 既然参数迭代是靠梯度向量的大小d步长α梯度向量的大小d \times步长\alpha梯度向量的大小d步长α来实现的&#xff0c;而J(θ)J(\theta)J(θ)的降…

群推王|如何引爆您的推特流量

推特营销主要吸引力在于其庞大的用户群体。它是最大的社交媒体平台之一&#xff0c;据统计每月有3.3亿活跃用户&#xff0c;为品牌知名度和增长做出了重大贡献。 尽管我们都知道推特营销的重要性&#xff0c;但是在实际运用上大家可能会遇到一些问题&#xff0c;比如您有很多粉…

C/C++ 结构体变量初始化的几种方法总结及内存排列(字节对齐)

前言 最近看到一些别人的代码&#xff0c;对结构体的初始化使用了不同的语法&#xff0c;就决定对结构体的初始化方法做个探索&#xff0c;这里小小的记录一下。 注意&#xff0c;没有初始化的结构体变量是不会输出的&#xff0c;比如 struct SBase{int iNumberOne;int iNum…

Redis的分布式锁问题(八)基于Redis的分布式锁

Redis的分布式锁问题&#xff08;八&#xff09;基于Redis的分布式锁 分布式锁 什么是分布式锁&#xff1f; 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 当多个进程不在同一个系统中&#xff0c;用分布式锁控制多个进程对资源的访问。 在…