节点相似度

本节描述了 Neo4j Snowflake 图分析中的节点相似度算法。该算法基于 Jaccard 和 Overlap 相似度指标。

引言

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

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

jacard nodesim

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

overlap nodesim

余弦相似度分数使用以下公式计算,其中当 A、B 未加权时,条目隐式地被赋予 1 的权重

cos

此算法的输入是一个二分连通图,包含两个不相交的节点集。每个关系都从第一个节点集中的一个节点开始,并在第二个节点集中的一个节点结束。

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

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

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

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

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

语法

本节涵盖了执行节点相似度算法所使用的语法。

运行节点相似度。
CALL Neo4j_Graph_Analytics.graph.node_similarity(
  'CPU_X64_XS',                    (1)
  {
    ['defaultTablePrefix': '...',] (2)
    'project': {...},              (3)
    'compute': {...},              (4)
    'write':   {...}               (5)
  }
);
1 计算池选择器。
2 表引用的可选前缀。
3 项目配置。
4 计算配置。
5 写入配置。
表 1. 参数
名称 类型 默认值 可选 描述

computePoolSelector

字符串

不适用

运行节点相似度作业的计算池选择器。

configuration

映射

{}

用于图项目、算法计算和结果回写的配置。

配置映射包含以下三个条目。

有关下方项目配置的更多详细信息,请参阅 项目文档
表 2. 项目配置
名称 类型

nodeTables

节点表列表。

relationshipTables

关系类型到关系表的映射。

表 3. 计算配置
名称 类型 默认值 可选 描述

mutateProperty

字符串

'similarity'

将回写到 Snowflake 数据库的关系属性。

mutateRelationshipType

字符串

'SIMILAR_TO'

用于回写到 Snowflake 数据库的关系类型。

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

字符串

用作权重的关系属性名称。如果未指定,算法将运行非加权模式。

similarityMetric

字符串

JACCARD

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

useComponents

布尔值或字符串

false

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

有关下方写入配置的更多详细信息,请参阅 写入文档
表 4. 写入配置
名称 类型 默认值 可选 描述

sourceLabel

字符串

不适用

内存图中用于要回写的关系的起始节点的节点标签。

targetLabel

字符串

不适用

内存图中用于要回写的关系的结束节点的节点标签。

outputTable

字符串

不适用

将关系写入的 Snowflake 数据库中的表。

relationshipType

字符串

'SIMILAR_TO'

将回写到 Snowflake 数据库的关系类型。

relationshipProperty

字符串

'similarity'

将回写到 Snowflake 数据库的关系属性。

示例

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

Visualization of the example graph
以下 SQL 语句将在 Snowflake 数据库中创建示例图表
CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.PERSONS (NODEID STRING);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.PERSONS VALUES
  ('Alice'),
  ('Bob'),
  ('Carol'),
  ('Dave'),
  ('Eve');

CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.INSTRUMENTS (NODEID STRING);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.INSTRUMENTS VALUES
  ('Guitar'),
  ('Synthesizer'),
  ('Bongos'),
  ('Trumpet');

CREATE OR REPLACE TABLE EXAMPLE_DB.DATA_SCHEMA.LIKES (SOURCENODEID STRING, TARGETNODEID STRING, WEIGHT FLOAT);
INSERT INTO EXAMPLE_DB.DATA_SCHEMA.LIKES VALUES
  ('Alice', 'Guitar',      NULL),
  ('Alice', 'Synthesizer', NULL),
  ('Alice', 'Bongos',      0.5),
  ('Bob',   'Guitar',      NULL),
  ('Bob',   'Synthesizer', NULL),
  ('Carol', 'Bongos',      NULL),
  ('Dave',  'Guitar',      NULL),
  ('Dave',  'Trumpet',     1.5),
  ('Dave',  'Bongos',      NULL);

这个二分图有两个节点集:人物节点 (Person nodes) 和乐器节点 (Instrument nodes)。这两个节点集通过 LIKES 关系连接。每个关系都从一个人物节点开始,并在一个乐器节点结束。

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

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

