应用训练好的模型进行预测

此功能处于 Beta 测试阶段。有关功能分级的更多信息,请参阅 API 分级

在前面的章节中,我们已经了解了如何构建链接预测训练流水线并对其进行训练以生成预测模型。经过 训练 后,该可运行模型类型为 LinkPrediction,并驻留在 模型目录 中。

训练好的模型可以应用于图目录中的图,以创建包含预测链接的新关系类型。这些关系还具有一个属性,用于存储链接的预测概率,这可以被视为模型预测置信度的一种相对度量。

由于模型是基于使用特征流水线创建的特征进行训练的,因此相同的特征流水线会被存储在模型中,并在预测时执行。与训练期间一样,特征流水线中节点属性步骤所创建的中间节点属性是瞬态的,在执行后不可见。

当使用该模型进行预测时,输入图中的关系将根据配置进行分离。默认情况下,配置将与用于训练流水线的配置相同。在训练期间标记为上下文关系的关系将再次用于计算节点属性步骤中的特征。目标关系类型用于防止预测已存在的关系。此配置可以被覆盖,以指定不同的上下文或排除在预测之外的不同关系集。

预测图必须包含流水线所需的属性,并且所使用的数组属性必须与训练图具有相同的维度。如果预测图和训练图不同,它们具有相似的来源和语义也是有益的,这样模型才能实现良好的泛化。

搜索策略

为了找到尽可能好的新链接,GDS 提供了两种不同的搜索策略。

穷举搜索将简单地遍历所有可能的新链接,即检查所有尚未通过关系连接的节点对。对于每个这样的节点对,使用训练好的模型来预测它们是否应该通过链接连接。穷举搜索会找到所有最佳链接,但运行时间可能很长。

为了避免在考虑所有可能的新链接时可能运行很长时间(由于相对于节点数量的固有二次复杂度),GDS 提供了一种近似搜索策略。

近似搜索策略允许我们利用 K-最近邻算法,并将模型的预测函数作为其相似性度量,从而以准确性换取更短的运行时间。此上下文中的准确性是指结果与根据我们模型预测的最优可能新链接的接近程度,即穷举搜索所能做出的最佳预测。

每个节点的初始候选链接集是随机选择的,然后根据之前预测的链接在多次迭代中进行优化。有关搜索工作原理的更多详细信息,请参阅 K-最近邻文档

语法

