FusedCSCSamplingGraph

class dgl.graphbolt.FusedCSCSamplingGraph(c_csc_graph: ScriptObject)[source]

基类: SamplingGraph

CSC 格式的采样图。

add_edge_attribute(name: str, tensor: Tensor) None[source]

按名称添加边属性张量。

参数:
  • name (str) – 边属性的名称。

  • tensor (torch.Tensor) – 边属性张量。

add_node_attribute(name: str, tensor: Tensor) None[source]

按名称添加节点属性张量。

参数:
  • name (str) – 节点属性的名称。

  • tensor (torch.Tensor) – 节点属性张量。

copy_to_shared_memory(shared_memory_name: str)[source]

将图复制到共享内存。

参数:

shared_memory_name (str) – 共享内存的名称。

返回:

共享内存上的复制 FusedCSCSamplingGraph 对象。

返回类型:

FusedCSCSamplingGraph

edge_attribute(name: str) Tensor | None[source]

按名称返回边属性张量。

参数:

name (str) – 边属性的名称。

返回:

如果存在,返回边属性张量。

返回类型:

torch.Tensor 或 None

in_subgraph(nodes: Tensor | Dict[str, Tensor]) SampledSubgraphImpl[source]

返回给定节点的入边导出的子图。

入子图相当于使用给定节点的入边创建一个新图。子图根据传入的 nodes 的顺序进行压缩。

参数:

nodes (torch.Tensor or Dict[str, torch.Tensor]) –

给定种子节点的 ID。
  • 如果 nodes 是一个张量:这意味着图是同构图,并且内部的 id 是同构 id。

  • 如果 nodes 是一个字典:键应该是节点类型,内部的 id 是异构 id。

返回:

入子图。

返回类型:

SampledSubgraphImpl

示例

>>> import dgl.graphbolt as gb
>>> import torch
>>> total_num_nodes = 5
>>> total_num_edges = 12
>>> ntypes = {"N0": 0, "N1": 1}
>>> etypes = {
...     "N0:R0:N0": 0, "N0:R1:N1": 1, "N1:R2:N0": 2, "N1:R3:N1": 3}
>>> indptr = torch.LongTensor([0, 3, 5, 7, 9, 12])
>>> indices = torch.LongTensor([0, 1, 4, 2, 3, 0, 1, 1, 2, 0, 3, 4])
>>> node_type_offset = torch.LongTensor([0, 2, 5])
>>> type_per_edge = torch.LongTensor(
...     [0, 0, 2, 2, 2, 1, 1, 1, 3, 1, 3, 3])
>>> graph = gb.fused_csc_sampling_graph(indptr, indices,
...     node_type_offset=node_type_offset,
...     type_per_edge=type_per_edge,
...     node_type_to_id=ntypes,
...     edge_type_to_id=etypes)
>>> nodes = {"N0":torch.LongTensor([1]), "N1":torch.LongTensor([1, 2])}
>>> in_subgraph = graph.in_subgraph(nodes)
>>> print(in_subgraph.sampled_csc)
{'N0:R0:N0': CSCFormatBase(indptr=tensor([0, 0]),
      indices=tensor([], dtype=torch.int64),
), 'N0:R1:N1': CSCFormatBase(indptr=tensor([0, 1, 2]),
            indices=tensor([1, 0]),
), 'N1:R2:N0': CSCFormatBase(indptr=tensor([0, 2]),
            indices=tensor([0, 1]),
), 'N1:R3:N1': CSCFormatBase(indptr=tensor([0, 1, 3]),
            indices=tensor([0, 1, 2]),
)}
node_attribute(name: str) Tensor | None[source]

按名称返回节点属性张量。

参数:

name (str) – 节点属性的名称。

返回:

如果存在,返回节点属性张量。

返回类型:

torch.Tensor 或 None

pin_memory_()[source]

FusedCSCSamplingGraph 就地复制到固定内存。返回就地修改后的同一对象。

sample_layer_neighbors(seeds: Tensor | Dict[str, Tensor], fanouts: Tensor, replace: bool = False, probs_name: str | None = None, returning_indices_and_original_edge_ids_are_optional: bool = False, random_seed: Tensor | None = None, seed2_contribution: float = 0.0, async_op: bool = False) SampledSubgraphImpl[source]

