快速随机投影
术语表
- 有向
-
有向特性。该算法在有向图上定义良好。
- 有向
-
有向特性。该算法忽略图的方向。
- 有向
-
有向特性。该算法不在有向图上运行。
- 无向
-
无向特性。该算法在无向图上定义良好。
- 无向
-
无向特性。该算法忽略图的无向性。
- 异构节点
-
完全支持异构节点。该算法能够区分不同类型的节点。
- 异构节点
-
允许异构节点。该算法对所有选定的节点一视同仁,无论其标签如何。
- 异构关系
-
完全支持异构关系。该算法能够区分不同类型的关系。
- 异构关系
-
允许异构关系。该算法对所有选定的关系一视同仁,无论其类型如何。
- 加权关系
-
加权特性。该算法支持使用关系属性作为权重,通过relationshipWeightProperty 配置参数指定。
- 加权关系
-
加权特性。该算法将每个关系视为同等重要,忽略任何关系权重的值。
FastRP 在端到端示例 Jupyter Notebooks 中有特色展示 |
简介
快速随机投影(简称 FastRP)是随机投影算法系列中的一种节点嵌入算法。这些算法在理论上由 Johnsson-Lindenstrauss 引理支持,该引理指出可以将任意维度的 n 个向量投影到 O(log(n)) 维度中,并且仍然近似保留点之间的成对距离。事实上,随机选择的线性投影满足此特性。
因此,这些技术允许进行积极的降维,同时保留大部分距离信息。FastRP 算法在图上运行,在这种情况下,我们关心的是保留节点及其邻居之间的相似性。这意味着具有相似邻域的两个节点应分配相似的嵌入向量。相反,不相似的两个节点不应分配相似的嵌入向量。
GDS 实现的 FastRP 在以下几个方面扩展了原始算法[1]
-
它允许使用节点属性来影响初始随机向量的创建。
-
它引入了
nodeSelfInfluence
参数。 -
它支持有向图。
-
它支持加权图。
FastRP 算法最初使用一种称为非常稀疏随机投影[2]的技术将随机向量分配给所有节点。从随机向量(节点投影)开始,并迭代地对节点邻域进行平均,该算法为每个节点 n 构建一系列中间嵌入 。更精确地说,
其中 m 遍历 n 的邻居, 是节点的初始随机向量。
节点 n 的嵌入 ,即算法的输出,是上述定义向量和嵌入的组合
因此,每个节点的嵌入取决于半径等于迭代次数的邻域。通过这种方式,FastRP 利用了图中的高阶关系,同时仍然具有高度可伸缩性。
节点属性
大多数真实世界图都包含节点属性,这些属性存储有关节点及其所代表的信息。GDS 库中的 FastRP 算法扩展了原始 FastRP 算法,使其能够考虑节点属性。因此,生成的嵌入可以更准确地表示图。
算法的节点属性感知方面通过参数 featureProperties
和 propertyRatio
进行配置。featureProperties
中的每个节点属性都与一个维度为 propertyDimension
的随机生成向量相关联,其中 propertyDimension = embeddingDimension * propertyRatio
。然后,每个节点都用一个大小为 embeddingDimension
的向量进行初始化,该向量由两部分连接而成
-
第一部分与标准 FastRP 算法中的形成方式相同,
-
第二部分是属性向量的线性组合,使用节点的属性值作为权重。
然后算法以与 FastRP 算法相同的逻辑继续。因此,算法将输出大小为 embeddingDimension
的数组。嵌入中最后 propertyDimension
个坐标捕获有关附近节点的属性值的信息(下面的“属性部分”),其余坐标(embeddingDimension
- propertyDimension
个;“拓扑部分”)捕获有关附近节点存在的信息。
[0, 1, ... | ..., N - 1, N] ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ topology part | property part ^ property ratio
在机器学习管道中的使用
为了使机器学习模型能够做出有用的预测,重要的是预测期间生成的特征与模型训练期间生成的特征具有相似的分布。此外,添加到管道中的节点属性步骤(无论是 FastRP 还是其他)在训练期间和训练模型的预测期间都会执行。因此,当管道包含一个在训练和预测期间产生过于不相似嵌入的嵌入步骤时,就会出现问题。
这对抗如何将 FastRP 用作节点属性步骤产生了一些影响。通常,如果使用 FastRP 作为节点属性步骤在某个图“g”上训练管道,则生成的训练模型应仅应用于与“g”不相差太大的图。
如果 propertyRatio<1.0
,则运行预测的图中的大多数节点必须与训练期间使用的原始图“g”中的节点(在数据库意义上)相同。原因在于 FastRP 是一种随机算法,在这种情况下,它是根据节点在 Neo4j 数据库中的 ID 进行初始化的。
但是,如果 propertyRatio=1.0
,则随机初始节点嵌入仅从节点属性向量派生,因此没有基于节点 ID 的随机初始化。
此外,为了使初始随机向量(与使用的 propertyRatio
无关)在运行(训练和预测调用)之间保持一致,在将 FastRP 节点属性步骤添加到训练管道时,必须为 randomSeed
配置参数提供一个值。
总之,如果您设置了随机种子并将 propertyRatio
设置为 1,则 FastRP 具有归纳性,因为嵌入仅基于确定性地投影到向量中的节点属性。
算法参数调优
为了使用 FastRP 改进您的图上的嵌入质量,可以调整算法参数。为您的特定用例和图找到最佳参数的过程通常称为超参数调优。我们将逐一介绍每个配置参数并解释它们的行为方式。
为了获得统计学上可靠的结果,最好保留一个排除参数调优的测试集。选择一组参数值后,可以使用下游机器学习任务在测试集上评估嵌入质量。通过改变参数值并研究机器学习任务的精度,可以推断出最适合具体数据集和用例的参数值。为了构建这样的集合,您可能希望在图中使用专用的节点标签来表示不包含测试数据的子图。
嵌入维度
嵌入维度是生成的向量的长度。更大的维度提供更高的精度,但操作成本更高。
最佳嵌入维度取决于图中的节点数量。由于嵌入可以编码的信息量受其维度的限制,因此更大的图往往需要更大的嵌入维度。典型值是 128 - 1024 范围内的 2 的幂。至少 256 的值在 105 节点数量级的图上能得到良好的结果,但通常增加维度会改善结果。然而,增加嵌入维度将线性增加内存需求和运行时。
归一化强度
归一化强度用于控制节点度如何影响嵌入。使用负值会降低高阶邻居的重要性,而正值则会增加其重要性。最佳归一化强度取决于图以及嵌入将用于的任务。在原始论文中,超参数调优在 [-1,0]
范围内进行(没有正值),但我们发现有些情况下正归一化强度会产生更好的结果。
迭代权重
迭代权重参数控制两个方面:迭代次数及其对最终节点嵌入的相对影响。该参数是一个数字列表,每个数字表示一次迭代,其中数字是应用于该迭代的权重。
在每次迭代中,算法将扩展图中所有关系。这有一些影响
-
单次迭代只会考虑每个节点的直接邻居。
-
两次迭代会考虑每个节点的直接邻居和二度邻居。
-
三次迭代会考虑每个节点的直接邻居、二度邻居和三度邻居。直接邻居可能会在不同的迭代中被两次访问。
-
通常,第
i
次迭代对应的嵌入包含取决于通过长度为i
的路径可达的节点的特征。如果图是无向的,则通过长度为L
的路径可达的节点也可以通过长度为L+2k
的路径可达,对于任何整数k
。 -
特别是在每个偶数迭代中,节点可能会回到自身(取决于图中的方向)。
最好在偶数和奇数位置上至少有一个非零权重。通常,建议使用至少几次迭代,例如三次。但是,过高的值将考虑远处的节点,可能没有信息量甚至有害。这里的直觉是,随着投影距离节点越来越远,邻域的特异性越低。当然,更多的迭代也将花费更多时间来完成。
节点自影响力
节点自影响力是原始 FastRP 算法的一个变体。
节点的嵌入受第 i 次迭代中的中间嵌入影响的程度由 iterationWeights
的第 i 个元素控制。这也可以看作是从节点经过 i 跳可达的节点的初始随机向量或投影对节点嵌入的影响程度。类似地,nodeSelfInfluence
的行为类似于第 0 次迭代的迭代权重,或者节点投影对同一节点嵌入的影响量。
将此参数设置为非零值的原因是,如果您的图连接性低或存在大量孤立节点。孤立节点与使用 propertyRatio = 0.0
结合会导致嵌入包含全零。但是,结合节点属性和节点自影响力可以为这些节点生成更有意义的嵌入。这可以看作是在图结构(局部)缺失时生成回退特征。此外,有时节点自身的属性只是信息丰富的特征,即使连接性高也值得包含。最后,节点自影响力可用于纯降维,以压缩用于节点分类的节点属性。
如果不使用节点属性,nodeSelfInfluence
的使用也可能产生积极影响,具体取决于其他设置和问题。
语法
本节介绍了在每种执行模式下执行 FastRP 算法所使用的语法。我们正在描述命名图语法变体。要了解更多关于通用语法变体的信息,请参阅语法概述。
CALL gds.fastRP.stream(
graphName: String,
configuration: Map
) YIELD
nodeId: Integer,
embedding: List of Float
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
configuration |
映射 |
|
是 |
算法特定配置和/或图过滤配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
字符串列表 |
|
是 |
使用给定节点标签过滤命名图。将包含具有任何给定标签的节点。 |
|
字符串列表 |
|
是 |
使用给定关系类型过滤命名图。将包含具有任何给定类型的关系。 |
|
整数 |
|
是 |
运行算法所使用的并发线程数。 |
|
字符串 |
|
是 |
可用于更轻松地跟踪算法进度的 ID。 |
|
布尔值 |
|
是 |
如果禁用,则不会记录进度百分比。 |
|
propertyRatio |
浮点数 |
|
是 |
属性嵌入维度与总 |
featureProperties |
字符串列表 |
|
是 |
应用作输入特征的节点属性名称。所有属性名称必须存在于投影图中,并且类型为浮点数或浮点数列表。 |
embeddingDimension |
整数 |
|
否 |
计算出的节点嵌入的维度。最小值为 1。 |
iterationWeights |
浮点数列表 |
|
是 |
包含每次迭代的权重。权重控制迭代中的中间嵌入对最终嵌入的贡献程度。 |
nodeSelfInfluence |
浮点数 |
|
是 |
控制每个节点的初始随机向量对其最终嵌入的贡献程度。 |
normalizationStrength |
浮点数 |
|
是 |
每个节点的初始随机向量按其度数的 |
randomSeed |
整数 |
|
是 |
用于计算嵌入中所有随机性的随机种子。 |
字符串 |
|
是 |
用于加权随机投影的关系属性名称。如果未指定,算法将运行无权重。 |
|
迭代次数等于 |
||||
要求 |
||||
名称 | 类型 | 描述 |
---|---|---|
nodeId |
整数 |
节点 ID。 |
embedding |
浮点数列表 |
FastRP 节点嵌入。 |
CALL gds.fastRP.stats(
graphName: String,
configuration: Map
) YIELD
nodeCount: Integer,
preProcessingMillis: Integer,
computeMillis: Integer,
configuration: Map
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
configuration |
映射 |
|
是 |
算法特定配置和/或图过滤配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
字符串列表 |
|
是 |
使用给定节点标签过滤命名图。将包含具有任何给定标签的节点。 |
|
字符串列表 |
|
是 |
使用给定关系类型过滤命名图。将包含具有任何给定类型的关系。 |
|
整数 |
|
是 |
运行算法所使用的并发线程数。 |
|
字符串 |
|
是 |
可用于更轻松地跟踪算法进度的 ID。 |
|
布尔值 |
|
是 |
如果禁用,则不会记录进度百分比。 |
|
propertyRatio |
浮点数 |
|
是 |
属性嵌入维度与总 |
featureProperties |
字符串列表 |
|
是 |
应用作输入特征的节点属性名称。所有属性名称必须存在于投影图中,并且类型为浮点数或浮点数列表。 |
embeddingDimension |
整数 |
|
否 |
计算出的节点嵌入的维度。最小值为 1。 |
iterationWeights |
浮点数列表 |
|
是 |
包含每次迭代的权重。权重控制迭代中的中间嵌入对最终嵌入的贡献程度。 |
nodeSelfInfluence |
浮点数 |
|
是 |
控制每个节点的初始随机向量对其最终嵌入的贡献程度。 |
normalizationStrength |
浮点数 |
|
是 |
每个节点的初始随机向量按其度数的 |
randomSeed |
整数 |
|
是 |
用于计算嵌入中所有随机性的随机种子。 |
字符串 |
|
是 |
用于加权随机投影的关系属性名称。如果未指定,算法将运行无权重。 |
|
迭代次数等于 |
||||
要求 |
||||
名称 | 类型 | 描述 |
---|---|---|
nodeCount |
整数 |
处理的节点数量。 |
preProcessingMillis |
整数 |
预处理图的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
configuration |
映射 |
运行算法使用的配置。 |
CALL gds.fastRP.mutate(
graphName: String,
configuration: Map
) YIELD
nodeCount: Integer,
nodePropertiesWritten: Integer,
preProcessingMillis: Integer,
computeMillis: Integer,
mutateMillis: Integer,
configuration: Map
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
configuration |
映射 |
|
是 |
算法特定配置和/或图过滤配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
mutateProperty |
字符串 |
|
否 |
嵌入写入的 GDS 图中的节点属性。 |
字符串列表 |
|
是 |
使用给定节点标签过滤命名图。 |
|
字符串列表 |
|
是 |
使用给定关系类型过滤命名图。 |
|
整数 |
|
是 |
运行算法所使用的并发线程数。 |
|
字符串 |
|
是 |
可用于更轻松地跟踪算法进度的 ID。 |
|
propertyRatio |
浮点数 |
|
是 |
属性嵌入维度与总 |
featureProperties |
字符串列表 |
|
是 |
应用作输入特征的节点属性名称。所有属性名称必须存在于投影图中,并且类型为浮点数或浮点数列表。 |
embeddingDimension |
整数 |
|
否 |
计算出的节点嵌入的维度。最小值为 1。 |
iterationWeights |
浮点数列表 |
|
是 |
包含每次迭代的权重。权重控制迭代中的中间嵌入对最终嵌入的贡献程度。 |
nodeSelfInfluence |
浮点数 |
|
是 |
控制每个节点的初始随机向量对其最终嵌入的贡献程度。 |
normalizationStrength |
浮点数 |
|
是 |
每个节点的初始随机向量按其度数的 |
randomSeed |
整数 |
|
是 |
用于计算嵌入中所有随机性的随机种子。 |
字符串 |
|
是 |
用于加权随机投影的关系属性名称。如果未指定,算法将运行无权重。 |
|
迭代次数等于 |
||||
要求 |
名称 | 类型 | 描述 |
---|---|---|
nodeCount |
整数 |
处理的节点数量。 |
nodePropertiesWritten |
整数 |
写入的节点属性数量。 |
preProcessingMillis |
整数 |
预处理图的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
mutateMillis |
整数 |
将属性添加到内存图的毫秒数。 |
configuration |
映射 |
运行算法使用的配置。 |
CALL gds.fastRP.write(
graphName: String,
configuration: Map
) YIELD
nodeCount: Integer,
nodePropertiesWritten: Integer,
preProcessingMillis: Integer,
computeMillis: Integer,
writeMillis: Integer,
configuration: Map
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
graphName |
字符串 |
|
否 |
存储在目录中的图的名称。 |
configuration |
映射 |
|
是 |
算法特定配置和/或图过滤配置。 |
名称 | 类型 | 默认值 | 可选 | 描述 |
---|---|---|---|---|
字符串列表 |
|
是 |
使用给定节点标签过滤命名图。将包含具有任何给定标签的节点。 |
|
字符串列表 |
|
是 |
使用给定关系类型过滤命名图。将包含具有任何给定类型的关系。 |
|
整数 |
|
是 |
运行算法所使用的并发线程数。 |
|
字符串 |
|
是 |
可用于更轻松地跟踪算法进度的 ID。 |
|
布尔值 |
|
是 |
如果禁用,则不会记录进度百分比。 |
|
整数 |
|
是 |
用于将结果写入 Neo4j 的并发线程数。 |
|
字符串 |
|
否 |
嵌入写入的 Neo4j 数据库中的节点属性。 |
|
propertyRatio |
浮点数 |
|
是 |
属性嵌入维度与总 |
featureProperties |
字符串列表 |
|
是 |
应用作输入特征的节点属性名称。所有属性名称必须存在于投影图中,并且类型为浮点数或浮点数列表。 |
embeddingDimension |
整数 |
|
否 |
计算出的节点嵌入的维度。最小值为 1。 |
iterationWeights |
浮点数列表 |
|
是 |
包含每次迭代的权重。权重控制迭代中的中间嵌入对最终嵌入的贡献程度。 |
nodeSelfInfluence |
浮点数 |
|
是 |
控制每个节点的初始随机向量对其最终嵌入的贡献程度。 |
normalizationStrength |
浮点数 |
|
是 |
每个节点的初始随机向量按其度数的 |
randomSeed |
整数 |
|
是 |
用于计算嵌入中所有随机性的随机种子。 |
字符串 |
|
是 |
用于加权随机投影的关系属性名称。如果未指定,算法将运行无权重。 |
|
迭代次数等于 |
||||
要求 |
||||
名称 | 类型 | 描述 |
---|---|---|
nodeCount |
整数 |
处理的节点数量。 |
nodePropertiesWritten |
整数 |
写入的节点属性数量。 |
preProcessingMillis |
整数 |
预处理图的毫秒数。 |
computeMillis |
整数 |
运行算法的毫秒数。 |
writeMillis |
整数 |
将结果数据写回 Neo4j 的毫秒数。 |
configuration |
映射 |
运行算法使用的配置。 |
示例
以下所有示例都应在空数据库中运行。 这些示例以Cypher 投影为规范。本机投影将在未来版本中弃用。 |
在本节中,我们将展示在具体图上运行 FastRP 节点嵌入算法的示例。目的是说明结果是什么样子,并提供在实际设置中如何使用该算法的指南。我们将在一个小型社交网络图上进行此操作,该图由少量节点以特定模式连接。示例图如下所示
CREATE
(dan:Person {name: 'Dan', age: 18}),
(annie:Person {name: 'Annie', age: 12}),
(matt:Person {name: 'Matt', age: 22}),
(jeff:Person {name: 'Jeff', age: 51}),
(brie:Person {name: 'Brie', age: 45}),
(elsa:Person {name: 'Elsa', age: 65}),
(john:Person {name: 'John', age: 64}),
(dan)-[:KNOWS {weight: 1.0}]->(annie),
(dan)-[:KNOWS {weight: 1.0}]->(matt),
(annie)-[:KNOWS {weight: 1.0}]->(matt),
(annie)-[:KNOWS {weight: 1.0}]->(jeff),
(annie)-[:KNOWS {weight: 1.0}]->(brie),
(matt)-[:KNOWS {weight: 3.5}]->(brie),
(brie)-[:KNOWS {weight: 1.0}]->(elsa),
(brie)-[:KNOWS {weight: 2.0}]->(jeff),
(john)-[:KNOWS {weight: 1.0}]->(jeff);
该图表示七个相互认识的人。关系属性 weight
表示两个人之间知识的强度。
在 Neo4j 中有了图,我们现在可以将其投影到图目录中,为算法执行做好准备。我们使用针对 Person
节点和 KNOWS
关系的 Cypher 投影来完成此操作。对于关系,我们将使用 UNDIRECTED
方向。这是因为 FastRP 算法已被测量出在无向图中计算出更具预测性的节点嵌入。我们还将添加 weight
关系属性,我们将在运行 FastRP 的加权版本时利用该属性。
MATCH (source:Person)-[r:KNOWS]->(target:Person)
RETURN gds.graph.project(
'persons',
source,
target,
{
sourceNodeProperties: source { .age },
targetNodeProperties: target { .age },
relationshipProperties: r { .weight }
},
{ undirectedRelationshipTypes: ['*'] }
)
内存估算
首先,我们将使用 estimate
过程估算运行算法的成本。这可以在任何执行模式下完成。在本例中,我们将使用 stream
模式。估算算法有助于了解在图上运行算法对内存的影响。当您稍后实际以某种执行模式运行算法时,系统将执行估算。如果估算显示执行超出其内存限制的可能性非常高,则禁止执行。要了解更多信息,请参阅自动估算和执行阻止。
有关 estimate
的更多详细信息,请参阅内存估算。
CALL gds.fastRP.stream.estimate('persons', {embeddingDimension: 128})
YIELD nodeCount, relationshipCount, bytesMin, bytesMax, requiredMemory
nodeCount | relationshipCount | bytesMin | bytesMax | requiredMemory |
---|---|---|---|---|
7 |
18 |
11392 |
11392 |
"11392 Bytes" |
流
在 stream
执行模式下,算法返回每个节点的嵌入。这允许我们直接检查结果或在 Cypher 中对其进行后处理,而没有任何副作用。例如,我们可以收集结果并将其传递给相似度算法。
有关 stream
模式的更多详细信息,请参阅流。
CALL gds.fastRP.stream('persons',
{
embeddingDimension: 4,
randomSeed: 42
}
)
YIELD nodeId, embedding
RETURN gds.util.asNode(nodeId).name as person, embedding
ORDER BY person
person | embedding |
---|---|
"Annie" |
[0.51714468, -0.4148067832, -0.5454565287, -1.741045475] |
"Brie" |
[0.4184039235, -0.4415202737, 0.2315290272, -1.5677155256] |
"Dan" |
[0.2612129152, -0.6138446331, -0.369674772, -1.7762401104] |
"Elsa" |
[0.5556756258, -0.3558300138, 0.308482945, -1.5653611422] |
"Jeff" |
[0.6856793165, -0.3247893453, -0.3811529875, -1.5765502453] |
"John" |
[1.0, -0.0890870914, -0.4454354346, -0.8908708692] |
"Matt" |
[0.2737978995, -0.4965225756, -0.3031099439, -1.8122189045] |
算法的结果不太容易直观地解释,因为节点嵌入格式是节点在其邻域内的数学抽象,专为机器学习程序设计。我们可以看到,嵌入有四个元素(根据 embeddingDimension
配置)并且数字相对较小(它们都落在 [-2, 2]
的范围内)。数字的大小由 embeddingDimension
、图中节点的数量以及 FastRP 对中间嵌入向量执行欧几里得归一化的事实控制。
由于算法的随机性,结果在不同运行之间会有所不同。然而,这不一定意味着两个节点嵌入的成对距离变化很大。 |
统计
在 stats
执行模式下,算法返回一行,其中包含算法结果的摘要。此执行模式没有任何副作用。通过检查 computeMillis
返回项来评估算法性能可能很有用。在下面的示例中,我们将省略返回时间。该过程的完整签名可在语法部分找到。
有关 stats
模式的更多详细信息,请参阅统计。
CALL gds.fastRP.stats('persons', { embeddingDimension: 8 })
YIELD nodeCount
nodeCount |
---|
7 |
stats
模式目前不提供嵌入本身的任何统计结果。但是,我们可以看到算法已成功处理了示例图中的所有七个节点。
变异
mutate
执行模式扩展了 stats
模式,增加了一个重要的副作用:使用包含该节点嵌入的新节点属性更新命名图。新属性的名称使用强制配置参数 mutateProperty
指定。结果是与 stats
类似的单个摘要行,但包含一些附加指标。当多个算法结合使用时,mutate
模式特别有用。
有关 mutate
模式的更多详细信息,请参阅变异。
mutate
模式下运行算法CALL gds.fastRP.mutate(
'persons',
{
embeddingDimension: 8,
mutateProperty: 'fastrp-embedding'
}
)
YIELD nodePropertiesWritten
nodePropertiesWritten |
---|
7 |
返回的结果与 stats
示例类似。此外,图“persons”现在具有一个节点属性 fastrp-embedding
,它存储每个节点的节点嵌入。要了解如何检查内存图的新模式,请参阅列出图。
写入
write
执行模式扩展了 stats
模式,增加了一个重要的副作用:将每个节点的嵌入作为属性写入 Neo4j 数据库。新属性的名称使用强制配置参数 writeProperty
指定。结果是与 stats
类似的单个摘要行,但包含一些附加指标。write
模式可以直接将结果持久化到数据库。
有关 write
模式的更多详细信息,请参阅写入。
write
模式下运行算法CALL gds.fastRP.write(
'persons',
{
embeddingDimension: 8,
writeProperty: 'fastrp-embedding'
}
)
YIELD nodePropertiesWritten
nodePropertiesWritten |
---|
7 |
返回的结果与 stats
示例类似。此外,七个节点中的每个节点现在都在 Neo4j 数据库中拥有一个新的属性 fastrp-embedding
,其中包含该节点的节点嵌入。
加权
以下是运行算法加权变体的示例。
CALL gds.fastRP.stream(
'persons',
{
embeddingDimension: 4,
randomSeed: 42,
relationshipWeightProperty: 'weight'
}
)
YIELD nodeId, embedding
RETURN gds.util.asNode(nodeId).name as person, embedding
ORDER BY person
person | embedding |
---|---|
"Annie" |
[0.034561187, -0.2929389477, 0.0952546224, -1.9652962685] |
"Brie" |
[0.1023679227, -0.2991863489, 0.5466092229, -1.2881529331] |
"Dan" |
[-0.0909044892, -0.4465829134, 0.3275954127, -1.6877939701] |
"Elsa" |
[0.0776494294, -0.2621908784, 0.5610812902, -1.2880744934] |
"Jeff" |
[0.1686269641, -0.2775687575, 0.4166130424, -1.3728146553] |
"John" |
[0.5247224569, -0.045596078, 0.3423381448, -0.9119215012] |
"Matt" |
[0.0523263216, -0.3151839674, 0.4781413078, -1.4239065647] |
由于算法的初始状态是随机的,因此无法直观地分析关系权重的影响。
使用节点属性作为特征
为了解释使用节点属性进行的新颖初始化,让我们考虑一个示例,其中 embeddingDimension
为 10,propertyRatio
为 0.2。因此,嵌入属性的维度 propertyDimension
为 2。假设我们有一个标量类型的属性 f1
,以及一个存储长度为 2 的数组的属性 f2
。这意味着有 3 个特征,我们按 f1
后跟 f2
的两个值的顺序排列。对于这三个特征中的每一个,我们采样一个二维随机向量。假设它们是 p1=[0.0, 2.4]
,p2=[-2.4, 0.0]
和 p3=[2.4, 0.0]
。现在考虑一个节点 (n {f1: 0.5, f2: [1.0, -1.0]})
。上面提到的线性组合,具体来说是 0.5 * p1 + 1.0 * p2 - 1.0 * p3 = [-4.8, 1.2]
。节点 n
的初始随机向量包含前 8 个值,这些值是按照原始 FastRP 论文中采样得到的,然后是我们计算出的值 -4.8
和 1.2
,总共 10 个条目。
在下面的示例中,我们再次将嵌入维度设置为 2,但我们将 propertyRatio
设置为 1,这意味着嵌入仅从节点属性计算。
CALL gds.fastRP.stream('persons', {
randomSeed: 42,
embeddingDimension: 2,
propertyRatio: 1.0,
featureProperties: ['age'],
iterationWeights: [1.0]
}) YIELD nodeId, embedding
RETURN gds.util.asNode(nodeId).name AS person, embedding
ORDER BY person
person | embedding |
---|---|
"Annie" |
[0.0, -1.0] |
"Brie" |
[0.0, -0.9999999403953552] |
"Dan" |
[0.0, -1.0] |
"Elsa" |
[0.0, -1.0] |
"Jeff" |
[0.0, -1.0] |
"John" |
[0.0, -1.0] |
"Matt" |
[0.0, -0.9999999403953552] |
在此示例中,嵌入基于 age
属性。由于对每次迭代应用了 L2 归一化(此处仅一次迭代),因此尽管所有节点具有不同的年龄值(舍入误差除外),但它们都具有相同的嵌入。