在以下示例中,我们将演示在此图上使用节点相似度算法。

运行作业

运行节点相似度作业涉及三个步骤:项目、计算和写入。

要运行此查询,需要为应用程序、您的消费者角色和您的环境设置必要的授权。有关更多信息,请参阅入门页面。

我们还假设应用程序名称是默认的 Neo4j_Graph_Analytics。如果您在安装过程中选择了不同的应用程序名称,请将其替换为该名称。

以下将运行一个节点相似度作业
CALL Neo4j_Graph_Analytics.graph.node_similarity('CPU_X64_XS', {
    'defaultTablePrefix': 'EXAMPLE_DB.DATA_SCHEMA',
    'project': {
        'nodeTables': ['PERSONS', 'INSTRUMENTS'],
        'relationshipTables': {
          'sourceTable': 'PERSONS',
          'targetTable': 'INSTRUMENTS'
        }
    },
    'compute': {
        'mutateProperty': 'score',
        'mutateRelationshipType': 'SIMILAR'
    },
    'write': [{
        'outputTable': 'PERSONS_SIMILARITY',
        'sourceLabel': 'PERSONS',
        'targetLabel': 'PERSONS',
        'relationshipType': 'SIMILAR',
        'relationshipProperty': 'score'
    }]
});
表 5. 结果
作业 ID 作业开始时间 作业结束时间 作业结果

job_547003e336b44e83b9716fda49069336

2025-04-30 06:32:57.635000

2025-04-30 06:33:05.199000

 {
  "node_similarity_1": {
    "computeMillis": 22,
    "configuration": {
      "bottomK": 10,
      "bottomN": 0,
      "concurrency": 2,
      "degreeCutoff": 1,
      "jobId":
"38eaf0c7-301f-4b56-8f4d-1372d2642ee2",
      "logProgress": true,
      "mutateProperty": "score",
      "mutateRelationshipType": "SIMILAR",
      "nodeLabels": [
        "*"
      ],
      "relationshipTypes": [
        "*"
      ],
      "similarityCutoff":
1.000000000000000e-42,
      "similarityMetric": "JACCARD",
      "sudo": false,
      "topK": 10,
      "topN": 0,
      "upperDegreeCutoff": 2147483647,
      "useComponents": false
    },
    "mutateMillis": 186,
    "nodesCompared": 4,
    "postProcessingMillis": 0,
    "preProcessingMillis": 7,
    "relationshipsWritten": 10,
    "similarityDistribution": {
      "max": 0.6666679382324218,
      "mean": 0.41666641235351565,
      "min": 0.25,
      "p1": 0.25,
      "p10": 0.25,
      "p100": 0.6666660308837891,
      "p25": 0.3333320617675781,
      "p5": 0.25,
      "p50": 0.3333320617675781,
      "p75": 0.5000019073486328,
      "p90": 0.6666660308837891,
      "p95": 0.6666660308837891,
      "p99": 0.6666660308837891,
      "stdDev": 0.14907148283512542
    }
  },
  "project_1": {
    "graphName": "snowgraph",
    "nodeCount": 9,
    "nodeMillis": 734,
    "relationshipCount": 9,
    "relationshipMillis": 525,
    "totalMillis": 1259
  },
  "write_relationship_type_1": {
    "exportMillis": 2133,
    "outputTable":
"EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY",
    "relationshipProperty": "score",
    "relationshipType": "SIMILAR",
    "relationshipsExported": 10
  }
}

返回的结果包含有关作业执行和结果分布的信息。此外,为比较的节点对计算的每个相似度分数都已回写到 Snowflake 数据库。我们可以这样查询它:

SELECT * FROM EXAMPLE_DB.DATA_SCHEMA.PERSONS_SIMILARITY ORDER BY SCORE DESC;

这显示了数据库中存储的计算结果

表 6. 结果
源节点 ID 目标节点 ID 分数

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 关系类型。这将返回乐器对的相似度,而不计算人物之间的任何相似度。

© . All rights reserved.