通过 NeurIPS 2023 论文 《层邻居采样 – 化解 GNN 中的邻居爆炸》 中的层邻居采样方法,对给定节点的邻居边进行采样并返回导出的子图。

参数:
  • seeds (torch.Tensor or Dict[str, torch.Tensor]) –

    给定种子节点的 ID。
    • 如果 nodes 是一个张量:这意味着图是同构图,并且内部的 id 是同构 id。

    • 如果 nodes 是一个字典:键应该是节点类型,内部的 id 是异构 id。

  • fanouts (torch.Tensor) –

    每个节点采样的边数,考虑或不考虑边类型。

    • 当长度为 1 时,表示 fanout 作为一个整体应用于节点的所有邻居,无论边类型如何。

    • 否则,长度应等于边类型的数量,并且每个 fanout 值对应于节点的特定边类型。

    每个 fanout 的值应 >= 0 或 = -1。
    • 当值为 -1 时,所有邻居(如果加权,则概率非零)将被采样一次,无论是否替换。这等效于当 fanout 大于等于邻居数量(且 replace 设置为 false)时选择所有概率非零的邻居。

    • 当值为非负整数时,它用作选择邻居的最小阈值。

  • replace (bool) – 布尔值,指示采样是否带有替换。如果为 True,一个值可以被多次选择。否则,每个值只能被选择一次。

  • probs_name (str, optional) – 可选字符串,指定边属性的名称。此属性张量应包含与节点每个邻居边对应的(未归一化)概率。它必须是 1D 浮点型或布尔型张量,元素数量等于总边数。

  • returning_indices_and_original_edge_ids_are_optional (bool) – 布尔值,指示调用此函数时是否允许索引和原始边 ID 张量保持未初始化。在这种情况下,如果缺少其中任何一个,用户有责任使用 _edge_ids_in_fused_csc_sampling_graph 来收集它们。

  • random_seed (torch.Tensor, optional) –

    一个包含一个或两个元素的 int64 张量。

    传入的 random_seed 使得对于任何种子节点 s 及其邻居 t,在任何使用相同 random seed 调用此函数时,滚动的随机变量 r_t 都是相同的。作为同一批次的一部分进行采样时,需要相同的种子,以便 LABOR 可以全局采样。一个例子是对于异构图,每个边类型传入一个单独的 random seed。与为每个边类型设置唯一的 random seed 相比,这将采样少得多的节点。如果为异构图的每个边类型单独调用此函数,并使用不同的 random seed,那么它将为每个边类型在本地运行 LABOR,导致采样更多的节点。

    如果调用此函数时没有 random_seed,我们将从 GraphBolt 获取一个随机数作为 random seed。如果多次调用此函数作为单个批次的一部分进行采样,请使用相同的 random_seed 参数。

    如果给定两个数字,则 seed2_contribution 参数决定了两个随机种子之间的插值。

  • seed2_contribution (float, optional) – 一个在 [0, 1) 之间的浮点值,决定了第二个随机种子 random_seed[-1] 对生成随机变量的贡献。

  • async_op (bool) – 布尔值,指示调用是否是异步的。如果是,可以通过对返回的 future 调用 wait 来获取结果。

返回:

采样的子图。

返回类型:

SampledSubgraphImpl

示例

>>> import dgl.graphbolt as gb
>>> import torch
>>> ntypes = {"n1": 0, "n2": 1}
>>> etypes = {"n1:e1:n2": 0, "n2:e2:n1": 1}
>>> indptr = torch.LongTensor([0, 2, 4, 6, 7, 9])
>>> indices = torch.LongTensor([2, 4, 2, 3, 0, 1, 1, 0, 1])
>>> node_type_offset = torch.LongTensor([0, 2, 5])
>>> type_per_edge = torch.LongTensor([1, 1, 1, 1, 0, 0, 0, 0, 0])
>>> graph = gb.fused_csc_sampling_graph(indptr, indices,
...     node_type_offset=node_type_offset,
...     type_per_edge=type_per_edge,
...     node_type_to_id=ntypes,
...     edge_type_to_id=etypes)
>>> nodes = {'n1': torch.LongTensor([0]), 'n2': torch.LongTensor([0])}
>>> fanouts = torch.tensor([1, 1])
>>> subgraph = graph.sample_layer_neighbors(nodes, fanouts)
>>> print(subgraph.sampled_csc)
{'n1:e1:n2': CSCFormatBase(indptr=tensor([0, 1]),
            indices=tensor([0]),
), 'n2:e2:n1': CSCFormatBase(indptr=tensor([0, 1]),
            indices=tensor([2]),
)}
sample_negative_edges_uniform(edge_type, node_pairs, negative_ratio)[source]

