Leiden
术语表
- 有向
-
有向特征。该算法在有向图上定义良好。
- 有向
-
有向特征。该算法忽略图的方向。
- 有向
-
有向特征。该算法不能在有向图上运行。
- 无向
-
无向特征。该算法在无向图上定义良好。
- 无向
-
无向特征。该算法忽略图的无向性。
- 异构节点
-
异构节点完全支持。该算法有能力区分不同类型的节点。
- 异构节点
-
异构节点允许。该算法平等对待所有选定的节点,无论其标签如何。
- 异构关系
-
异构关系完全支持。该算法有能力区分不同类型的关系。
- 异构关系
-
异构关系允许。该算法平等对待所有选定的关系,无论其类型如何。
- 加权关系
-
加权特征。该算法支持将关系属性用作权重,通过 relationshipWeightProperty 配置参数指定。
- 加权关系
-
加权特征。该算法将每个关系视为同等重要,忽略任何关系权重值。
- 节点属性
-
节点属性特征。该算法使用节点属性。
简介
Leiden 算法是一种用于检测大型网络中社区的算法。该算法将节点划分为不相交的社区,以最大化每个社区的模块度(Modularity)得分。模块度量化了节点分配到社区的质量,即社区内节点的连接密度,与随机网络中预期连接密度的对比。
Leiden 算法是一种层次聚类算法,它通过贪婪地优化模块度,递归地将社区合并为单个节点,并在压缩后的图中重复此过程。它改进了 Louvain 算法,以解决其部分缺陷,即 Louvain 发现的某些社区连接不够紧密的问题。这是通过定期随机地将社区分解为更小的紧密连接社区来实现的。
有关此算法的更多信息,请参阅
|
运行此算法需要足够的可用内存。在运行之前,建议您阅读 内存估计 (Memory Estimation)。 |
语法
本节介绍在每种执行模式下运行 Leiden 算法所使用的语法。我们这里描述的是命名图(Named Graph)的语法变体。要了解有关通用语法变体的更多信息,请参阅 语法概述。
CALL gds.leiden.stream(
graphName: String,
configuration: Map
)
YIELD
nodeId: Integer,
communityId: Integer,
intermediateCommunityIds: List of Integer
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定配置和/或图过滤配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
字符串列表 |
|
是 |
使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。 |
|
字符串列表 |
|
是 |
使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。 |
|
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
字符串 |
|
是 |
可以提供一个 ID 以更轻松地跟踪算法的进度。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
|
maxLevels |
整数 |
|
是 |
图进行聚类并随后压缩的最大层级数。 |
gamma |
浮点数 |
|
是 |
计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[2] |
theta |
浮点数 |
|
是 |
控制将社区分解为较小社区时的随机性。 |
浮点数 |
|
是 |
迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。 |
|
includeIntermediateCommunities |
布尔值 |
|
是 |
指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。 |
字符串 |
|
是 |
用于设置节点的初始社区。属性值必须为非负数。 |
|
consecutiveIds |
布尔值 |
|
是 |
用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。 |
randomSeed |
整数 |
|
是 |
控制算法随机性的种子值。 |
minCommunitySize |
整数 |
|
是 |
仅返回属于大于或等于给定值的社区的节点。 |
2. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。 |
||||
| 名称 | 类型 | 描述 |
|---|---|---|
nodeId |
整数 |
节点 ID。 |
communityId |
整数 |
最终层级的社区 ID。 |
intermediateCommunityIds |
整数列表 |
每一层级的社区 ID。如果 |
CALL gds.leiden.stats(
graphName: String,
configuration: Map
)
YIELD
preProcessingMillis: Integer,
computeMillis: Integer,
postProcessingMillis: Integer,
communityCount: Integer,
ranLevels: Integer,
modularity: Float,
modularities: List of Float,
nodeCount: Integer,
didConverge: Boolean,
communityDistribution: Map,
configuration: Map
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定配置和/或图过滤配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
字符串列表 |
|
是 |
使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。 |
|
字符串列表 |
|
是 |
使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。 |
|
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
字符串 |
|
是 |
可以提供一个 ID 以更轻松地跟踪算法的进度。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
|
maxLevels |
整数 |
|
是 |
图进行聚类并随后压缩的最大层级数。 |
gamma |
浮点数 |
|
是 |
计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[4] |
theta |
浮点数 |
|
是 |
控制将社区分解为较小社区时的随机性。 |
浮点数 |
|
是 |
迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。 |
|
includeIntermediateCommunities |
布尔值 |
|
是 |
指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。 |
字符串 |
|
是 |
用于设置节点的初始社区。属性值必须为非负数。 |
|
consecutiveIds |
布尔值 |
|
是 |
用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。 |
randomSeed |
整数 |
|
是 |
控制算法随机性的种子值。 |
4. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。 |
||||
| 名称 | 类型 | 描述 |
|---|---|---|
preProcessingMillis |
整数 |
预处理数据的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
postProcessingMillis |
整数 |
计算百分位数和社区数量所需的毫秒数。 |
communityCount |
整数 |
发现的社区数量。 |
ranLevels |
整数 |
算法实际运行的层级数。 |
modularity |
浮点数 |
最终的模块度得分。 |
modularities |
浮点数列表 |
每一层级的模块度得分。 |
nodeCount |
整数 |
图中的节点数。 |
didConverge |
布尔值 |
指示算法是否收敛。 |
communityDistribution |
Map |
包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。 |
配置 |
Map |
用于运行算法的配置。 |
CALL gds.leiden.mutate(
graphName: String,
configuration: Map
)
YIELD
preProcessingMillis: Integer,
computeMillis: Integer,
mutateMillis: Integer,
postProcessingMillis: Integer,
communityCount: Integer,
ranLevels: Integer,
modularity: Float,
modularities: List of Float,
nodeCount: Integer,
didConverge: Boolean,
nodePropertiesWritten: Integer,
communityDistribution: Map,
configuration: Map
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定配置和/或图过滤配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
mutateProperty |
字符串 |
|
否 |
GDS 图中写入社区 ID 的节点属性。 |
字符串列表 |
|
是 |
使用给定的节点标签过滤命名图。 |
|
字符串列表 |
|
是 |
使用给定的关系类型过滤命名图。 |
|
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
字符串 |
|
是 |
可以提供一个 ID 以更轻松地跟踪算法的进度。 |
|
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
|
maxLevels |
整数 |
|
是 |
图进行聚类并随后压缩的最大层级数。 |
gamma |
浮点数 |
|
是 |
计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[5] |
theta |
浮点数 |
|
是 |
控制将社区分解为较小社区时的随机性。 |
浮点数 |
|
是 |
迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。 |
|
includeIntermediateCommunities |
布尔值 |
|
是 |
指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。 |
字符串 |
|
是 |
用于设置节点的初始社区。属性值必须为非负数。 |
|
consecutiveIds |
布尔值 |
|
是 |
用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。 |
randomSeed |
整数 |
|
是 |
控制算法随机性的种子值。 |
5. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。 |
||||
| 名称 | 类型 | 描述 |
|---|---|---|
preProcessingMillis |
整数 |
预处理数据的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
mutateMillis |
整数 |
向投影图添加属性的毫秒数。 |
postProcessingMillis |
整数 |
计算百分位数和社区数量所需的毫秒数。 |
communityCount |
整数 |
发现的社区数量。 |
ranLevels |
整数 |
算法实际运行的层级数。 |
modularity |
浮点数 |
最终的模块度得分。 |
modularities |
浮点数列表 |
每一层级的模块度得分。 |
nodeCount |
整数 |
图中的节点数。 |
didConverge |
布尔值 |
指示算法是否收敛。 |
nodePropertiesWritten |
整数 |
添加到投影图中的属性数量。 |
communityDistribution |
Map |
包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。 |
配置 |
Map |
用于运行算法的配置。 |
CALL gds.leiden.write(
graphName: String,
configuration: Map
)
YIELD
preProcessingMillis: Integer,
computeMillis: Integer,
writeMillis: Integer,
postProcessingMillis: Integer,
communityCount: Integer,
ranLevels: Integer,
modularity: Float,
modularities: List of Float,
nodeCount: Integer,
didConverge: Boolean,
nodePropertiesWritten: Integer,
communityDistribution: Map,
configuration: Map
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
配置 |
Map |
|
是 |
算法特定配置和/或图过滤配置。 |
| 名称 | 类型 | 默认 | 可选 | 描述 |
|---|---|---|---|---|
字符串列表 |
|
是 |
使用给定的节点标签过滤命名图。具有任何给定标签的节点都将被包含。 |
|
字符串列表 |
|
是 |
使用给定的关系类型过滤命名图。具有任何给定类型的关系都将被包含。 |
|
整数 |
|
是 |
用于运行算法的并发线程数。 |
|
字符串 |
|
是 |
可以提供一个 ID 以更轻松地跟踪算法的进度。 |
|
布尔值 |
|
是 |
如果禁用,进度百分比将不会被记录。 |
|
整数 |
|
是 |
用于将结果写入 Neo4j 的并发线程数。 |
|
字符串 |
|
否 |
Neo4j 数据库中写入社区 ID 的节点属性。 |
|
字符串 |
|
是 |
用作权重的关系属性名称。如果未指定,算法将作为无权重运行。 |
|
maxLevels |
整数 |
|
是 |
图进行聚类并随后压缩的最大层级数。 |
gamma |
浮点数 |
|
是 |
计算模块度时使用的分辨率参数。在内部,该值对于无权图会除以关系总数,否则除以所有关系权重之和。[7] |
theta |
浮点数 |
|
是 |
控制将社区分解为较小社区时的随机性。 |
浮点数 |
|
是 |
迭代之间模块度的最小变化值。如果模块度变化小于该容差值,则结果被视为稳定,算法终止。 |
|
includeIntermediateCommunities |
布尔值 |
|
是 |
指示是否写入中间社区。如果设置为 false,则仅保留最终的社区。 |
字符串 |
|
是 |
用于设置节点的初始社区。属性值必须为非负数。 |
|
consecutiveIds |
布尔值 |
|
是 |
用于决定组件标识符是否映射到连续 ID 空间的标志(需要额外的内存)。 |
randomSeed |
整数 |
|
是 |
控制算法随机性的种子值。 |
minCommunitySize |
整数 |
|
是 |
仅将大小大于或等于给定值的社区的社区 ID 写入 Neo4j。 |
6. 在 GDS Session 中,默认值为可用处理器的数量。 7. 更高的分辨率会导致更多的社区,而较低的分辨率会导致更少的社区。 |
||||
| 名称 | 类型 | 描述 |
|---|---|---|
preProcessingMillis |
整数 |
预处理数据的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
writeMillis |
整数 |
向投影图添加属性的毫秒数。 |
postProcessingMillis |
整数 |
计算百分位数和社区数量所需的毫秒数。 |
communityCount |
整数 |
发现的社区数量。 |
ranLevels |
整数 |
算法实际运行的层级数。 |
modularity |
浮点数 |
最终的模块度得分。 |
modularities |
浮点数列表 |
每一层级的模块度得分。 |
nodeCount |
整数 |
图中的节点数。 |
didConverge |
布尔值 |
指示算法是否收敛。 |
nodePropertiesWritten |
整数 |
添加到 Neo4j 数据库的属性数量。 |
communityDistribution |
Map |
包含最后一级社区大小的最小值、最大值、平均值以及 p1、p5、p10、p25、p50、p75、p90、p95、p99 和 p999 百分位数的映射。 |
配置 |
Map |
用于运行算法的配置。 |
示例
|
以下所有示例应在空数据库中运行。 这些示例将 Cypher 投影作为规范。原生投影将在未来版本中弃用。 |
在本节中,我们将展示在具体图上运行 Leiden 社区检测算法的示例。目的是说明结果的样子,并提供在实际环境中使用该算法的指南。我们将使用一个小的社交网络图来完成此操作,该图包含以特定模式连接的少数节点。示例图如下所示:
CREATE
(nAlice:User {name: 'Alice', seed: 42}),
(nBridget:User {name: 'Bridget', seed: 42}),
(nCharles:User {name: 'Charles', seed: 42}),
(nDoug:User {name: 'Doug'}),
(nMark:User {name: 'Mark'}),
(nMichael:User {name: 'Michael'}),
(nAlice)-[:LINK {weight: 1}]->(nBridget),
(nAlice)-[:LINK {weight: 1}]->(nCharles),
(nCharles)-[:LINK {weight: 1}]->(nBridget),
(nAlice)-[:LINK {weight: 5}]->(nDoug),
(nMark)-[:LINK {weight: 1}]->(nDoug),
(nMark)-[:LINK {weight: 1}]->(nMichael),
(nMichael)-[:LINK {weight: 1}]->(nMark);
该图有两个由 用户 (Users) 组成的簇,它们连接紧密。这些簇通过一条边连接。关系属性 weight 决定了节点间各自关系的强度。
我们现在可以投射该图并将其存储在图目录中。我们将 LINK 关系加载并将方向设置为 UNDIRECTED,因为这与 Leiden 算法配合使用效果最佳。
MATCH (source:User)-[r:LINK]->(target:User)
RETURN gds.graph.project(
'myGraph',
source,
target,
{
sourceNodeProperties: source { .seed },
targetNodeProperties: target { .seed },
relationshipProperties: r { .weight }
},
{ undirectedRelationshipTypes: ['*'] }
)
在接下来的示例中,我们将演示在此图上使用 Leiden 算法。
内存估算
首先,我们将使用 estimate 过程估算运行算法的成本。这可以在任何执行模式下完成。在这个例子中我们将使用 write 模式。估算算法有助于了解在您的图上运行该算法将产生的内存影响。当您随后在其中一种执行模式下真正运行算法时,系统将执行一次估算。如果估算显示执行超出其内存限制的可能性非常高,则禁止执行。要阅读更多关于此的内容,请参阅 自动估算和执行阻塞。
有关 estimate 的更多详细信息,请参阅 内存估算。
CALL gds.leiden.write.estimate('myGraph', {writeProperty: 'communityId', randomSeed: 19})
YIELD nodeCount, relationshipCount, requiredMemory
| nodeCount | relationshipCount | requiredMemory |
|---|---|---|
6 |
14 |
"[551 KiB ... 551 KiB]" |
流 (Stream)
在 stream 执行模式下,算法会返回每个节点的社区 ID。这使我们能够直接检查结果,或者在 Cypher 中对其进行后处理,而不会产生任何副作用。
有关 stream 模式的更多详细信息,请参阅 流式读取。
CALL gds.leiden.stream('myGraph', { randomSeed: 19 })
YIELD nodeId, communityId
RETURN gds.util.asNode(nodeId).name AS name, communityId
ORDER BY name ASC
| 名称 (name) | communityId |
|---|---|
"Alice" |
1 |
“Bridget” |
1 |
“Charles” |
1 |
“Doug” |
5 |
“Mark” |
5 |
“Michael” |
5 |
我们对过程配置参数使用默认值。maxLevels 设置为 10,gamma 和 theta 参数分别设置为 1.0 和 0.01。
统计 (Stats)
在 stats 执行模式下,算法返回一行包含算法结果摘要的数据。此执行模式没有任何副作用。它对于通过检查 computeMillis 返回项来评估算法性能很有用。在下面的示例中,我们将省略返回的时间信息。该过程的完整签名可以在 语法部分 中找到。
有关 stats 模式的更多详细信息,请参阅 统计。
CALL gds.leiden.stats('myGraph', { randomSeed: 19 })
YIELD communityCount
| communityCount |
|---|
2 |
变更 (Mutate)
mutate 执行模式扩展了 stats 模式,并带有一个重要的副作用:用包含该节点社区 ID 的新节点属性更新命名图。新属性的名称通过必需的配置参数 mutateProperty 指定。结果是一个摘要行,类似于 stats,但带有额外的指标。mutate 模式在多个算法协同使用时特别有用。
有关 mutate 模式的更多详细信息,请参阅 变更。
myGraph 中:CALL gds.leiden.mutate('myGraph', { mutateProperty: 'communityId', randomSeed: 19 })
YIELD communityCount
| communityCount |
|---|
2 |
在 mutate 模式下,过程仅返回一行结果。该结果包含元信息,如识别出的社区数量。结果被写入 GDS 内存图,而不是 Neo4j 数据库。
写入 (Write)
write 执行模式扩展了 stats 模式,并带有一个重要的副作用:将每个节点的社区 ID 作为属性写入 Neo4j 数据库。新属性的名称通过必需的配置参数 writeProperty 指定。结果是一个摘要行,类似于 stats,但带有额外的指标。write 模式允许直接将结果持久化到数据库中。
有关 write 模式的更多详细信息,请参阅 写入。
CALL gds.leiden.write('myGraph', { writeProperty: 'communityId', randomSeed: 19 })
YIELD communityCount, nodePropertiesWritten
| communityCount | nodePropertiesWritten |
|---|---|
2 |
6 |
在 write 模式下,过程仅返回一行结果。该结果包含元信息,如识别出的社区数量。结果被写入 Neo4j 数据库,而不是 GDS 内存图。
加权 (Weighted)
Leiden 算法也可以在加权图上运行,在计算模块度时考虑给定的关系权重。
CALL gds.leiden.stream('myGraph', { relationshipWeightProperty: 'weight', randomSeed: 19 })
YIELD nodeId, communityId
RETURN gds.util.asNode(nodeId).name AS name, communityId
ORDER BY name ASC
| 名称 (name) | communityId |
|---|---|
"Alice" |
4 |
“Bridget” |
1 |
“Charles” |
1 |
“Doug” |
4 |
“Mark” |
5 |
“Michael” |
5 |
使用加权关系,我们看到 Alice 和 Doug 形成了他们自己的社区,因为他们的链接比其他所有链接都要强得多。
使用中间社区
如前所述,Leiden 是一种层次聚类算法。这意味着在每个聚类步骤之后,所有属于同一簇的节点都会被简化为一个节点。同一簇中节点之间的关系变为自循环关系,与其他簇节点的关系则连接到该簇的代表节点。然后,这个压缩后的图被用于运行下一层聚类。该过程重复进行,直到簇稳定为止。
为了演示这种迭代行为,我们需要构建一个更复杂的图。
CREATE (a:Node {name: 'a'})
CREATE (b:Node {name: 'b'})
CREATE (c:Node {name: 'c'})
CREATE (d:Node {name: 'd'})
CREATE (e:Node {name: 'e'})
CREATE (f:Node {name: 'f'})
CREATE (g:Node {name: 'g'})
CREATE (h:Node {name: 'h'})
CREATE (i:Node {name: 'i'})
CREATE (j:Node {name: 'j'})
CREATE (k:Node {name: 'k'})
CREATE (l:Node {name: 'l'})
CREATE (m:Node {name: 'm'})
CREATE (n:Node {name: 'n'})
CREATE (x:Node {name: 'x'})
CREATE (a)-[:TYPE]->(b)
CREATE (a)-[:TYPE]->(d)
CREATE (a)-[:TYPE]->(f)
CREATE (b)-[:TYPE]->(d)
CREATE (b)-[:TYPE]->(x)
CREATE (b)-[:TYPE]->(g)
CREATE (b)-[:TYPE]->(e)
CREATE (c)-[:TYPE]->(x)
CREATE (c)-[:TYPE]->(f)
CREATE (d)-[:TYPE]->(k)
CREATE (e)-[:TYPE]->(x)
CREATE (e)-[:TYPE]->(f)
CREATE (e)-[:TYPE]->(h)
CREATE (f)-[:TYPE]->(g)
CREATE (g)-[:TYPE]->(h)
CREATE (h)-[:TYPE]->(i)
CREATE (h)-[:TYPE]->(j)
CREATE (i)-[:TYPE]->(k)
CREATE (j)-[:TYPE]->(k)
CREATE (j)-[:TYPE]->(m)
CREATE (j)-[:TYPE]->(n)
CREATE (k)-[:TYPE]->(m)
CREATE (k)-[:TYPE]->(l)
CREATE (l)-[:TYPE]->(n)
CREATE (m)-[:TYPE]->(n);
MATCH (source:Node)
OPTIONAL MATCH (source)-[r:TYPE]->(target:Node)
RETURN gds.graph.project(
'myGraph2',
source,
target,
{},
{ undirectedRelationshipTypes: ['*'] }
)
流式传输中间社区
CALL gds.leiden.stream('myGraph2', {
randomSeed: 23,
includeIntermediateCommunities: true,
concurrency: 1
})
YIELD nodeId, communityId, intermediateCommunityIds
RETURN gds.util.asNode(nodeId).name AS name, communityId, intermediateCommunityIds
ORDER BY name ASC
| 名称 (name) | communityId | intermediateCommunityIds |
|---|---|---|
"a" |
4 |
[2, 4] |
"b" |
4 |
[2, 4] |
"c" |
5 |
[7, 5] |
"d" |
4 |
[2, 4] |
"e" |
5 |
[6, 5] |
"f" |
5 |
[7, 5] |
"g" |
5 |
[7, 5] |
"h" |
5 |
[11, 5] |
"i" |
5 |
[11, 5] |
"j" |
1 |
[12, 1] |
"k" |
1 |
[12, 1] |
"l" |
1 |
[12, 1] |
"m" |
1 |
[12, 1] |
"n" |
1 |
[12, 1] |
"x" |
5 |
[6, 5] |
种子 (Seeded)
通过提供种子(seed)属性,可以增量运行 Leiden 算法。如果指定,种子属性将为部分已加载节点提供初始社区映射。算法将尝试保留种子社区 ID。
CALL gds.leiden.stream('myGraph', { seedProperty: 'seed' })
YIELD nodeId, communityId, intermediateCommunityIds
RETURN gds.util.asNode(nodeId).name AS name, communityId, intermediateCommunityIds
ORDER BY name ASC
| 名称 (name) | communityId | intermediateCommunityIds |
|---|---|---|
"Alice" |
42 |
null |
“Bridget” |
42 |
null |
“Charles” |
42 |
null |
“Doug” |
45 |
null |
“Mark” |
45 |
null |
“Michael” |
45 |
null |
可以看出,使用种子图时,节点 Alice 保留了其初始社区 ID 42。另一个社区被分配了一个新的社区 ID,该 ID 保证大于最大的种子社区 ID。注意,consecutiveIds 配置选项不能与种子设定结合使用,以便保留种子值。
变更中间社区
CALL gds.leiden.mutate('myGraph2', {
mutateProperty: 'intermediateCommunities',
randomSeed: 23,
includeIntermediateCommunities: true,
concurrency: 1
})
YIELD communityCount, modularity, modularities
| communityCount | modularity | modularities |
|---|---|---|
3 |
0.3624 |
[0.3296, 0.3624] |
CALL gds.graph.nodeProperty.stream('myGraph2', 'intermediateCommunities')
YIELD nodeId, propertyValue
RETURN
gds.util.asNode(nodeId).name AS name,
toIntegerList(propertyValue) AS intermediateCommunities
ORDER BY name ASC
| 名称 (name) | intermediateCommunities |
|---|---|
"a" |
[2, 4] |
"b" |
[2, 4] |
"c" |
[7, 5] |
"d" |
[2, 4] |
"e" |
[6, 5] |
"f" |
[7, 5] |
"g" |
[7, 5] |
"h" |
[11, 5] |
"i" |
[11, 5] |
"j" |
[12, 1] |
"k" |
[12, 1] |
"l" |
[12, 1] |
"m" |
[12, 1] |
"n" |
[12, 1] |
"x" |
[6, 5] |
写入中间社区
CALL gds.leiden.write('myGraph2', {
writeProperty: 'intermediateCommunities',
randomSeed: 19,
includeIntermediateCommunities: true,
concurrency: 1
})
YIELD communityCount, modularity, modularities
| communityCount | modularity | modularities |
|---|---|---|
3 |
0.3624 |
[0.3296, 0.3624] |
MATCH (n:Node) RETURN n.name AS name, toIntegerList(n.intermediateCommunities) AS intermediateCommunities
ORDER BY name ASC
| 名称 (name) | intermediateCommunities |
|---|---|
"a" |
[2, 4] |
"b" |
[2, 4] |
"c" |
[7, 5] |
"d" |
[2, 4] |
"e" |
[6, 5] |
"f" |
[7, 5] |
"g" |
[7, 5] |
"h" |
[11, 5] |
"i" |
[11, 5] |
"j" |
[12, 1] |
"k" |
[12, 1] |
"l" |
[12, 1] |
"m" |
[12, 1] |
"n" |
[12, 1] |
"x" |
[6, 5] |