快速随机投影
词汇表
- 有向
-
有向特性。该算法在有向图上定义良好。
- 有向
-
有向特性。该算法忽略图的方向。
- 有向
-
有向特性。该算法无法在有向图上运行。
- 无向
-
无向特性。该算法在无向图上定义良好。
- 无向
-
无向特性。该算法忽略图的无向性。
- 异构节点
-
异构节点 完全支持。该算法能够区分不同类型的节点。
- 异构节点
-
异构节点 允许。该算法对所有选定的节点进行类似处理,而不管其标签如何。
- 异构关系
-
异构关系 完全支持。该算法能够区分不同类型的关系。
- 异构关系
-
异构关系 允许。该算法对所有选定的关系进行类似处理,而不管其类型如何。
- 加权关系
-
加权特性。该算法支持使用关系属性作为权重,通过 relationshipWeightProperty 配置参数指定。
- 加权关系
-
加权特性。该算法将每个关系视为同等重要,丢弃任何关系权重的值。
FastRP 在端到端示例 Jupyter 笔记本中有所介绍 |
简介
快速随机投影,简称FastRP,是一种属于随机投影算法家族的节点嵌入算法。这些算法在理论上得到了约翰逊-林德斯特劳斯引理的支持,该引理指出,可以将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的幂。对于大约105个节点的图,至少256的值可以获得良好的结果,但一般来说,增加维度可以改善结果。但是,增加嵌入维度将线性地增加内存需求和运行时间。
归一化强度
归一化强度用于控制节点度如何影响嵌入。使用负值将淡化高度邻居的重要性,而使用正值则会增加它们的重要性。最佳归一化强度取决于图以及将使用嵌入的任务。在原始论文中,超参数调整是在[-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 字节" |
流
在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。
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。
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归一化,因此所有节点都具有相同的嵌入,尽管具有不同的年龄值(舍入误差除外)。