通过根据均匀分布随机选择负源-目标边来采样负边。对于每条边 (u, v),它应该生成 negative_ratio 对负边 (u, v'),其中 v' 从图中的所有节点中均匀选择。 u 与对应的正边完全相同。它返回将正边与负边连接的结果。在负边中,负源从对应的正边构建。

参数:
  • edge_type (str) – 提供给 node_pairs 的边类型。任何采样的负边也将具有相同的类型。如果设置为 None,则将被视为同构图。

  • node_pairs (torch.Tensor) – 一个 2D 张量,表示源-目标格式的 N 对正边,其中“正”表示这些边存在于图中。值得注意的是,在异构图的上下文中,这些张量中的 id 表示异构 id。

  • negative_ratio (int) – 负样本数与正样本数之比。

返回:

一个 2D 张量,表示 N 对正负源-目标节点对。在异构图的上下文中,输入节点和选定节点都由异构 ID 表示,并且形成的边是输入类型 edge_type 的。请注意,负样本指的是假负样本,这意味着边可能存在也可能不存在于图中。

返回类型:

torch.Tensor

sample_neighbors(seeds: Tensor | Dict[str, Tensor], fanouts: Tensor, replace: bool = False, probs_name: str | None = None, returning_indices_and_original_edge_ids_are_optional: bool = False, async_op: bool = False) SampledSubgraphImpl[source]

采样给定节点的邻居边并返回导出的子图。

参数:
  • seeds (torch.Tensor or Dict[str, torch.Tensor]) –

    给定种子节点的 ID。
    • 如果 nodes 是一个张量:这意味着图是同构图,并且内部的 id 是同构 id。

    • 如果 nodes 是一个字典:键应该是节点类型,内部的 id 是异构 id。

  • fanouts (torch.Tensor) –

    每个节点采样的边数,考虑或不考虑边类型。

    • 当长度为 1 时,表示 fanout 作为一个整体应用于节点的所有邻居,无论边类型如何。

    • 否则,长度应等于边类型的数量,并且每个 fanout 值对应于节点的特定边类型。

    每个 fanout 的值应 >= 0 或 = -1。
    • 当值为 -1 时,所有邻居(如果加权,则概率非零)将被采样一次,无论是否替换。这等效于当 fanout 大于等于邻居数量(且 replace 设置为 false)时选择所有概率非零的邻居。

    • 当值为非负整数时,它用作选择邻居的最小阈值。

  • replace (bool) – 布尔值,指示采样是否带有替换。如果为 True,一个值可以被多次选择。否则,每个值只能被选择一次。

  • probs_name (str, optional) – 可选字符串,指定使用的边属性的名称。此属性张量应包含与节点每个邻居边对应的(未归一化)概率。它必须是 1D 浮点型或布尔型张量,元素数量等于总边数。

  • returning_indices_and_original_edge_ids_are_optional (bool) – 布尔值,指示调用此函数时是否允许索引和原始边 ID 张量保持未初始化。在这种情况下,如果缺少其中任何一个,用户有责任使用 _edge_ids_in_fused_csc_sampling_graph 来收集它们。

  • async_op (bool) – 布尔值,指示调用是否是异步的。如果是,可以通过对返回的 future 调用 wait 来获取结果。

返回:

采样的子图。

返回类型:

SampledSubgraphImpl

示例

>>> import dgl.graphbolt as gb
>>> import torch
>>> ntypes = {"n1": 0, "n2": 1}
>>> etypes = {"n1:e1:n2": 0, "n2:e2:n1": 1}
>>> indptr = torch.LongTensor([0, 2, 4, 6, 7, 9])
>>> indices = torch.LongTensor([2, 4, 2, 3, 0, 1, 1, 0, 1])
>>> node_type_offset = torch.LongTensor([0, 2, 5])
>>> type_per_edge = torch.LongTensor([1, 1, 1, 1, 0, 0, 0, 0, 0])
>>> graph = gb.fused_csc_sampling_graph(indptr, indices,
...     node_type_offset=node_type_offset,
...     type_per_edge=type_per_edge,
...     node_type_to_id=ntypes,
...     edge_type_to_id=etypes)
>>> nodes = {'n1': torch.LongTensor([0]), 'n2': torch.LongTensor([0])}
>>> fanouts = torch.tensor([1, 1])
>>> subgraph = graph.sample_neighbors(nodes, fanouts)
>>> print(subgraph.sampled_csc)
{'n1:e1:n2': CSCFormatBase(indptr=tensor([0, 1]),
            indices=tensor([0]),
), 'n2:e2:n1': CSCFormatBase(indptr=tensor([0, 1]),
            indices=tensor([2]),
)}
temporal_sample_layer_neighbors(seeds: Tensor | Dict[str, Tensor], seeds_timestamp: Tensor | Dict[str, Tensor], fanouts: Tensor, replace: bool = False, seeds_pre_time_window: Tensor | Dict[str, Tensor] | None = None, probs_name: str | None = None, node_timestamp_attr_name: str | None = None, edge_timestamp_attr_name: str | None = None, random_seed: Tensor | None = None, seed2_contribution: float = 0.0) ScriptObject[source]

通过 NeurIPS 2023 论文 《层邻居采样 – 化解 GNN 中的邻居爆炸》 中的层邻居采样方法,按时间顺序采样给定节点的邻居边并返回导出的子图。

如果给定 node_timestamp_attr_nameedge_timestamp_attr_name,则采样到的种子节点的邻居或边的时间戳必须小于种子节点的时间戳。

参数:
  • seeds (torch.Tensor) – 给定种子节点的 ID。

  • seeds_timestamp (torch.Tensor) – 给定种子节点的时间戳。

  • fanouts (torch.Tensor) –

    每个节点采样的边数,考虑或不考虑边类型。

    • 当长度为 1 时,表示 fanout 作为一个整体应用于节点的所有邻居,无论边类型如何。

    • 否则,长度应等于边类型的数量,并且每个 fanout 值对应于节点的特定边类型。

    每个 fanout 的值应 >= 0 或 = -1。
    • 当值为 -1 时,所有邻居(如果加权,则概率非零)将被采样一次,无论是否替换。这等效于当 fanout 大于等于邻居数量(且 replace 设置为 false)时选择所有概率非零的邻居。

    • 当值为非负整数时,它用作选择邻居的最小阈值。

  • replace (bool) – 布尔值,指示采样是否带有替换。如果为 True,一个值可以被多次选择。否则,每个值只能被选择一次。

  • seeds_pre_time_window (torch.Tensor) – 节点的时间窗口表示 seeds_timestamp 之前的一段时间。如果提供,将只过滤时间戳落在 [seeds_timestamp - seeds_pre_time_window, seeds_timestamp] 范围内的邻居和相关边。

  • probs_name (str, optional) – 可选字符串,指定边属性的名称。此属性张量应包含与节点每个邻居边对应的(未归一化)概率。它必须是 1D 浮点型或布尔型张量,元素数量等于总边数。

  • node_timestamp_attr_name (str, optional) – 可选字符串,指定节点属性的名称。

  • edge_timestamp_attr_name (str, optional) – 可选字符串,指定边属性的名称。

  • random_seed (torch.Tensor, optional) –

    一个包含一个或两个元素的 int64 张量。

    传入的 random_seed 使得对于任何种子节点 s 及其邻居 t,在任何使用相同 random seed 调用此函数时,滚动的随机变量 r_t 都是相同的。作为同一批次的一部分进行采样时,需要相同的种子,以便 LABOR 可以全局采样。一个例子是对于异构图,每个边类型传入一个单独的 random seed。与为每个边类型设置唯一的 random seed 相比,这将采样少得多的节点。如果为异构图的每个边类型单独调用此函数,并使用不同的 random seed,那么它将为每个边类型在本地运行 LABOR,导致采样更多的节点。

    如果调用此函数时没有 random_seed,我们将从 GraphBolt 获取一个随机数作为 random seed。如果多次调用此函数作为单个批次的一部分进行采样,请使用相同的 random_seed 参数。

    如果给定两个数字,则 seed2_contribution 参数决定了两个随机种子之间的插值。

  • seed2_contribution (float, optional) – 一个在 [0, 1) 之间的浮点值,决定了第二个随机种子 random_seed[-1] 对生成随机变量的贡献。

返回:

采样的子图。

返回类型:

SampledSubgraphImpl

temporal_sample_neighbors(seeds: Tensor | Dict[str, Tensor], seeds_timestamp: Tensor | Dict[str, Tensor], fanouts: Tensor, replace: bool = False, seeds_pre_time_window: Tensor | Dict[str, Tensor] | None = None, probs_name: str | None = None, node_timestamp_attr_name: str | None = None, edge_timestamp_attr_name: str | None = None) ScriptObject[source]

按时间顺序采样给定节点的邻居边并返回导出的子图。

如果给定 node_timestamp_attr_nameedge_timestamp_attr_name,则采样到的种子节点的邻居或边的时间戳必须小于种子节点的时间戳。

参数:
  • seeds (torch.Tensor) – 给定种子节点的 ID。

  • seeds_timestamp (torch.Tensor) – 给定种子节点的时间戳。

  • fanouts (torch.Tensor) –

    每个节点采样的边数,考虑或不考虑边类型。

    • 当长度为 1 时,表示 fanout 作为一个整体应用于节点的所有邻居,无论边类型如何。

    • 否则,长度应等于边类型的数量,并且每个 fanout 值对应于节点的特定边类型。

    每个 fanout 的值应 >= 0 或 = -1。
    • 当值为 -1 时,所有邻居(如果加权,则概率非零)将被采样一次,无论是否替换。这等效于当 fanout 大于等于邻居数量(且 replace 设置为 false)时选择所有概率非零的邻居。

    • 当值为非负整数时,它用作选择邻居的最小阈值。

  • replace (bool) – 布尔值,指示采样是否带有替换。如果为 True,一个值可以被多次选择。否则,每个值只能被选择一次。

  • seeds_pre_time_window (torch.Tensor) – 节点的时间窗口表示 seeds_timestamp 之前的一段时间。如果提供,将只过滤时间戳落在 [seeds_timestamp - seeds_pre_time_window, seeds_timestamp] 范围内的邻居和相关边。

  • probs_name (str, optional) – 可选字符串,指定边属性的名称。此属性张量应包含与节点每个邻居边对应的(未归一化)概率。它必须是 1D 浮点型或布尔型张量,元素数量等于总边数。

  • node_timestamp_attr_name (str, optional) – 可选字符串,指定节点属性的名称。

  • edge_timestamp_attr_name (str, optional) – 可选字符串,指定边属性的名称。

返回:

采样的子图。

返回类型:

SampledSubgraphImpl

to(device: device) None[source]

FusedCSCSamplingGraph 复制到指定的设备。

property csc_indptr: tensor

返回 CSC 图中的索引指针。

返回:

CSC 图中的索引指针。一个形状为 (total_num_nodes+1,) 的整数张量。

返回类型:

torch.tensor

property edge_attributes: Dict[str, Tensor] | None

返回边属性字典。

返回:

如果存在,返回边属性字典。每个键表示属性的名称,而相应的值保存属性的具体值。每个值的长度应与总边数匹配。

返回类型:

Dict[str, torch.Tensor] 或 None

property edge_type_to_id: Dict[str, int] | None

如果存在,返回边类型到 id 的字典。

返回:

如果存在,返回一个将边类型映射到边类型 id 的字典。

返回类型:

Dict[str, int] 或 None

property indices: tensor

返回 CSC 图中的索引。

返回:

CSC 图中的索引。一个形状为 (total_num_edges,) 的整数张量。

返回类型:

torch.tensor

注意事项

假定每个节点的边已经按边类型 id 排序。

property node_attributes: Dict[str, Tensor] | None

返回节点属性字典。

返回:

如果存在,返回节点属性字典。每个键表示属性的名称,而相应的值保存属性的具体值。每个值的长度应与总节点数匹配。

返回类型:

Dict[str, torch.Tensor] 或 None

property node_type_offset: Tensor | None

如果存在,返回节点类型偏移张量。不要就地修改返回的张量。

返回:

如果存在,返回形状为 (num_node_types + 1,) 的 1D 整数张量。张量按升序排列,因为相同类型的节点具有连续的 ID,并且较大的节点 ID 与较大的节点类型 ID 配对。第一个值为 0,最后一个值为节点数。ID 在 node_type_offset_[i]~node_type_offset_[i+1] 之间的节点类型 id 为 ‘i’。

返回类型:

torch.Tensor 或 None

property node_type_to_id: Dict[str, int] | None

如果存在,返回节点类型到 id 的字典。

返回:

如果存在,返回一个将节点类型映射到节点类型 id 的字典。

返回类型:

Dict[str, int] 或 None

property num_edges: int | Dict[str, int]

图中的边数。 - 如果图是同构的,返回一个整数。 - 如果图是异构的,返回一个字典。

返回:

边数。整数表示同构图的总边数;字典表示异构图按边类型划分的边数。

返回类型:

Union[int, Dict[str, int]]

示例

>>> import dgl.graphbolt as gb, torch
>>> total_num_nodes = 5
>>> total_num_edges = 12
>>> ntypes = {"N0": 0, "N1": 1}
>>> etypes = {"N0:R0:N0": 0, "N0:R1:N1": 1,
...     "N1:R2:N0": 2, "N1:R3:N1": 3}
>>> indptr = torch.LongTensor([0, 3, 5, 7, 9, 12])
>>> indices = torch.LongTensor([0, 1, 4, 2, 3, 0, 1, 1, 2, 0, 3, 4])
>>> node_type_offset = torch.LongTensor([0, 2, 5])
>>> type_per_edge = torch.LongTensor(
...     [0, 0, 2, 2, 2, 1, 1, 1, 3, 1, 3, 3])
>>> metadata = gb.GraphMetadata(ntypes, etypes)
>>> graph = gb.fused_csc_sampling_graph(indptr, indices, node_type_offset,
...     type_per_edge, None, metadata)
>>> print(graph.num_edges)
{'N0:R0:N0': 2, 'N0:R1:N1': 1, 'N1:R2:N0': 2, 'N1:R3:N1': 3}
property num_nodes: int | Dict[str, int]

图中的节点数。 - 如果图是同构的,返回一个整数。 - 如果图是异构的,返回一个字典。

返回:

节点数。整数表示同构图的总节点数;字典表示异构图按节点类型划分的节点数。

返回类型:

Union[int, Dict[str, int]]

示例

>>> import dgl.graphbolt as gb, torch
>>> total_num_nodes = 5
>>> total_num_edges = 12
>>> ntypes = {"N0": 0, "N1": 1}
>>> etypes = {"N0:R0:N0": 0, "N0:R1:N1": 1,
...     "N1:R2:N0": 2, "N1:R3:N1": 3}
>>> indptr = torch.LongTensor([0, 3, 5, 7, 9, 12])
>>> indices = torch.LongTensor([0, 1, 4, 2, 3, 0, 1, 1, 2, 0, 3, 4])
>>> node_type_offset = torch.LongTensor([0, 2, 5])
>>> type_per_edge = torch.LongTensor(
...     [0, 0, 2, 2, 2, 1, 1, 1, 3, 1, 3, 3])
>>> graph = gb.fused_csc_sampling_graph(indptr, indices,
...     node_type_offset=node_type_offset,
...     type_per_edge=type_per_edge,
...     node_type_to_id=ntypes,
...     edge_type_to_id=etypes)
>>> print(graph.num_nodes)
{'N0': 2, 'N1': 3}
property total_num_edges: int

返回图中的边数。

返回:

图中的边数。

返回类型:

int

property total_num_nodes: int

返回图中的节点数。

返回:

稠密格式中的行数。

返回类型:

int

property type_per_edge: Tensor | None

如果存在,返回边类型张量。

返回:

如果存在,返回形状为 (total_num_edges,) 的 1D 整数张量,其中包含图中每条边的类型。

返回类型:

torch.Tensor 或 None