运行算法

在下面的示例中,我们假设已经实例化了一个名为 gdsGraphDataScience 对象。请在 入门指南 中阅读更多相关信息。

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 Seriesestimate 过程也是如此。

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() 能力的更高级匹配,建议通过 gds.run_cypher 使用 Cypher 的 MATCH

进行 拓扑链接预测 的方法略有不同。正如在 GDS 过程 API 中,它们不接受图作为参数,而是接受两个节点引用作为位置参数。它们仅返回本次预测的相似度得分,类型为 float——并不会返回任何 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