应用训练好的模型进行预测
此功能处于测试版(beta)级别。有关功能级别的更多信息,请参阅 API 级别。
然后,可以将训练好的模型应用于图目录中的图,以创建包含预测链接的新关系类型。这些关系还具有一个属性,用于存储链接的预测概率,这可以视为模型预测置信度的相对度量。
由于模型是根据使用特征管道创建的特征进行训练的,因此相同的特征管道存储在模型中,并在预测时执行。与训练期间一样,特征管道中节点属性步骤创建的中间节点属性是瞬态的,在执行后不可见。
使用模型进行预测时,输入图中的关系会根据配置进行分离。默认情况下,配置将与用于训练管道的配置相同。训练期间标记为上下文关系的关系再次用于在节点属性步骤中计算特征。目标关系类型用于防止预测已经存在的关系。此配置可以被覆盖,以指定不同的上下文,或不同的关系集合以从预测中排除。
预测图必须包含管道所需的属性,并且所使用的数组属性必须与训练图中的具有相同的维度。如果预测图和训练图是不同的,那么它们具有相似的来源和语义也很有益,这样模型才能很好地泛化。
搜索策略
语法
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
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定和/或图过滤的配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
modelName |
字符串 |
|
否 |
模型目录中链接预测模型的名称。 |
sourceNodeLabel |
字符串 |
|
是 |
预测链接应开始的节点标签名称。 |
targetNodeLabel |
字符串 |
|
是 |
预测链接应结束的节点标签名称。 |
relationshipTypes |
字符串列表 |
|
是 |
现有关系的名称。默认情况下,我们使用训练中的 |
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
字符串 |
|
是 |
可以提供一个 ID,以便更轻松地跟踪算法的进度。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
mutateRelationshipType |
字符串 |
|
否 |
用于写入投影图的新关系的关系类型。 |
mutateProperty |
字符串 |
|
是 |
结果写入 GDS 图中的关系属性。 |
sampleRate |
浮点数 |
|
否 |
采样率,用于确定每个节点考虑多少链接。如果设置为 1,则考虑所有可能的链接,即穷举搜索。否则,将使用近似搜索策略。值必须在 0(不含)到 1(含)之间。 |
topN [2] |
整数 |
|
否 |
限制输出的预测关系数量。 |
threshold [2] |
浮点数 |
|
是 |
输出关系上的最小预测概率。 |
topK [3] |
整数 |
|
是 |
限制每个节点输出的预测关系数量。此值不能低于 1。 |
deltaThreshold [3] |
浮点数 |
|
是 |
作为百分比的值,用于确定何时提前停止。如果更新次数少于配置值,算法将停止。值必须在 0(不含)到 1(含)之间。 |
整数 |
|
是 |
在此迭代次数后停止算法的硬限制。 |
|
randomJoins [3] |
整数 |
|
是 |
每次迭代之间,基于随机选择尝试连接新节点邻居的次数。 |
字符串 |
|
是 |
用于为每个节点采样前 |
|
randomSeed [3] |
整数 |
|
是 |
控制算法随机性的种子值。请注意,设置此参数时, |
名称 | 类型 | 描述 |
---|---|---|
preProcessingMillis |
整数 |
图预处理的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
postProcessingMillis |
整数 |
计算全局指标的毫秒数。 |
mutateMillis |
整数 |
向投影图添加属性的毫秒数。 |
relationshipsWritten |
整数 |
创建的关系数量。 |
probabilityDistribution |
Map |
预测概率分布的描述。 |
samplingStats |
Map |
预测如何采样的描述。 |
配置 |
Map |
用于运行算法的配置。 |
CALL gds.beta.pipeline.linkPrediction.predict.stream(
graphName: String,
configuration: Map
)
YIELD
node1: Integer,
node2: Integer,
probability: Float
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定和/或图过滤的配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
modelName |
字符串 |
|
否 |
模型目录中 LinkPrediction 模型的名称。 |
字符串列表 |
|
是 |
使用给定的节点标签过滤命名图。将包含具有任何给定标签的节点。 |
|
字符串列表 |
|
是 |
使用给定的关系类型过滤命名图。将包含具有任何给定类型的关系。 |
|
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
字符串 |
|
是 |
可以提供一个 ID,以便更轻松地跟踪算法的进度。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
sampleRate |
浮点数 |
|
否 |
采样率,用于确定每个节点考虑多少链接。如果设置为 1,则考虑所有可能的链接,即穷举搜索。否则,将使用近似搜索策略。值必须在 0(不含)到 1(含)之间。 |
topN [5] |
整数 |
|
否 |
限制输出的预测关系数量。 |
threshold [5] |
浮点数 |
|
是 |
输出关系上的最小预测概率。 |
topK [6] |
整数 |
|
是 |
限制每个节点输出的预测关系数量。此值不能低于 1。 |
deltaThreshold [6] |
浮点数 |
|
是 |
作为百分比的值,用于确定何时提前停止。如果更新次数少于配置值,算法将停止。值必须在 0(不含)到 1(含)之间。 |
整数 |
|
是 |
在此迭代次数后停止算法的硬限制。 |
|
randomJoins [6] |
整数 |
|
是 |
每次迭代之间,基于随机选择尝试连接新节点邻居的次数。 |
字符串 |
|
是 |
用于为每个节点采样前 |
|
randomSeed [6] |
整数 |
|
是 |
控制算法随机性的种子值。请注意,设置此参数时, |
名称 | 类型 | 描述 |
---|---|---|
node1 |
整数 |
第一个节点的节点 ID。 |
node2 |
整数 |
第二个节点的节点 ID。 |
probability |
浮点数 |
节点之间链接的预测概率。 |
示例
在此示例中,我们将展示如何使用训练好的模型预测投影图中的新关系。为此,我们必须首先在模型目录中注册一个已训练好的模型。我们将使用在训练示例中训练的模型,该模型名为lp-pipeline-model
。该算法排除了对图中现有关系和自环的预测。
选择在预测新链接时考虑哪些节点对有两种不同的策略:穷举搜索和近似搜索。前者考虑所有可能的新链接,而后者将使用一种随机策略,只考虑其中的一个子集,以便运行更快。我们将在下面的变异示例中分别解释每种策略并提供示例。
写入和变异过程产生的关系是无向的,就像输入一样。然而,不会产生并行关系。因此,例如,如果在进行近似搜索时, |
内存估算
首先,我们将使用 estimate
过程来估算运行算法的成本。这可以在任何执行模式下完成。在此示例中,我们将使用 stream
模式。估算算法有助于了解在图上运行算法将产生的内存影响。当您随后实际以某种执行模式运行算法时,系统将执行估算。如果估算显示执行极有可能超出其内存限制,则将禁止执行。要了解更多信息,请参阅 自动估算和执行阻塞。
有关 estimate
的更多详细信息,请参阅 内存估算。
CALL gds.beta.pipeline.linkPrediction.predict.stream.estimate('myGraph', {
modelName: 'lp-pipeline-model',
topN: 5,
threshold: 0.5
})
YIELD requiredMemory
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
,我们使用穷举搜索。
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
方向,所以我们将向内存图写入两倍数量的关系。
relationshipsWritten | samplingStats |
---|---|
10 |
{linksConsidered=16, strategy="exhaustive"} |
正如我们在 samplingStats
中看到的,我们使用了穷举搜索策略,并在预测期间检查了 16 个可能的链接。确实,由于图中总共有 8 * (8 - 1) / 2 = 28
个可能的链接,而我们已经有 12 个,这意味着我们检查了所有可能的新链接。尽管考虑了 16 个链接,但我们只变异了高于阈值的最佳五个(因为 topN = 5
),实际上只有一个链接通过了阈值(参见 流)。
如果我们的图非常大,可能会有很多可能的新链接。因此,运行预测可能需要很长时间。因此,使用只查看所有可能新链接子集的搜索策略可能是一个更可行的选择。
近似搜索
为了避免考虑所有可能的新链接可能导致运行时间过长,我们可以使用近似搜索策略。
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
的值。对于这个小例子,我们通过将 maxIterations
设置为 3
和 randomJoins
设置为 2
来限制搜索。此外,我们将 topK = 1
以获得每个节点的一个预测链接。因为我们使用 UNDIRECTED
方向,所以我们将向内存图写入两倍数量的关系。
relationshipsWritten | samplingStats |
---|---|
16 |
{didConverge=true, linksConsidered=56, ranIterations=3, strategy="approximate"} |
正如我们在 samplingStats
中看到的,我们使用了近似搜索策略,并在预测期间检查了 56 个可能的链接。尽管在这个小例子中我们实际考虑的链接比穷举搜索的情况更多,但对于大型图来说通常并非如此。由于我们写入的关系是无向的,当我们为每个节点搜索最佳(topK = 1
)预测时,报告的 relationshipsWritten
为 16。
带上下文过滤的预测
在带上下文过滤的训练中,我们在 fullGraph
上训练了另一个模型 lp-pipeline-model-filtered
,该模型使用上下文 City
节点和上下文 LIVES
以及 BORN
关系。
我们可以在预测中利用此模型,可选地覆盖预测中的节点标签或关系类型过滤器配置。在此情况下,我们不进行覆盖,而是从 lp-pipeline-model-filtering
模型的训练配置中继承过滤配置。换句话说,我们预测 Person-KNOWS-Person 关系,并额外使用 City
节点以及 LIVES
和 BORN
关系进行节点属性步骤。
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
,我们使用穷举搜索。
person1 | person2 | probability |
---|---|---|
"Alice" |
"Chris" |
0.7174928596 |
"Mark" |
"Chris" |
0.6573294858 |
"Mark" |
"Alice" |
0.5617915136 |
"Alice" |
"Karin" |
0.54489345 |
"Alice" |
"Greg" |
0.5364068805 |
我们可以看到我们的模型预测了与未过滤模型 lp-pipeline-model
相同的 top 5 链接。然而,由于训练和预测中使用了额外的上下文信息,概率略有不同。