节点相似度 (Node Similarity)

本节介绍了 Neo4j 图数据科学库中的节点相似度算法。该算法基于 Jaccard 和重叠 (Overlap) 相似度指标。

术语表

有向

有向特征。该算法在有向图上定义良好。

有向

有向特征。该算法忽略图的方向。

有向

有向特征。该算法不能在有向图上运行。

无向

无向特征。该算法在无向图上定义良好。

无向

无向特征。该算法忽略图的无向性。

异构节点

异构节点完全支持。该算法有能力区分不同类型的节点。

异构节点

异构节点允许。该算法平等对待所有选定的节点,无论其标签如何。

异构关系

异构关系完全支持。该算法有能力区分不同类型的关系。

异构关系

异构关系允许。该算法平等对待所有选定的关系,无论其类型如何。

加权关系

加权特征。该算法支持将关系属性用作权重,通过 relationshipWeightProperty 配置参数指定。

加权关系

加权特征。该算法将每个关系视为同等重要,忽略任何关系权重值。

节点属性

节点属性特征。该算法使用节点属性。

简介

节点相似度算法基于节点所连接的其他节点来比较一组节点。如果两个节点共享许多相同的邻居,则认为它们是相似的。节点相似度基于 Jaccard 指标(也称为 Jaccard 相似度得分)、重叠系数(也称为 Szymkiewicz–Simpson 系数)以及余弦相似度得分来计算成对相似度。前两者最常用于无权集合,而余弦相似度通常用于加权输入。

给定两个集合 AB,Jaccard 相似度使用以下公式计算

jacard nodesim

重叠系数使用以下公式计算

overlap nodesim

加权情况的公式可在下方的加权示例中找到。

余弦相似度得分使用以下公式计算,其中当 A 和 B 为无权时,条目的权重默认为 1

cos

该算法的输入是一个包含两个不相交节点集的二分连通图。每条关系都始于第一个节点集中的一个节点,并终止于第二个节点集中的一个节点。

节点相似度算法会将每个具有出度的节点与其他此类节点进行比较。对于每个节点 n,我们收集该节点的出邻居 N(n),即所有满足存在从 nm 的关系的节点 m。对于每一对 n, m,算法会计算该对的相似度,结果等于所选相似度指标在 N(n)N(m) 上的计算结果。

节点相似度的时间复杂度为 O(n3),空间复杂度为 O(n2)。我们以 O(n2) 的时间和空间计算并存储邻居集,然后以 O(n3) 的时间计算成对相似度得分。

为了限制内存使用,您可以为每个节点指定输出结果数量的明确上限,即 'topK' 参数。它可以设置为除 0 以外的任何值。当然,您会在整体计算中损失精度,而运行时间不受影响——我们仍然必须在丢弃结果之前计算出它们。

该算法的输出是第一个节点集各对节点之间的新关系。相似度得分通过关系属性表示。

有关此算法的更多信息,请参阅

也可以对生成的相似度对中的源节点和/或目标节点进行过滤。为此,您可以参考过滤后的节点相似度算法。

运行此算法需要足够的可用内存。在运行此算法之前,我们建议您阅读内存估算

语法

本节涵盖了执行节点相似度算法各种模式时使用的语法。我们描述的是命名图变体的语法。要了解更多关于通用语法变体的信息,请参阅语法概述

节点相似度各模式的语法
在命名图上以流模式 (stream) 运行节点相似度。
CALL gds.nodeSimilarity.stream(
  graphName: String,
  configuration: Map
) YIELD
  node1: Integer,
  node2: Integer,
  similarity: Float
表 1. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

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

配置

Map

{}

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

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

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [1]

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

jobId

字符串

内部生成

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

logProgress

布尔值

true

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

similarityCutoff

浮点数

1e-42

结果中显示相似度得分的下限。值必须介于 0 和 1 之间。

degreeCutoff

整数

1

节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。

upperDegreeCutoff

整数

2147483647

节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。

topK

整数

10

每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。

bottomK

整数

10

每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。

topN

整数

0

计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。

bottomN

整数

0

计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

similarityMetric

字符串

