"src/git@developer.sourcefind.cn:renzhc/diffusers_dcu.git" did not exist on "bf725e044e0b2fec29c074510c2d12d5ef66d2d1"
Unverified Commit 808a3676 authored by zhjwy9343's avatar zhjwy9343 Committed by GitHub
Browse files

[Doc] Chinese User Guide chapter1 (#2240)



* [Feature] Add full graph training with dgl built-in dataset.

* [Feature] Add full graph training with dgl built-in dataset.

* [Feature] Add full graph training with dgl built-in dataset.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Bug] fix model to cuda.

* [Feature] Add test loss and accuracy

* [Feature] Add test loss and accuracy

* [Feature] Add test loss and accuracy

* [Feature] Add test loss and accuracy

* [Feature] Add test loss and accuracy

* [Feature] Add test loss and accuracy

* [Fix] Add random

* [Bug] Fix batch norm error

* [Doc] Test with CN in Sphinx

* [Doc] Test with CN in Sphinx

* [Doc] Remove the test CN docs.

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Feature] Add input embedding layer

* [Doc] fill readme with new performance results

* [Doc] Add Chinese User Guide, graph and 1.5

* [Doc] Add Chinese User Guide, graph and 1.5

* [Doc] Add Chines User Guide

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* Update README.md

* [Doc] Finalize CN user guide chapter 1

* [Doc] Finalize CN user guide chapter 1

* [Doc] Finalize CN user guide chapter 1

* [Doc] Add CN link in user guide chapter 1

* [Doc] Add CN link in user guide chapter 1

* [Fix] Temporary remove compgcn

* [Doc] Add Chines User Guide

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] user guide cn chapter 1

* [Doc] Finalize CN user guide chapter 1

* [Doc] Finalize CN user guide chapter 1

* [Doc] Finalize CN user guide chapter 1

* [Doc] Add CN link in user guide chapter 1

* update hash in 3rd party

* [Fix] copyedit some errors

* [Fix] copyedit some errors

* [Fix] copyedit some errors

* [Fix] copyedit some errors

* [Fix] copyedit some errors