各模式下的链接预测语法
在命名图上以 mutate 模式运行链接预测
CALL gds.beta.pipeline.linkPrediction.predict.mutate(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  postProcessingMillis: Integer,
  mutateMillis: Integer,
  relationshipsWritten: Integer,
  probabilityDistribution: Integer,
  samplingStats: Map,
  configuration: Map
表 1. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 2. 配置
名称 类型 默认 可选 描述

modelName

字符串

不适用

模型目录中链接预测模型的名称。

sourceNodeLabel

字符串

来自 trainConfig

预测链接应从其开始的节点标签名称。

targetNodeLabel

字符串

来自 trainConfig

预测链接应到达的节点标签名称。

relationshipTypes

字符串列表

来自 trainConfig

现有关系的名称。默认情况下,我们使用训练时的 targetRelationshipType

concurrency

整数

4 [1]

用于运行算法的并发线程数。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

mutateRelationshipType

字符串

不适用

用于写入投影图的新关系的关系类型。

mutateProperty

字符串

'probability'

GDS 图中写入结果的关系属性。

sampleRate

浮点数

不适用

用于确定每个节点考虑多少链接的采样率。如果设置为 1,则考虑所有可能的链接,即 穷举搜索。否则,将使用 近似搜索策略。值必须介于 0(不含)和 1(含)之间。

topN [2]

整数

不适用

输出预测关系的限制数量。

threshold [2]

浮点数

0.0

输出关系的最小预测概率。

topK [3]

整数

10

每个节点输出的预测关系数量限制。此值不能低于 1。

deltaThreshold [3]

浮点数

0.001

以百分比表示的值,用于确定何时提前停止。如果发生的更新少于配置的值,算法将停止。值必须介于 0(不含)和 1(含)之间。

maxIterations [3]

整数

100

硬限制,在进行这些迭代后停止算法。

randomJoins [3]

整数

10

在每次迭代之间,基于随机选择连接新节点邻居的尝试次数。

initialSampler [3]

字符串

"uniform"

用于为每个节点采样前 k 个随机邻居的方法。“uniform”和“randomWalk”(均不区分大小写)是有效的输入。

randomSeed [3]

整数

不适用

控制算法随机性的种子值。请注意,设置此参数时必须将 concurrency 设置为 1。

1. 在 GDS 会话 中,默认值为可用处理器数量。

2. 仅适用于 穷举搜索

3. 仅适用于 近似搜索策略。有关详细信息,请查看 kNN 语法章节

表 3. 结果
名称 类型 描述

preProcessingMillis

整数

预处理图的毫秒数。

computeMillis

整数

运行算法的毫秒数。

postProcessingMillis

整数

计算全局指标所耗费的毫秒数。

mutateMillis

整数

向投影图添加属性的毫秒数。

relationshipsWritten

整数

创建的关系数量。

probabilityDistribution

Map

预测概率分布的描述。

samplingStats

Map

关于预测如何采样的描述。

配置

Map

运行算法所使用的配置。

在命名图上以 stream 模式运行链接预测
CALL gds.beta.pipeline.linkPrediction.predict.stream(
  graphName: String,
  configuration: Map
)
YIELD
  node1: Integer,
  node2: Integer,
  probability: Float
表 4. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

存储在目录中的图的名称。

配置

Map

{}

算法特定配置和/或图过滤配置。

表 5. 配置
名称 类型 默认 可选 描述

modelName

字符串

不适用

模型目录中链接预测模型的名称。

sourceNodeLabel

字符串

来自 trainConfig

预测链接应从其开始的节点标签名称。

targetNodeLabel

字符串

来自 trainConfig

预测链接应到达的节点标签名称。

relationshipTypes

字符串列表

来自 trainConfig

现有关系的名称。默认情况下,我们使用训练时的 targetRelationshipType

concurrency

整数

4 [4]

用于运行算法的并发线程数。

jobId

字符串

内部生成

可以提供一个 ID 以更轻松地跟踪算法的进度。

logProgress

布尔值

true

如果禁用,进度百分比将不会被记录。

sampleRate

浮点数

不适用

用于确定每个节点考虑多少链接的采样率。如果设置为 1,则考虑所有可能的链接,即 穷举搜索。否则,将使用 近似搜索策略。值必须介于 0(不含)和 1(含)之间。

topN [5]

整数

不适用

输出预测关系的限制数量。

threshold [5]

浮点数

0.0

输出关系的最小预测概率。

topK [6]

整数

10

每个节点输出的预测关系数量限制。此值不能低于 1。

deltaThreshold [6]

浮点数

0.001

以百分比表示的值,用于确定何时提前停止。如果发生的更新少于配置的值,算法将停止。值必须介于 0(不含)和 1(含)之间。

maxIterations [6]

整数

100

硬限制,在进行这些迭代后停止算法。

randomJoins [6]

整数

10

在每次迭代之间,基于随机选择连接新节点邻居的尝试次数。

initialSampler [6]

字符串

"uniform"

用于为每个节点采样前 k 个随机邻居的方法。“uniform”和“randomWalk”(均不区分大小写)是有效的输入。

randomSeed [6]

整数

不适用

控制算法随机性的种子值。请注意,设置此参数时必须将 concurrency 设置为 1。

4. 在 GDS 会话 中,默认值为可用处理器数量。

5. 仅适用于 穷举搜索

6. 仅适用于 近似搜索策略。有关详细信息,请查看 kNN 语法章节

表 6. 结果
名称 类型 描述

node1

整数

第一个节点的节点 ID。

node2

整数

第二个节点的节点 ID。

probability

浮点数

节点之间链接的预测概率。

在此示例中,我们将展示如何使用训练好的模型来预测投影图中的新关系。为此,我们必须首先在模型目录中注册一个已经训练好的模型。我们将使用在 训练示例 中训练过的模型,并将其命名为 lp-pipeline-model。该算法会排除图中现有关系和自循环的预测。

在预测新链接时,有两种不同的策略来选择要考虑的节点对:穷举搜索和近似搜索。前者考虑所有可能的新链接,而后者将使用随机策略,仅考虑其中的一部分以实现更快的运行速度。我们将在下面的 mutate 示例 中分别进行解释。

write 和 mutate 过程产生的关系与输入一样是无向的。但是,不会产生平行关系。因此,例如在进行近似搜索时,如果 a — b 位于 a 的最佳预测中,而 b — a 位于 b 的最佳预测中,则最终只会产生一个无向关系 a — b。stream 过程只会产生一次节点对。

首先,我们将使用 estimate 过程来估算运行算法的成本。这可以在任何执行模式下完成。在本示例中,我们将使用 stream 模式。估算算法有助于了解在您的图上运行该算法会产生什么样的内存影响。当您稍后在某个执行模式下实际运行算法时,系统会执行一次估算。如果估算结果显示执行超出内存限制的可能性极高,则禁止执行。要了解更多信息,请参阅 自动估算和执行阻塞

有关 estimate 的更多详细信息,请参阅 内存估算

以下将估算应用模型所需的内存需求
CALL gds.beta.pipeline.linkPrediction.predict.stream.estimate('myGraph', {
  modelName: 'lp-pipeline-model',
  topN: 5,
  threshold: 0.5
})
YIELD requiredMemory
表 7. 结果
requiredMemory

"24 KiB"

stream 执行模式下,该算法返回每个节点对的链接概率。这使我们能够直接检查结果或在 Cypher 中对其进行后处理,而不会产生任何副作用。

有关 stream 模式的更多详细信息,请参阅 流模式

CALL gds.beta.pipeline.linkPrediction.predict.stream('myGraph', {
  modelName: 'lp-pipeline-model',
  topN: 5,
  threshold: 0.5
})
 YIELD node1, node2, probability
 RETURN gds.util.asNode(node1).name AS person1, gds.util.asNode(node2).name AS person2, probability
 ORDER BY probability DESC, person1

我们指定 threshold 以仅包含概率大于 50% 的预测,并指定 topN 以将输出限制为前 5 个关系。由于默认 samplingRate 为 1,我们使用 穷举搜索

表 8. 结果
person1 person2 probability

"Alice"

"Chris"

0.6207332784

“Mark”

"Chris"

0.5986795167

“Mark”

"Alice"

0.5662968371

"Alice"

"Karin"

0.5607462866

"Alice"

"Greg"

0.5579582123

我们可以看到模型认为上述节点对应该连接。其他节点对的概率较低,并从结果中过滤掉了。

在此示例中,我们将展示如何将预测结果写入您的投影图。我们将使用我们在 训练示例 中训练的模型 lp-pipeline-model

CALL gds.beta.pipeline.linkPrediction.predict.mutate('myGraph', {
  modelName: 'lp-pipeline-model',
  relationshipTypes: ['KNOWS'],
  mutateRelationshipType: 'KNOWS_EXHAUSTIVE_PREDICTED',
  topN: 5,
  threshold: 0.5
}) YIELD relationshipsWritten, samplingStats

我们指定 threshold 以仅包含概率大于 50% 的预测,并指定 topN 以将输出限制为前 5 个关系。由于默认 samplingRate 为 1,我们使用 穷举搜索。因为我们使用的是 UNDIRECTED 方向,所以我们将向内存图写入两倍的关系。

表 9. 结果
relationshipsWritten samplingStats

10

{linksConsidered=16, strategy="exhaustive"}

正如我们在 samplingStats 中看到的,我们使用了穷举搜索策略,并在预测期间检查了 16 个可能的链接。事实上,由于图中总共有 8 * (8 - 1) / 2 = 28 个可能的链接,而我们已经拥有了 12 个,这意味着我们检查了所有可能的新链接。虽然考虑了 16 个链接,但我们只对其中的前五个(因为 topN = 5)且高于阈值的链接执行了 mutate 操作,实际上只有一个链接通过了阈值(请参阅 Stream)。

如果我们的图非常大,可能会有很多可能的新链接。因此,运行预测可能需要很长时间。因此,使用仅查看所有可能新链接子集的搜索策略可能是一个更可行的选择。

为了避免在考虑所有可能的新链接时可能需要运行很长时间,我们可以使用 近似搜索策略

CALL gds.beta.pipeline.linkPrediction.predict.mutate('myGraph', {
  modelName: 'lp-pipeline-model',
  relationshipTypes: ['KNOWS'],
  mutateRelationshipType: 'KNOWS_APPROX_PREDICTED',
  sampleRate: 0.5,
  topK: 1,
  randomJoins: 2,
  maxIterations: 3,
  // necessary for deterministic results
  concurrency: 1,
  randomSeed: 42
})
 YIELD relationshipsWritten, samplingStats

为了使用近似策略,我们要确保将 sampleRate 明确设置为 < 1.0 的值。对于这个小示例,我们通过设置 maxIterations3randomJoins2 来限制搜索。此外,我们设置 topK = 1 以便为每个节点获得一个预测链接。因为我们使用的是 UNDIRECTED 方向,所以我们将向内存图写入两倍的关系。

表 10. 结果
relationshipsWritten samplingStats

16

{didConverge=true, linksConsidered=56, ranIterations=3, strategy="approximate"}

正如我们在 samplingStats 中看到的,我们使用了近似搜索策略,并在预测期间检查了 56 个可能的链接。虽然在这个小示例中,我们实际上考虑的链接比穷举情况多,但对于更大的图,通常情况并非如此。由于我们写入的关系是无向的,当我们为每个节点搜索最佳(topK = 1)预测时,报告的 relationshipsWritten 为 16。

使用上下文过滤器进行训练 中,我们在 fullGraph 上训练了另一个模型 lp-pipeline-model-filtered,该模型使用了 City 节点以及 LIVESBORN 关系作为上下文。

我们可以在预测中利用该模型,并可选择在预测中覆盖节点标签或关系类型过滤配置。在这种情况下,我们不这样做,而是继承 lp-pipeline-model-filtering 模型训练配置中的过滤配置。换句话说,我们预测 Person-KNOWS-Person 关系,并在节点属性步骤中额外使用 City 节点以及 LIVESBORN 关系。

CALL gds.beta.pipeline.linkPrediction.predict.stream('fullGraph', {
  modelName: 'lp-pipeline-model-filtered',
  topN: 5,
  threshold: 0.5
})
 YIELD node1, node2, probability
 RETURN gds.util.asNode(node1).name AS person1, gds.util.asNode(node2).name AS person2, probability
 ORDER BY probability DESC, person1

我们指定 threshold 以仅包含概率大于 50% 的预测,并指定 topN 以将输出限制为前 5 个关系。由于默认 samplingRate 为 1,我们使用 穷举搜索

表 11. 结果
person1 person2 probability

"Alice"

"Chris"

0.7174928596

“Mark”

"Chris"

0.6573294858

“Mark”

"Alice"

0.5617915136

"Alice"

"Karin"

0.54489345

"Alice"

"Greg"

0.5364068805

我们可以看到,我们的模型预测的前 5 个链接与未过滤模型 lp-pipeline-model 的结果相同。然而,由于在训练和预测中使用了额外的上下文信息,概率略有不同。