JACCARD

用于计算相似度的指标。可以是 JACCARDOVERLAPCOSINE

useComponents

布尔值或字符串

false

如果启用,节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 false(默认):算法不使用组件,而是计算整个图的相似度。设置为 true:算法使用组件,并在计算相似度之前计算这些组件。设置为 String:使用存储在图中的预计算组件,String 是表示组件的节点属性键。

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

表 3. 结果
名称 类型 描述

node1

整数

第一个节点的节点 ID。

node2

整数

第二个节点的节点 ID。

similarity

浮点数

两个节点的相似度分数。

在命名图上以统计模式 (stats) 运行节点相似度。
CALL gds.nodeSimilarity.stats(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  postProcessingMillis: Integer,
  nodesCompared: Integer,
  similarityPairs: Integer,
  similarityDistribution: Map,
  configuration: Map
表 4. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

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

配置

Map

{}

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

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

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [2]

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

jobId

字符串

内部生成

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

logProgress

布尔值

true

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

similarityCutoff

浮点数

1e-42

结果中显示相似度得分的下限。值必须介于 0 和 1 之间。

degreeCutoff

整数

1

节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。

upperDegreeCutoff

整数

2147483647

节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。

topK

整数

10

每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。

bottomK

整数

10

每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。

topN

整数

0

计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。

bottomN

整数

0

计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

similarityMetric

字符串

JACCARD

用于计算相似度的指标。可以是 JACCARDOVERLAPCOSINE

useComponents

布尔值或字符串

false

如果启用,节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 false(默认):算法不使用组件,而是计算整个图的相似度。设置为 true:算法使用组件,并在计算相似度之前计算这些组件。设置为 String:使用存储在图中的预计算组件,String 是表示组件的节点属性键。

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

表 6. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

postProcessingMillis

整数

计算组件计数和分布统计信息的毫秒数。

nodesCompared

整数

计算过相似度的节点数量。

similarityPairs

整数

结果中的相似度对数量。

similarityDistribution

Map

包含计算出的相似度结果的最小值、最大值、平均值以及 p50, p75, p90, p95, p99 和 p999 百分位值的映射。

配置

Map

用于运行算法的配置。

在存储于目录中的图上以变更模式 (mutate) 运行节点相似度。
CALL gds.nodeSimilarity.mutate(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  mutateMillis: Integer,
  postProcessingMillis: Integer,
  relationshipsWritten: Integer,
  nodesCompared: Integer,
  similarityDistribution: Map,
  configuration: Map
表 7. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

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

配置

Map

{}

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

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

mutateRelationshipType

字符串

不适用

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

mutateProperty

字符串

不适用

GDS 图中写入相似度分数的属性。

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。

concurrency

整数

4

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

logProgress

布尔值

true

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

jobId

字符串

内部生成

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

similarityCutoff

浮点数

1e-42

结果中显示相似度得分的下限。值必须介于 0 和 1 之间。

degreeCutoff

整数

1

节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。

upperDegreeCutoff

整数

2147483647

节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。

topK

整数

10

每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。

bottomK

整数

10

每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。

topN

整数

0

计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。

bottomN

整数

0

计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

similarityMetric

字符串

JACCARD

用于计算相似度的指标。可以是 JACCARDOVERLAPCOSINE

useComponents

布尔值或字符串

false

如果启用,节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 false(默认):算法不使用组件,而是计算整个图的相似度。设置为 true:算法使用组件,并在计算相似度之前计算这些组件。设置为 String:使用存储在图中的预计算组件,String 是表示组件的节点属性键。

表 9. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

mutateMillis

整数

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

postProcessingMillis

整数

计算百分位数的毫秒数。

nodesCompared

整数

计算过相似度的节点数量。

relationshipsWritten

整数

创建的关系数量。

similarityDistribution

Map

包含计算出的相似度结果的最小值、最大值、平均值、标准差以及 p1, p5, p10, p25, p75, p90, p95, p99, p100 百分位值的映射。

配置

Map

用于运行算法的配置。

在存储于目录中的图上以写入模式 (write) 运行节点相似度。
CALL gds.nodeSimilarity.write(
  graphName: String,
  configuration: Map
)
YIELD
  preProcessingMillis: Integer,
  computeMillis: Integer,
  writeMillis: Integer,
  postProcessingMillis: Integer,
  nodesCompared: Integer,
  relationshipsWritten: Integer,
  similarityDistribution: Map,
  configuration: Map
表 10. 参数
名称 类型 默认 可选 描述

graphName

字符串

不适用

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

配置

Map

{}

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

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

nodeLabels

字符串列表

['*']

使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。

relationshipTypes

字符串列表

['*']

使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。

concurrency

整数

4 [3]

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

jobId

字符串

内部生成

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

logProgress

布尔值

true

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

writeConcurrency

整数

'concurrency' 的值

用于将结果写入 Neo4j 的并发线程数。

writeRelationshipType

字符串

不适用

用于将计算出的关系持久化到 Neo4j 数据库的关系类型。

writeProperty

字符串

不适用

Neo4j 数据库中写入相似度分数的属性。

similarityCutoff

浮点数

1e-42

结果中显示相似度得分的下限。值必须介于 0 和 1 之间。

degreeCutoff

整数

1

节点被纳入比较所需满足的节点度数的包含性下限。该值不能低于 1。

upperDegreeCutoff

整数

2147483647

节点被纳入比较所需满足的节点度数的包含性上限。该值不能低于 1。

topK

整数

10

每个节点的得分数量上限。返回 K 个最大的结果。此值不能低于 1。

bottomK

整数

10

每个节点的得分数量上限。返回 K 个最小的结果。此值不能低于 1。

topN

整数

0

计算出的得分的全局总数上限。返回 N 个最大的结果。此值不能为负数,值为 0 表示没有全局上限。

bottomN

整数

0

计算出的得分的全局总数上限。返回 N 个最小的结果。此值不能为负数,值为 0 表示没有全局上限。

relationshipWeightProperty

字符串

null

用作权重的关系属性名称。如果未指定,算法将作为无权重运行。

similarityMetric

字符串

JACCARD

用于计算相似度的指标。可以是 JACCARDOVERLAPCOSINE

useComponents

布尔值或字符串

false

如果启用,节点相似度将使用组件来提高计算性能,跳过不同组件中节点之间的比较。设置为 false(默认):算法不使用组件,而是计算整个图的相似度。设置为 true:算法使用组件,并在计算相似度之前计算这些组件。设置为 String:使用存储在图中的预计算组件,String 是表示组件的节点属性键。

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

表 12. 结果
名称 类型 描述

preProcessingMillis

整数

预处理数据的毫秒数。

computeMillis

整数

运行算法的毫秒数。

writeMillis

整数

将结果数据写回 Neo4j 的毫秒数。

postProcessingMillis

整数

计算百分位数的毫秒数。

nodesCompared

整数

计算过相似度的节点数量。

relationshipsWritten

整数

创建的关系数量。

similarityDistribution

Map

包含计算出的相似度结果的最小值、最大值、平均值、标准差以及 p1, p5, p10, p25, p75, p90, p95, p99, p100 百分位值的映射。

配置

Map

用于运行算法的配置。

示例

以下所有示例应在空数据库中运行。

这些示例将 Cypher 投影作为规范。原生投影将在未来版本中弃用。

在本节中,我们将展示在具体图上运行节点相似度算法的示例。目的是说明结果的样子,并为如何在实际环境中使用该算法提供指南。我们将使用一个小型知识图谱,其中包含少量以特定模式连接的节点。示例图如下所示

Visualization of the example graph
以下 Cypher 语句将在 Neo4j 数据库中创建示例图:
CREATE
  (alice:Person {name: 'Alice'}),
  (bob:Person {name: 'Bob'}),
  (carol:Person {name: 'Carol'}),
  (dave:Person {name: 'Dave'}),
  (eve:Person {name: 'Eve'}),
  (guitar:Instrument {name: 'Guitar'}),
  (synth:Instrument {name: 'Synthesizer'}),
  (bongos:Instrument {name: 'Bongos'}),
  (trumpet:Instrument {name: 'Trumpet'}),

  (alice)-[:LIKES]->(guitar),
  (alice)-[:LIKES]->(synth),
  (alice)-[:LIKES {strength: 0.5}]->(bongos),
  (bob)-[:LIKES]->(guitar),
  (bob)-[:LIKES]->(synth),
  (carol)-[:LIKES]->(bongos),
  (dave)-[:LIKES]->(guitar),
  (dave)-[:LIKES {strength: 1.5}]->(trumpet),
  (dave)-[:LIKES]->(bongos);

这个二分图有两个节点集:人 (Person) 节点和乐器 (Instrument) 节点。这两个节点集通过 LIKES 关系连接。每条关系都始于一个 Person 节点,并终止于一个 Instrument 节点。

在示例中,我们希望使用节点相似度算法根据人们喜欢的乐器来比较他们。

节点相似度算法仅计算度数至少为 1 的节点的相似度。在示例图中,Eve 节点将不会与其他 Person 节点进行比较。

以下语句将投影图并将其存储在图目录中。
MATCH (source:Person)
OPTIONAL MATCH (source)-[r:LIKES]->(target:Instrument)
RETURN gds.graph.project(
  'myGraph',
  source,
  target,
  { relationshipProperties: r { strength: coalesce(r.strength, 1.0) } }
)

在接下来的示例中,我们将演示如何在图上使用节点相似度算法。

内存估算

首先,我们将使用 estimate 过程估算运行算法的成本。这可以在任何执行模式下完成。在这个例子中我们将使用 write 模式。估算算法有助于了解在您的图上运行该算法将产生的内存影响。当您随后在其中一种执行模式下真正运行算法时,系统将执行一次估算。如果估算显示执行超出其内存限制的可能性非常高,则禁止执行。要阅读更多关于此的内容,请参阅 自动估算和执行阻塞

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

以下内容将估算运行算法所需的内存
CALL gds.nodeSimilarity.write.estimate('myGraph', {
  writeRelationshipType: 'SIMILAR',
  writeProperty: 'score'
})
YIELD nodeCount, relationshipCount, bytesMin, bytesMax, requiredMemory
表 13. 结果
nodeCount relationshipCount bytesMin bytesMax requiredMemory

9

9

2384

2600

"[2384 字节 ... 2600 字节]"

流 (Stream)

stream 执行模式下,算法返回每个关系的相似度分数。这允许我们直接检查结果或在 Cypher 中进行后处理,而不会产生任何副作用。

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

以下内容将运行算法并流式传输结果
CALL gds.nodeSimilarity.stream('myGraph')
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY similarity DESCENDING, Person1, Person2
表 14. 结果
Person1 Person2 similarity

"Alice"

"Bob"

0.6666666666666666

"Bob"

"Alice"

0.6666666666666666

"Alice"

"Dave"

0.5

"Dave"

"Alice"

0.5

"Alice"

"Carol"

0.3333333333333333

"Carol"

"Alice"

0.3333333333333333

"Carol"

"Dave"

0.3333333333333333

"Dave"

"Carol"

0.3333333333333333

"Bob"

"Dave"

0.25

"Dave"

"Bob"

0.25

我们对过程配置参数使用默认值。topK 设置为 10,topN 设置为 0。因此,结果集包含每个节点的前 10 个相似度得分。

如果我们想改为比较乐器之间的相似性,我们将使用 REVERSE 方向来投影 LIKES 关系类型。这将返回乐器对的相似性,而不会计算人与人之间的任何相似性。

统计 (Stats)

stats 执行模式下,算法返回一行包含算法结果摘要的数据。此执行模式没有任何副作用。通过检查 computeMillis 返回项来评估算法性能非常有用。在下面的示例中,我们将省略返回的时间。该过程的完整签名可以在语法部分找到。

有关 stats 模式的更多详细信息,请参阅 统计

以下内容将运行算法并以统计和测量值的形式返回结果
CALL gds.nodeSimilarity.stats('myGraph')
YIELD nodesCompared, similarityPairs
表 15. 结果
nodesCompared similarityPairs

4

10

变更 (Mutate)

mutate 执行模式扩展了 stats 模式并产生了一个重要的副作用:使用包含该关系相似度分数的新关系属性更新命名图。新属性的名称使用强制配置参数 mutateProperty 指定。结果是一个摘要行,类似于 stats,但包含一些额外的指标。mutate 模式在同时使用多个算法时特别有用。

有关 mutate 模式的更多详细信息,请参阅 变更

以下内容将运行算法,并将结果写回内存中图
CALL gds.nodeSimilarity.mutate('myGraph', {
    mutateRelationshipType: 'SIMILAR',
    mutateProperty: 'score'
})
YIELD nodesCompared, relationshipsWritten
表 16. 结果
nodesCompared relationshipsWritten

4

10

从结果中可以看出,创建的关系数量等于流式示例中的行数。

由变更产生的所有关系都是有向的,即使输入图是无向的。如果 a → ba 的 topK,且对称地 b → ab 的 topK(或者 a → bb → a 都是 topN),看起来似乎产生了一个无向关系。但实际上,它们只是两个独立生成的有向关系。

写入 (Write)

write 执行模式会为每一对节点在 Neo4j 数据库中创建一个关系,并将相似度得分作为该关系的属性。新关系的类型使用强制配置参数 writeRelationshipType 指定。新属性的名称使用强制配置参数 writeProperty 指定。结果是一行摘要,类似于 stats,但包含一些额外的指标。

有关 write 模式的更多详细信息,请参阅 写入

以下内容将运行算法并写回结果
CALL gds.nodeSimilarity.write('myGraph', {
    writeRelationshipType: 'SIMILAR',
    writeProperty: 'score'
})
YIELD nodesCompared, relationshipsWritten
表 17. 结果
nodesCompared relationshipsWritten

4

10

从结果中可以看出,创建的关系数量等于流式示例中的行数。

写入的关系始终是有向的,即使输入图是无向的。如果 a → ba 的 topK,且对称地 b → ab 的 topK(或者 a → bb → a 都是 topN),看起来似乎写入了一个无向关系。但实际上,它们只是两个独立写入的有向关系。

限制结果

可以对相似度结果应用四种限制。Top 将结果限制为最高相似度得分。Bottom 将结果限制为最低相似度得分。Top 和 bottom 限制都可以应用于整个结果集 ("N"),或应用于每个节点的结果 ("K")。

始终必须有一个 "K" 限制(bottomK 或 topK),它必须是一个正数。topK 和 bottomK 的默认值为 10。

表 18. 结果限制
总结果数 每个节点的结果数

最高分

topN

topK

最低分

bottomN

bottomK

topK 和 bottomK

TopK 和 bottomK 是每个节点计算得分数量的限制。对于 topK,返回每个节点的前 K 个最大相似度得分。对于 bottomK,返回每个节点的后 K 个最小相似度得分。TopK 和 bottomK 不能为 0,不能同时使用,默认值为 10。如果未指定,则使用 topK。

以下内容将运行该算法,并流式输出每个节点的前 1 个结果
CALL gds.nodeSimilarity.stream('myGraph', { topK: 1 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY Person1
表 19. 结果
Person1 Person2 similarity

"Alice"

"Bob"

0.666666666666667

"Bob"

"Alice"

0.666666666666667

"Carol"

"Alice"

0.333333333333333

"Dave"

"Alice"

0.5

以下内容将运行该算法,并流式输出每个节点的后 1 个结果
CALL gds.nodeSimilarity.stream('myGraph', { bottomK: 1 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY Person1
表 20. 结果
Person1 Person2 similarity

"Alice"

"Carol"

0.3333333333333333

"Bob"

"Dave"

0.25

"Carol"

"Alice"

0.3333333333333333

"Dave"

"Bob"

0.25

topN 和 bottomN

TopN 和 bottomN 限制所有节点上的相似度得分数量。这是对总结果集的限制,是对每个节点 topK 或 bottomK 限制的补充。对于 topN,返回前 N 个最大相似度得分。对于 bottomN,返回后 N 个最小相似度得分。值为 0 表示不施加全局限制,返回所有来自 topK 或 bottomK 的结果。

以下内容将运行该算法,并流式输出每个节点前 1 个结果中的最高 3 个结果
CALL gds.nodeSimilarity.stream('myGraph', { topK: 1, topN: 3 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY similarity DESC, Person1, Person2
表 21. 结果
Person1 Person2 similarity

"Alice"

"Bob"

0.6666666667

"Bob"

"Alice"

0.6666666667

"Dave"

"Alice"

0.5

度数截断和相似度截断

可以通过两个名为 degreeCutoffupperDegreeCutoff 的整数参数来调整节点相似度,从而根据度数约束忽略某些节点。如果设置,degreeCutoff 会对参与比较的节点度数设置下限,并跳过任何度数低于 degreeCutoff 的节点。如果设置,upperDegreeCutoff 会对节点度数设置上限,并跳过任何度数高于 upperDegreeCutoff 的节点。这两个参数也可以组合使用,以便只考虑度数落入特定区间的节点。

两个参数的最小值均为 1

以下内容将忽略少于 3 个 LIKES 关系的节点
CALL gds.nodeSimilarity.stream('myGraph', { degreeCutoff: 3 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY Person1
表 22. 结果
Person1 Person2 similarity

"Alice"

"Dave"

0.5

"Dave"

"Alice"

0.5

相似度截断是结果中出现相似度得分的下限。默认值非常小 (1E-42),用于排除相似度得分为 0 的结果。

将相似度截断设置为 0 可能会产生非常大的结果集,增加运行时间和内存消耗。

以下内容将忽略相似度得分低于 0.5 的节点对
CALL gds.nodeSimilarity.stream('myGraph', { similarityCutoff: 0.5 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY Person1
表 23. 结果
Person1 Person2 similarity

"Alice"

"Bob"

0.666666666666667

"Alice"

"Dave"

0.5

"Bob"

"Alice"

0.6666666666666666

"Dave"

"Alice"

0.5

加权相似度

关系属性可用于通过将其值作为衡量重要性的方式,来修改由特定关系引起的相似度。默认情况下,加权节点相似度根据以下公式使用加权 Jaccard 相似度

weighted jaccard

形式上,给定两个节点及其加权邻居列表 A'B',我们将列表扩展为 AB,对它们的邻居并集 A' ∪ B' 进行索引(对于任何非邻居设置权重 = 0),然后应用加权 Jaccard 相似度。

它还支持加权重叠 (Overlap) 相似度,根据以下公式

weighted overlap

此外,如简介所述,加权情况下也可以使用余弦相似度。

加权相似度指标仅针对大于或等于 0 的值定义。

以下查询将在相似度计算中尊重关系属性
CALL gds.nodeSimilarity.stream('myGraph', { relationshipWeightProperty: 'strength', similarityCutoff: 0.3 })
YIELD node1, node2, similarity
RETURN gds.util.asNode(node1).name AS Person1, gds.util.asNode(node2).name AS Person2, similarity
ORDER BY Person1
表 24. 结果
Person1 Person2 similarity

"Alice"

"Bob"

0.8

"Alice"

"Dave"

0.333333333333333

"Bob"

"Alice"

0.8

"Dave"

"Alice"

0.333333333333333

可以看出,与该算法的非加权版本相比,Alice 和 Dave 之间的相似度降低了(从 0.5 降至 0.33)。

Alice 喜欢 Guitar、Synthesizer 和 Bongos,强度分别为 (1, 1, 0.5)。Dave 喜欢 Guitar、Bongos 和 Trumpet,强度分别为 (1, 1, 1.5)。因此,取 Alice 和 Dave 的邻居,Alice 的强度列表为 A = (1, 1, 0.5, 0),Dave 的为 B = (1, 0, 1, 1.5),索引为 Guitar, Synthesizer, Bongos, Trumpet

因此,Alice 和 Dave 的加权(Jaccard)节点相似度为

weighted jaccard example

类似地,Alice 和 Bob 之间的相似度增加了(从 0.66 增加到 0.8),因为缺失的喜欢乐器对相似度得分的影响较低。