运行算法

在下面的示例中,我们假设我们有一个名为 gds 的已实例化的 GraphDataScience 对象。有关此的更多信息,请阅读 入门

1. 介绍

使用 Python 客户端运行大多数算法在结构上与使用 Cypher API 类似

语法组成
result = gds[.<tier>].<algorithm>.<execution-mode>[.<estimate>](
  G: Graph,
  **configuration: dict[str, any]
)

在这里,我们可以注意到一些关键区别

  • 我们使用 图对象 作为第一个位置参数,而不是第一个参数的图名称字符串。

  • 我们使用命名的关键字参数,而不是配置映射。

运行过程的结果将作为 pandas DataFrame 或 pandas Series 返回,具体取决于 执行模式

为了说明这一点,我们介绍一个小型道路网络图

gds.run_cypher(
  """
  CREATE
    (a:City {name: "New York City", settled: 1624}),
    (b:City {name: "Philadelphia", settled: 1682}),
    (c:City:Capital {name: "Washington D.C.", settled: 1790}),
    (d:City {name: "Baltimore"}),
    (e:City {name: "Atlantic City"}),
    (f:City {name: "Boston"}),

    (a)-[:ROAD {cost: 50}]->(b),
    (a)-[:ROAD {cost: 50}]->(c),
    (a)-[:ROAD {cost: 100}]->(d),
    (b)-[:ROAD {cost: 40}]->(d),
    (c)-[:ROAD {cost: 40}]->(d),
    (c)-[:ROAD {cost: 80}]->(e),
    (d)-[:ROAD {cost: 30}]->(e),
    (d)-[:ROAD {cost: 80}]->(f),
    (e)-[:ROAD {cost: 40}]->(f);
  """
)
G, project_result = gds.graph.project("road_graph", "City", {"ROAD": {"properties": ["cost"]}})

assert G.relationship_count() == 9

现在我们准备在我们的图 G 上运行算法。

louvain_result = gds.louvain.mutate(
    G,                            #  Graph object
    maxIterations=5,              #  Configuration parameters
    mutateProperty="community"
)
assert louvain_result["communityCount"] > 0

fastrp_result = gds.fastRP.write(
    G,                                #  Graph object
    featureProperties=["community"],  #  Configuration parameters
    embeddingDimension=256,
    propertyRatio=0.3,
    relationshipWeightProperty="cost",
    writeProperty="embedding"
)
assert fastrp_result["nodePropertiesWritten"] == G.node_count()

某些算法偏离了标准语法结构。我们在下面的部分中描述了如何在 Python 客户端中使用它们。

2. 执行模式

算法以其执行模式控制的格式返回结果。这些模式在 运行算法 中有详细解释。在 Python 客户端中,statsmutatewrite 模式返回一个包含运行算法的摘要结果的 pandas Series。对于 estimate 过程也是如此。

2.1. 流

stream 模式有点不同,因为此模式不会以任何形式在服务器端保留结果。相反,结果会作为 pandas DataFrame 流回 Python 客户端。计算完成后,结果会立即在客户端侧实例化。以这种方式将结果流回可能会占用大量资源,因为结果可能很大。通常,结果大小将与图的大小处于同一数量级。一些算法会产生特别庞大的结果,例如节点嵌入。

2.2. 训练

train 模式用于将算法产生的机器学习模型放入 GDS 模型目录 中。Python 客户端对处理此类模型有特殊支持,我们在 模型对象 中对此进行了描述。

3. 需要节点匹配的算法

某些算法将(数据库)节点 ID 作为输入。这些节点 ID 必须直接从 Neo4j 数据库中匹配。在 Cypher 中工作时,这是很直接的。在 Python 客户端中,有一个便捷方法 gds.find_node_id 用于根据节点标签和属性键值对检索节点 ID。

例如,要找到图 G 的源节点和目标节点(其中包含城市),以在这些节点上运行 Dijkstra 源-目标最短路径,我们可以执行以下操作

source_id = gds.find_node_id(["City"], {"name": "New York City"})
target_id = gds.find_node_id(["City"], {"name": "Boston"})

result = gds.shortestPath.dijkstra.stream(
    G,
    sourceNode=source_id,
    targetNode=target_id,
    relationshipWeightProperty="cost"
)
assert result["totalCost"][0] == 160

gds.find_node_id 接受节点标签列表和节点属性键值对字典。找到的节点是具有所有指定标签且完全匹配给定所有属性键值对的节点。请注意,每个方法调用必须匹配一个节点,否则将引发错误。

3.1. Cypher 映射

Python 调用

gds.find_node_id(["City", "Capital"], {"settled": 1790, "name": "Washington D.C."})

与以下 Cypher 语句完全等效

MATCH (n:City:Capital {settled: 1790, name: 'Washington D.C.'})
RETURN id(n) AS id

要执行超出 find_node_id() 功能的更高级匹配,我们建议使用 Cypher 的 MATCH(通过 gds.run_cypher)。

执行 拓扑链接预测 的方法略有不同。就像在 GDS 过程 API 中一样,它们不接受图作为参数,而是接受两个节点引用作为位置参数。它们只是返回作为浮点数的预测相似度得分 - 而不是任何类型的 pandas 数据结构。

例如,要运行 Adamic Adar 算法,我们可以使用以下方法

node1 = gds.find_node_id(["City"], {"name": "Boston"})
node2 = gds.find_node_id(["City"], {"name": "Atlantic City"})

score = gds.alpha.linkprediction.adamicAdar(node1, node2)
assert round(score, 2) == 0.62