* Update
Co-authored-by: default avatarMufei Li <mufeili1996@gmail.com>
parent c341520d
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
1.1 Some Basic Definitions about Graphs (Graphs 101) 1.1 Some Basic Definitions about Graphs (Graphs 101)
---------------------------------------------------- ----------------------------------------------------
:ref:`(中文版)<guide_cn-graph-basic>`
A graph :math:`G=(V, E)` is a structure used to represent entities and their relations. It consists of A graph :math:`G=(V, E)` is a structure used to represent entities and their relations. It consists of
two sets -- the set of nodes :math:`V` (also called vertices) and the set of edges :math:`E` (also called two sets -- the set of nodes :math:`V` (also called vertices) and the set of edges :math:`E` (also called
arcs). An edge :math:`(u, v) \in E` connecting a pair of nodes :math:`u` and :math:`v` indicates that there is a arcs). An edge :math:`(u, v) \in E` connecting a pair of nodes :math:`u` and :math:`v` indicates that there is a
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
1.4 Creating Graphs from External Sources 1.4 Creating Graphs from External Sources
----------------------------------------- -----------------------------------------
:ref:`(中文版)<guide_cn-graph-external>`
The options to construct a :class:`~dgl.DGLGraph` from external sources include: The options to construct a :class:`~dgl.DGLGraph` from external sources include:
- Conversion from external python libraries for graphs and sparse matrices (NetworkX and SciPy). - Conversion from external python libraries for graphs and sparse matrices (NetworkX and SciPy).
......
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
1.3 Node and Edge Features 1.3 Node and Edge Features
-------------------------- --------------------------
:ref:`(中文版)<guide_cn-graph-feature>`
The nodes and edges of a :class:`~dgl.DGLGraph` can have several user-defined named features for The nodes and edges of a :class:`~dgl.DGLGraph` can have several user-defined named features for
storing graph-specific properties of the nodes and edges. These features can be accessed storing graph-specific properties of the nodes and edges. These features can be accessed
via the :py:attr:`~dgl.DGLGraph.ndata` and :py:attr:`~dgl.DGLGraph.edata` interface. For example, the following code creates two node via the :py:attr:`~dgl.DGLGraph.ndata` and :py:attr:`~dgl.DGLGraph.edata` interface. For example, the following code creates two node
features (named ``'x'`` and ``'y'`` in lines 8 and 15) and one edge feature (named ``'x'`` in line 9). features (named ``'x'`` and ``'y'`` in line 5 and 8) and one edge feature (named ``'x'`` in line 6).
.. code-block:: python .. code-block:: python
:linenos: :linenos:
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
1.6 Using DGLGraph on a GPU 1.6 Using DGLGraph on a GPU
--------------------------- ---------------------------
:ref:`(中文版)<guide_cn-graph-gpu>`
One can create a :class:`~dgl.DGLGraph` on a GPU by passing two GPU tensors during construction. One can create a :class:`~dgl.DGLGraph` on a GPU by passing two GPU tensors during construction.
Another approach is to use the :func:`~dgl.DGLGraph.to` API to copy a :class:`~dgl.DGLGraph` to a GPU, which Another approach is to use the :func:`~dgl.DGLGraph.to` API to copy a :class:`~dgl.DGLGraph` to a GPU, which
copies the graph structure as well as the feature data to the given device. copies the graph structure as well as the feature data to the given device.
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
1.2 Graphs, Nodes, and Edges 1.2 Graphs, Nodes, and Edges
---------------------------- ----------------------------
:ref:`(中文版)<guide_cn-graph-graphs-nodes-edges>`
DGL represents each node by a unique integer, called its node ID, and each edge by a pair DGL represents each node by a unique integer, called its node ID, and each edge by a pair
of integers corresponding to the IDs of its end nodes. DGL assigns to each edge a unique of integers corresponding to the IDs of its end nodes. DGL assigns to each edge a unique
integer, called its **edge ID**, based on the order in which it was added to the graph. The integer, called its **edge ID**, based on the order in which it was added to the graph. The
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
1.5 Heterogeneous Graphs 1.5 Heterogeneous Graphs
------------------------ ------------------------
:ref:`(中文版)<guide_cn-graph-heterogeneous>`
A heterogeneous graph can have nodes and edges of different types. Nodes/Edges of A heterogeneous graph can have nodes and edges of different types. Nodes/Edges of
different types have independent ID space and feature storage. For example in the figure below, the different types have independent ID space and feature storage. For example in the figure below, the
user and game node IDs both start from zero and the they have different features. user and game node IDs both start from zero and the they have different features.
...@@ -18,12 +20,6 @@ In DGL, a heterogeneous graph (heterograph for short) is specified with a series ...@@ -18,12 +20,6 @@ In DGL, a heterogeneous graph (heterograph for short) is specified with a series
relation. Each relation is a string triplet ``(source node type, edge type, destination node type)``. relation. Each relation is a string triplet ``(source node type, edge type, destination node type)``.
Since relations disambiguate the edge types, DGL calls them canonical edge types. Since relations disambiguate the edge types, DGL calls them canonical edge types.
.. code::
{relation1 : node_tensor_tuple1,
relation2 : node_tensor_tuple2,
...}
The following code snippet is an example for creating a heterogeneous graph in DGL. The following code snippet is an example for creating a heterogeneous graph in DGL.
.. code:: .. code::
...@@ -243,7 +239,7 @@ It proceeds as follows: ...@@ -243,7 +239,7 @@ It proceeds as follows:
[0.], [0.],
[0.]]) [0.]])
The original node/edge types and type-specific IDs are stored in :py:attr:`~dgl.DGLGraph.ndata` and :py:attr:`~dgl.DGLGraph.edata`. The original node/edge types and type-specific IDs are stored in :py:attr:`~dgl.DGLGraph.ndata` and :py:attr:`~dgl.DGLGraph.edata`.
.. code:: .. code::
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
Chapter 1: Graph Chapter 1: Graph
====================== ======================
:ref:`(中文版)<guide_cn-graph>`
Graphs express entities (nodes) along with their relations (edges), and both nodes and Graphs express entities (nodes) along with their relations (edges), and both nodes and
edges can be typed (e.g., ``"user"`` and ``"item"`` are two different types of nodes). DGL provides a edges can be typed (e.g., ``"user"`` and ``"item"`` are two different types of nodes). DGL provides a
graph-centric programming abstraction with its core data structure -- :class:`~dgl.DGLGraph`. :class:`~dgl.DGLGraph` graph-centric programming abstraction with its core data structure -- :class:`~dgl.DGLGraph`. :class:`~dgl.DGLGraph`
......
.. _guide_cn-graph-basic:
1.1 关于图的基本概念
-----------------
:ref:`(English Version) <guide-graph-basic>`
图是用以表示实体及其关系的结构,记为 :math:`G=(V, E)` 。图由两个集合组成,一是节点的集合 :math:`V` ,一个是边的集合 :math:`E` 。
在边集 :math:`E` 中,一条边 :math:`(u, v)` 连接一对节点 :math:`u` 和 :math:`v` ,表明两节点间存在关系。关系可以是无向的,
如描述节点之间的对称关系;也可以是有向的,如描述非对称关系。例如,若用图对社交网络中人们的友谊关系进行建模,因为友谊是相互的,则边是无向的;
若用图对Twitter用户的关注行为进行建模,则边是有向的。图可以是 *有向的* 或 *无向的* ,这取决于图中边的方向性。
图可以是 *加权的* 或 *未加权的* 。在加权图中,每条边都与一个标量权重值相关联。例如,该权重可以表示长度或连接的强度。
图可以是 *同构的* 或是 *异构的* 。在同构图中,所有节点表示同一类型的实体,所有边表示同一类型的关系。
例如,社交网络的图由表示同一实体类型的人及其相互之间的社交关系组成。
相对地,在异构图中,节点和边的类型可以是不同的。例如,编码市场的图可以有表示"顾客"、"商家"和"商品"的节点,
它们通过“想购买”、“已经购买”、“是顾客”和“正在销售”的边互相连接。二分图是一类特殊的、常用的异构图,
其中的边连接两类不同类型的节点。例如,在推荐系统中,可以使用二分图表示"用户"和"物品"之间的关系。想了解更多信息,读者可参考 :ref:`guide_cn-graph-heterogeneous`。
在多重图中,同一对节点之间可以有多条(有向)边,包括自循环的边。例如,两名作者可以在不同年份共同署名文章,
这就带来了具有不同特征的多条边。
.. _guide_cn-graph-external:
1.4 从外部源创建图
---------------
:ref:`(English Version)<guide-graph-external>`
可以从外部来源构造一个 :class:`~dgl.DGLGraph` 对象,包括:
- 从用于图和稀疏矩阵的外部Python库(NetworkX 和 SciPy)创建而来。
- 从磁盘加载图数据。
本节不涉及通过转换其他图来生成图的函数,相关概述请阅读API参考手册。
从外部库创建图
^^^^^^^^^^^
以下代码片段为从SciPy稀疏矩阵和NetworkX图创建DGL图的示例。
.. code::
>>> import dgl
>>> import torch as th
>>> import scipy.sparse as sp
>>> spmat = sp.rand(100, 100, density=0.05) # 5%非零项
>>> dgl.from_scipy(spmat) # 来自SciPy
Graph(num_nodes=100, num_edges=500,
ndata_schemes={}
edata_schemes={})
>>> import networkx as nx
>>> nx_g = nx.path_graph(5) # 一条链路0-1-2-3-4
>>> dgl.from_networkx(nx_g) # 来自NetworkX
Graph(num_nodes=5, num_edges=8,
ndata_schemes={}
edata_schemes={})
注意,当使用 `nx.path_graph(5)` 进行创建时, :class:`~dgl.DGLGraph` 对象有8条边,而非4条。
这是由于 `nx.path_graph(5)` 构建了一个无向的NetworkX图 :class:`networkx.Graph` ,而 :class:`~dgl.DGLGraph` 的边总是有向的。
所以当将无向的NetworkX图转换为 :class:`~dgl.DGLGraph` 对象时,DGL会在内部将1条无向边转换为2条有向边。
使用有向的NetworkX图 :class:`networkx.DiGraph` 可避免该行为。
.. code::
>>> nxg = nx.DiGraph([(2, 1), (1, 2), (2, 3), (0, 0)])
>>> dgl.from_networkx(nxg)
Graph(num_nodes=4, num_edges=4,
ndata_schemes={}
edata_schemes={})
.. note::
DGL在内部将SciPy矩阵和NetworkX图转换为张量来创建图。因此,这些构建方法并不适用于重视性能的场景。
相关API: :func:`dgl.from_scipy`、 :func:`dgl.from_networkx`。
从磁盘加载图
^^^^^^^^^^
有多种文件格式可储存图,所以这里难以枚举所有选项。本节仅给出一些常见格式的一般情况。
逗号分隔值(CSV)
""""""""""""""
CSV是一种常见的格式,以表格格式储存节点、边及其特征:
.. table:: nodes.csv
+-----------+
|age, title |
+===========+
|43, 1 |
+-----------+
|23, 3 |
+-----------+
|... |
+-----------+
.. table:: edges.csv
+-----------------+
|src, dst, weight |
+=================+
|0, 1, 0.4 |
+-----------------+
|0, 3, 0.9 |
+-----------------+
|... |
+-----------------+
许多知名Python库(如Pandas)可以将该类型数据加载到python对象(如 :class:`numpy.ndarray`)中,
进而使用这些对象来构建DGLGraph对象。如果后端框架也提供了从磁盘中保存或加载张量的工具(如 :func:`torch.save`, :func:`torch.load` ),
可以遵循相同的原理来构建图。
另见: `从成对的边 CSV 文件中加载 Karate Club Network 的教程 <https://github.com/dglai/WWW20-Hands-on-Tutorial/blob/master/basic_tasks/1_load_data.ipynb>`_。
JSON/GML 格式
""""""""""""
如果对速度不太关注的话,读者可以使用NetworkX提供的工具来解析 `各种数据格式 <https://networkx.github.io/documentation/stable/reference/readwrite/index.html>`_,
DGL可以间接地从这些来源创建图。
DGL 二进制格式
""""""""""""
DGL提供了API以从磁盘中加载或向磁盘里保存二进制格式的图。除了图结构,API也能处理特征数据和图级别的标签数据。
DGL也支持直接从S3/HDFS中加载或向S3/HDFS保存图。参考手册提供了该用法的更多细节。
相关API: :func:`dgl.save_graphs`、 :func:`dgl.load_graphs`。
\ No newline at end of file
.. _guide_cn-graph-feature:
1.3 节点和边的特征
---------------
:ref:`(English Version)<guide-graph-feature>`
:class:`~dgl.DGLGraph` 对象的节点和边可具有多个用户定义的、可命名的特征,以储存图的节点和边的属性。
通过 :py:attr:`~dgl.DGLGraph.ndata` 和 :py:attr:`~dgl.DGLGraph.edata` 接口可访问这些特征。
例如,以下代码创建了2个节点特征(分别在第5、8行命名为 ``'x'`` 、 ``'y'`` )和1个边特征(在第6行命名为 ``'x'`` )。
.. code-block:: python
:linenos:
>>> import dgl
>>> import torch as th
>>> g = dgl.graph(([0, 0, 1, 5], [1, 2, 2, 0])) # 6个节点,4条边
>>> g
Graph(num_nodes=6, num_edges=4,
ndata_schemes={}
edata_schemes={})
>>> g.ndata['x'] = th.ones(g.num_nodes(), 3) # 长度为3的节点特征
>>> g.edata['x'] = th.ones(g.num_edges(), dtype=th.int32) # 标量整型特征
>>> g
Graph(num_nodes=6, num_edges=4,
ndata_schemes={'x' : Scheme(shape=(3,), dtype=torch.float32)}
edata_schemes={'x' : Scheme(shape=(,), dtype=torch.int32)})
>>> # 不同名称的特征可以具有不同形状
>>> g.ndata['y'] = th.randn(g.num_nodes(), 5)
>>> g.ndata['x'][1] # 获取节点1的特征
tensor([1., 1., 1.])
>>> g.edata['x'][th.tensor([0, 3])] # 获取边0和3的特征
tensor([1, 1], dtype=torch.int32)
关于 :py:attr:`~dgl.DGLGraph.ndata` 和 :py:attr:`~dgl.DGLGraph.edata` 接口的重要说明:
- 仅允许使用数值类型(如单精度浮点型、双精度浮点型和整型)的特征。这些特征可以是标量、向量或多维张量。
- 每个节点特征具有唯一名称,每个边特征也具有唯一名称。节点和边的特征可以具有相同的名称(如上述示例代码中的 ``'x'`` )。
- 通过张量分配创建特征时,DGL会将特征赋给图中的每个节点和每条边。该张量的第一维必须与图中节点或边的数量一致。
不能将特征赋给图中节点或边的子集。
- 相同名称的特征必须具有相同的维度和数据类型。
- 特征张量使用"行优先"的原则,即每个行切片储存1个节点或1条边的特征(参考上述示例代码的第10~11行)。
对于加权图,用户可以将权重储存为一个边特征,如下。
.. code-block:: python
>>> # 边 0->1, 0->2, 0->3, 1->3
>>> edges = th.tensor([0, 0, 0, 1]), th.tensor([1, 2, 3, 3])
>>> weights = th.tensor([0.1, 0.6, 0.9, 0.7]) # 每条边的权重
>>> g = dgl.graph(edges)
>>> g.edata['w'] = weights # 将其命名为 'w'
>>> g
Graph(num_nodes=4, num_edges=4,
ndata_schemes={}
edata_schemes={'w' : Scheme(shape=(,), dtype=torch.float32)})
相关API: :py:attr:`~dgl.DGLGraph.ndata`、 :py:attr:`~dgl.DGLGraph.edata`。
\ No newline at end of file
.. _guide_cn-graph-gpu:
1.6 在GPU上使用DGLGraph
----------------------
:ref:`(English Version)<guide-graph-gpu>`
用户可以通过在构造过程中传入两个GPU张量来创建GPU上的 :class:`~dgl.DGLGraph` 。
另一种方法是使用 :func:`~dgl.DGLGraph.to` API将 :class:`~dgl.DGLGraph` 复制到GPU,这会将图结构和特征数据都拷贝到指定的设备。
.. code::
>>> import dgl
>>> import torch as th
>>> u, v = th.tensor([0, 1, 2]), th.tensor([2, 3, 4])
>>> g = dgl.graph((u, v))
>>> g.ndata['x'] = th.randn(5, 3) # 原始特征在CPU上
>>> g.device
device(type='cpu')
>>> cuda_g = g.to('cuda:0') # 接受来自后端框架的任何设备对象
>>> cuda_g.device
device(type='cuda', index=0)
>>> cuda_g.ndata['x'].device # 特征数据也拷贝到了GPU上
device(type='cuda', index=0)
>>> # 由GPU张量构造的图也在GPU上
>>> u, v = u.to('cuda:0'), v.to('cuda:0')
>>> g = dgl.graph((u, v))
>>> g.device
device(type='cuda', index=0)
任何涉及GPU图的操作都是在GPU上运行的。因此,这要求所有张量参数都已经放在GPU上,其结果(图或张量)也将在GPU上。
此外,GPU图只接受GPU上的特征数据。
.. code::
>>> cuda_g.in_degrees()
tensor([0, 0, 1, 1, 1], device='cuda:0')
>>> cuda_g.in_edges([2, 3, 4]) # 可以接受非张量类型的参数
(tensor([0, 1, 2], device='cuda:0'), tensor([2, 3, 4], device='cuda:0'))
>>> cuda_g.in_edges(th.tensor([2, 3, 4]).to('cuda:0')) # 张量类型的参数必须在GPU上
(tensor([0, 1, 2], device='cuda:0'), tensor([2, 3, 4], device='cuda:0'))
>>> cuda_g.ndata['h'] = th.randn(5, 4) # ERROR! 特征也必须在GPU上!
DGLError: Cannot assign node feature "h" on device cpu to a graph on device
cuda:0. Call DGLGraph.to() to copy the graph to the same device.
.. _guide_cn-graph-graphs-nodes-edges:
1.2 图、节点和边
--------------
:ref:`(English Version)<guide-graph-graphs-nodes-edges>`
DGL使用一个唯一的整数来表示一个节点,称为点ID;并用对应的两个端点ID表示一条边。同时,DGL也会根据边被添加的顺序,
给每条边分配一个唯一的整数编号,称为边ID。节点和边的ID都是从0开始构建的。在DGL的图里,所有的边都是有方向的,
即边 :math:`(u, v)` 表示它是从节点 :math:`u` 指向节点 :math:`v` 的。
对于多个节点,DGL使用一个一维的整型张量(如,PyTorch的Tensor类,TensorFlow的Tensor类或MXNet的ndarray类)来保存图的点ID,
DGL称之为"节点张量"。为了指代多条边,DGL使用一个包含2个节点张量的元组 :math:`(U, V)` ,其中,用 :math:`(U[i], V[i])` 指代一条
:math:`U[i]` 到 :math:`V[i]` 的边。
创建一个 :class:`~dgl.DGLGraph` 对象的一种方法是使用 :func:`dgl.graph` 函数。它接受一个边的集合作为输入。DGL也支持从其他的数据源来创建图对象。
读者可参考 :ref:`guide_cn-graph-external`。
下面的代码段使用了 :func:`dgl.graph` 函数来构建一个 :class:`~dgl.DGLGraph` 对象,对应着下图所示的包含4个节点的图。
其中一些代码演示了查询图结构的部分API的使用方法。
.. figure:: https://data.dgl.ai/asset/image/user_guide_graphch_1.png
:height: 200px
:width: 300px
:align: center
.. code::
>>> import dgl
>>> import torch as th
>>> # 边 0->1, 0->2, 0->3, 1->3
>>> u, v = th.tensor([0, 0, 0, 1]), th.tensor([1, 2, 3, 3])
>>> g = dgl.graph((u, v))
>>> print(g) # 图中节点的数量是DGL通过给定的图的边列表中最大的点ID推断所得出的
Graph(num_nodes=4, num_edges=4,
ndata_schemes={}
edata_schemes={})
>>> # 获取节点的ID
>>> print(g.nodes())
tensor([0, 1, 2, 3])
>>> # 获取边的对应端点
>>> print(g.edges())
(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 3]))
>>> # 获取边的对应端点和边ID
>>> print(g.edges(form='all'))
(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 3]), tensor([0, 1, 2, 3]))
>>> # 如果具有最大ID的节点没有边,在创建图的时候,用户需要明确地指明节点的数量。
>>> g = dgl.graph((u, v), num_nodes=8)
对于无向的图,用户需要为每条边都创建两个方向的边。可以使用 :func:`dgl.to_bidirected` 函数来实现这个目的。
如下面的代码段所示,这个函数可以把原图转换成一个包含反向边的图。
.. code::
>>> bg = dgl.to_bidirected(g)
>>> bg.edges()
(tensor([0, 0, 0, 1, 1, 2, 3, 3]), tensor([1, 2, 3, 0, 3, 0, 0, 1]))
.. note::
由于Tensor类内部使用C来存储,且显性定义了数据类型以及存储的设备信息,DGL推荐使用Tensor作为DGL API的输入。
不过大部分的DGL API也支持Python的可迭代类型(比如列表)或numpy.ndarray类型作为API的输入,方便用户快速进行开发验证。
DGL支持使用 :math:`32` 位或 :math:`64` 位的整数作为节点ID和边ID。节点和边ID的数据类型必须一致。如果使用 :math:`64` 位整数,
DGL可以处理最多 :math:`2^{63} - 1` 个节点或边。不过,如果图里的节点或者边的数量小于 :math:`2^{63} - 1` ,用户最好使用 :math:`32` 位整数。
这样不仅能提升速度,还能减少内存的使用。DGL提供了进行数据类型转换的方法,如下例所示。
.. code::
>>> edges = th.tensor([2, 5, 3]), th.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=th.int32) # 使用int32构建图
>>> g32.idtype
torch.int32
>>> g64_2 = g32.long() # 转换成int64
>>> g64_2.idtype
torch.int64
>>> g32_2 = g64.int() # 转换成int32
>>> g32_2.idtype
torch.int32
相关API::func:`dgl.graph`、 :func:`dgl.DGLGraph.nodes`、 :func:`dgl.DGLGraph.edges`、 :func:`dgl.to_bidirected`、
:func:`dgl.DGLGraph.int`、 :func:`dgl.DGLGraph.long` 和 :py:attr:`dgl.DGLGraph.idtype`。
.. _guide_cn-graph-heterogeneous:
1.5 异构图
---------
:ref:`(English Version)<guide-graph-heterogeneous>`
相比同构图,异构图里可以有不同类型的节点和边。这些不同类型的节点和边具有独立的ID空间和特征。
例如在下图中,"用户"和"游戏"节点的ID都是从0开始的,而且两种节点具有不同的特征。
.. figure:: https://data.dgl.ai/asset/image/user_guide_graphch_2.png
一个异构图示例。该图具有两种类型的节点("用户"和"游戏")和两种类型的边("关注"和"玩")。
创建异构图
^^^^^^^^
在DGL中,一个异构图由一系列子图构成,一个子图对应一种关系。每个关系由一个字符串三元组
定义 ``(源节点类型, 边类型, 目标节点类型)`` 。由于这里的关系定义消除了边类型的歧义,DGL称它们为规范边类型。
下面的代码是一个在DGL中创建异构图的示例。
.. code::
>>> import dgl
>>> import torch as th
>>> # 创建一个具有3种节点类型和3种边类型的异构图
>>> graph_data = {
... ('drug', 'interacts', 'drug'): (th.tensor([0, 1]), th.tensor([1, 2])),
... ('drug', 'interacts', 'gene'): (th.tensor([0, 1]), th.tensor([2, 3])),
... ('drug', 'treats', 'disease'): (th.tensor([1]), th.tensor([2]))
... }
>>> g = dgl.heterograph(graph_data)
>>> g.ntypes
['disease', 'drug', 'gene']
>>> g.etypes
['interacts', 'interacts', 'treats']
>>> g.canonical_etypes
[('drug', 'interacts', 'drug'),
('drug', 'interacts', 'gene'),
('drug', 'treats', 'disease')]
注意,同构图和二分图只是一种特殊的异构图,它们只包括一种关系。
.. code::
>>> # 一个同构图
>>> dgl.heterograph({('node_type', 'edge_type', 'node_type'): (u, v)})
>>> # 一个二分图
>>> dgl.heterograph({('source_type', 'edge_type', 'destination_type'): (u, v)})
与异构图相关联的 *metagraph* 就是图的模式。它指定节点集和节点之间的边的类型约束。
*metagraph* 中的一个节点 :math:`u` 对应于相关异构图中的一个节点类型。
*metagraph* 中的边 :math:`(u,v)` 表示在相关异构图中存在从 :math:`u` 型节点到 :math:`v` 型节点的边。
.. code::
>>> 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')])
>>> g.metagraph().edges()
OutMultiEdgeDataView([('drug', 'drug'), ('drug', 'gene'), ('drug', 'disease')])
相关API: :func:`dgl.heterograph`、 :py:attr:`~dgl.DGLGraph.ntypes`、 :py:attr:`~dgl.DGLGraph.etypes`、
:py:attr:`~dgl.DGLGraph.canonical_etypes`、 :py:attr:`~dgl.DGLGraph.metagraph`。
使用多种类型
^^^^^^^^^^
当引入多种节点和边类型后,用户在调用DGLGraph API以获取特定类型的信息时,需要指定具体的节点和边类型。此外,不同类型的节点和边具有单独的ID。
.. code::
>>> # 获取图中所有节点的数量
>>> g.num_nodes()
10
>>> # 获取drug节点的数量
>>> g.num_nodes('drug')
3
>>> # 不同类型的节点有单独的ID。因此,没有指定节点类型就没有明确的返回值。
>>> g.nodes()
DGLError: Node type name must be specified if there are more than one node types.
>>> g.nodes('drug')
tensor([0, 1, 2])
为了设置/获取特定节点和边类型的特征,DGL提供了两种新类型的语法: `g.nodes['node_type'].data['feat_name']` 和 `g.edges['edge_type'].data['feat_name']` 。
.. code::
>>> # 设置/获取"drug"类型的节点的"hv"特征
>>> g.nodes['drug'].data['hv'] = th.ones(3, 1)
>>> g.nodes['drug'].data['hv']
tensor([[1.],
[1.],
[1.]])
>>> # 设置/获取"treats"类型的边的"he"特征
>>> g.edges['treats'].data['he'] = th.zeros(1, 1)
>>> g.edges['treats'].data['he']
tensor([[0.]])
如果图里只有一种节点或边类型,则不需要指定节点或边的类型。
.. code::
>>> g = dgl.heterograph({
... ('drug', 'interacts', 'drug'): (th.tensor([0, 1]), th.tensor([1, 2])),
... ('drug', 'is similar', 'drug'): (th.tensor([0, 1]), th.tensor([2, 3]))
... })
>>> g.nodes()
tensor([0, 1, 2, 3])
>>> # 设置/获取单一类型的节点或边特征,不必使用新的语法
>>> g.ndata['hv'] = th.ones(4, 1)
.. note::
当边类型唯一地确定了源节点和目标节点的类型时,用户可以只使用一个字符串而不是字符串三元组来指定边类型。例如,
对于具有两个关系 ``('user', 'plays', 'game')`` 和 ``('user', 'likes', 'game')`` 的异构图,
只使用 ``'plays'`` 或 ``'like'`` 来指代这两个关系是可以的。
从磁盘加载异构图
^^^^^^^^^^^^^
逗号分隔值(CSV)
""""""""""""""
一种存储异构图的常见方法是在不同的CSV文件中存储不同类型的节点和边。下面是一个例子。
.. code::
# 数据文件夹
data/
|-- drug.csv # drug节点
|-- gene.csv # gene节点
|-- disease.csv # disease节点
|-- drug-interact-drug.csv # drug-drug相互作用边
|-- drug-interact-gene.csv # drug-gene相互作用边
|-- drug-treat-disease.csv # drug-disease治疗边
与同构图的情况类似,用户可以使用像Pandas这样的包先将CSV文件解析为numpy数组或框架张量,再构建一个关系字典,并用它构造一个异构图。
这种方法也适用于其他流行的文件格式,比如GML或JSON。
DGL二进制格式
"""""""""""
DGL提供了 :func:`dgl.save_graphs` 和 :func:`dgl.load_graphs` 函数,分别用于以二进制格式保存异构图和加载它们。
边类型子图
^^^^^^^^
用户可以通过指定要保留的关系来创建异构图的子图,相关的特征也会被拷贝。
.. code::
>>> g = dgl.heterograph({
... ('drug', 'interacts', 'drug'): (th.tensor([0, 1]), th.tensor([1, 2])),
... ('drug', 'interacts', 'gene'): (th.tensor([0, 1]), th.tensor([2, 3])),
... ('drug', 'treats', 'disease'): (th.tensor([1]), th.tensor([2]))
... })
>>> g.nodes['drug'].data['hv'] = th.ones(3, 1)
>>> # 保留关系 ('drug', 'interacts', 'drug') 和 ('drug', 'treats', 'disease') 。
>>> # 'drug' 和 'disease' 类型的节点也会被保留
>>> eg = dgl.edge_type_subgraph(g, [('drug', 'interacts', 'drug'),
... ('drug', 'treats', 'disease')])
>>> eg
Graph(num_nodes={'disease': 3, 'drug': 3},
num_edges={('drug', 'interacts', 'drug'): 2, ('drug', 'treats', 'disease'): 1},
metagraph=[('drug', 'drug', 'interacts'), ('drug', 'disease', 'treats')])
>>> # 相关的特征也会被拷贝
>>> eg.nodes['drug'].data['hv']
tensor([[1.],
[1.],
[1.]])
将异构图转化为同构图
^^^^^^^^^^^^^^^^
异构图为管理不同类型的节点和边及其相关特征提供了一个清晰的接口。这在以下情况下尤其有用:
1. 不同类型的节点和边的特征具有不同的数据类型或大小。
2. 用户希望对不同类型的节点和边应用不同的操作。
如果上述情况不适用,并且用户不希望在建模中区分节点和边的类型,则DGL允许使用 :func:`dgl.DGLGraph.to_homogeneous` API将异构图转换为同构图。
具体行为如下:
1. 用从0开始的连续整数重新标记所有类型的节点和边。
2. 对所有的节点和边合并用户指定的特征。
.. code::
>>> g = dgl.heterograph({
... ('drug', 'interacts', 'drug'): (th.tensor([0, 1]), th.tensor([1, 2])),
... ('drug', 'treats', 'disease'): (th.tensor([1]), th.tensor([2]))})
>>> g.nodes['drug'].data['hv'] = th.zeros(3, 1)
>>> g.nodes['disease'].data['hv'] = th.ones(3, 1)
>>> g.edges['interacts'].data['he'] = th.zeros(2, 1)
>>> g.edges['treats'].data['he'] = th.zeros(1, 2)
>>> # 默认情况下不进行特征合并
>>> hg = dgl.to_homogeneous(g)
>>> 'hv' in hg.ndata
False
>>> # 拷贝边的特征
>>> # 对于要拷贝的特征,DGL假定不同类型的节点或边的需要合并的特征具有相同的大小和数据类型
>>> hg = dgl.to_homogeneous(g, edata=['he'])
DGLError: Cannot concatenate column ‘he’ with shape Scheme(shape=(2,), dtype=torch.float32) and shape Scheme(shape=(1,), dtype=torch.float32)
>>> # 拷贝节点特征
>>> hg = dgl.to_homogeneous(g, ndata=['hv'])
>>> hg.ndata['hv']
tensor([[1.],
[1.],
[1.],
[0.],
[0.],
[0.]])
原始的节点或边的类型和对应的ID被存储在 :py:attr:`~dgl.DGLGraph.ndata` 和 :py:attr:`~dgl.DGLGraph.edata` 中。
.. code::
>>> # 异构图中节点类型的顺序
>>> g.ntypes
['disease', 'drug']
>>> # 原始节点类型
>>> hg.ndata[dgl.NTYPE]
tensor([0, 0, 0, 1, 1, 1])
>>> # 原始的特定类型节点ID
>>> hg.ndata[dgl.NID]
>>> tensor([0, 1, 2, 0, 1, 2])
>>> # 异构图中边类型的顺序
>>> g.etypes
['interacts', 'treats']
>>> # 原始边类型
>>> hg.edata[dgl.ETYPE]
tensor([0, 0, 1])
>>> # 原始的特定类型边ID
>>> hg.edata[dgl.EID]
tensor([0, 1, 0])
出于建模的目的,用户可能需要将一些关系合并,并对它们应用相同的操作。为了实现这一目的,可以先抽取异构图的边类型子图,然后将该子图转换为同构图。
.. code::
>>> g = dgl.heterograph({
... ('drug', 'interacts', 'drug'): (th.tensor([0, 1]), th.tensor([1, 2])),
... ('drug', 'interacts', 'gene'): (th.tensor([0, 1]), th.tensor([2, 3])),
... ('drug', 'treats', 'disease'): (th.tensor([1]), th.tensor([2]))
... })
>>> sub_g = dgl.edge_type_subgraph(g, [('drug', 'interacts', 'drug'),
... ('drug', 'interacts', 'gene')])
>>> h_sub_g = dgl.to_homogeneous(sub_g)
>>> h_sub_g
Graph(num_nodes=7, num_edges=4,
...)
.. _guide_cn-graph:
第1章:图
========
:ref:`(English Version)<guide-graph>`
图表示实体(节点)和它们的关系(边),其中节点和边可以是有类型的 (例如,``"用户"`` 和 ``"物品"`` 是两种不同类型的节点)。
DGL通过其核心数据结构 :class:`~dgl.DGLGraph` 提供了一个以图为中心的编程抽象。 :class:`~dgl.DGLGraph` 提供了接口以处理图的结构、节点/边
的特征,以及使用这些组件可以执行的计算。
本章路线图
--------
本章首先简要介绍了图的定义(见1.1节),然后介绍了一些 :class:`~dgl.DGLGraph` 相关的核心概念:
* :ref:`guide_cn-graph-basic`
* :ref:`guide_cn-graph-graphs-nodes-edges`
* :ref:`guide_cn-graph-feature`
* :ref:`guide_cn-graph-external`
* :ref:`guide_cn-graph-heterogeneous`
* :ref:`guide_cn-graph-gpu`
.. toctree::
:maxdepth: 1
:hidden:
:glob:
graph_cn-basic
graph_cn-graphs-nodes-edges
graph_cn-feature
graph_cn-external
graph_cn-heterogeneous
graph_cn-gpu
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment