机器学习管道
1. 节点分类
本节概述了如何使用 Python 客户端构建、配置和训练 节点分类管道,以及如何使用训练生成的模型进行预测。
1.1. 管道
要创建新的节点分类管道,可以执行以下调用
pipe = gds.nc_pipe("my-pipe")
其中 pipe 是一个管道对象。
接着,为了构建、配置和训练管道,我们将直接在节点分类管道对象上调用方法。以下是此类对象方法的描述
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
返回管道选定的特征属性列表。 |
|
|
|
如果模型存在于 GDS 管道目录中则返回 |
|
|
|
管道在管道目录中显示的名称。 |
|
|
|
管道的类型。 |
|
|
|
管道创建的时间。 |
|
|
|
返回管道的节点属性步骤。 |
|
|
|
返回为数据集的特征-训练-测试拆分设置的配置。 |
|
|
|
返回训练时模型选择阶段所设置的模型参数空间。 |
|
|
|
返回为自动调优设置的配置。 |
|
|
|
|
1. 范围也可以作为长度为 2 的 |
|||
将上述方法与 Cypher API 的过程进行比较时,有两个主要区别:
-
由于 Python 方法是在管道对象上调用的,因此在调用它们时无需提供名称。
-
Cypher 调用中的配置参数在 Python 方法调用中由命名关键字参数表示。
请参阅 节点分类 Cypher 文档,了解这些方法期望的输入类型。
1.1.1. 示例
下面是一个关于如何配置和训练一个基础节点分类管道的小示例。注意,我们没有显式配置拆分,而是使用了默认值。
为了演示这一点,我们引入了一个小型人员图
gds.run_cypher(
"""
CREATE
(a:Person {name: "Bob", fraudster: 0}),
(b:Person {name: "Alice", fraudster: 0}),
(c:Person {name: "Eve", fraudster: 1}),
(d:Person {name: "Chad", fraudster: 1}),
(e:Person {name: "Dan", fraudster: 0}),
(f:UnknownPerson {name: "Judy"}),
(a)-[:KNOWS]->(b),
(a)-[:KNOWS]->(c),
(a)-[:KNOWS]->(d),
(b)-[:KNOWS]->(d),
(c)-[:KNOWS]->(d),
(c)-[:KNOWS]->(e),
(d)-[:KNOWS]->(e),
(d)-[:KNOWS]->(f),
(e)-[:KNOWS]->(f)
"""
)
G, project_result = gds.graph.project("person_graph", {"Person": {"properties": ["fraudster"]}}, "KNOWS")
assert G.node_labels() == ["Person"]
pipe, _ = gds.beta.pipeline.nodeClassification.create("my-pipe")
# Add Degree centrality as a property step producing "rank" node properties
pipe.addNodeProperty("degree", mutateProperty="rank")
# Select our "rank" property as a feature for the model training
pipe.selectFeatures("rank")
# Verify that the features to be used in model training are what we expect
feature_properties = pipe.feature_properties()
assert len(feature_properties) == 1
assert feature_properties[0]["feature"] == "rank"
# Configure the model training to do cross-validation over logistic regression
pipe.addLogisticRegression(tolerance=(0.01, 0.1))
pipe.addLogisticRegression(penalty=1.0)
# Train the pipeline targeting node property "class" as label and "ACCURACY" as only metric
fraud_model, train_result = pipe.train(
G,
modelName="fraud-model",
targetProperty="fraudster",
metrics=["ACCURACY"],
randomSeed=111
)
assert train_result["trainMillis"] >= 0
一个在 GDS 模型目录 中称为 "fraud-model" 的模型被生成。在下一节中,我们将介绍如何使用该模型进行预测。
1.2. 模型
如上一节所示,节点分类模型是在训练节点分类管道时创建的。除了继承所有 模型对象 的通用方法外,节点分类模型还具有以下方法
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
用于训练分类模型的类别列表。 |
|
|
|
用作输入模型特征的节点属性。 |
|
|
|
管道在训练前用于计算节点属性的算法列表。 |
|
|
|
训练时指定的指标值。 |
|
|
|
在验证集中表现最好的训练方法参数。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
可以注意到,这些预测方法确实与 对应的 Cypher 方法 非常相似。三个主要区别在于:
1.2.1. 示例(续)
我们现在继续 上面的示例,使用我们在那里训练的节点分类模型 trained_pipe_model。
# Make sure we indeed obtained an accuracy score
metrics = fraud_model.metrics()
assert "ACCURACY" in metrics
H, project_result = gds.graph.project("full_person_graph", ["Person", "UnknownPerson"], "KNOWS")
# Predict on `H` and stream the results with a specific concurrency of 2
predictions = fraud_model.predict_stream(H, concurrency=2)
assert len(predictions) == H.node_count()
2. 链接预测
本节概述了如何使用 Python 客户端构建、配置和训练 链接预测管道,以及如何使用训练产生的模型进行预测。
2.1. 管道
要创建新的链接预测管道,可以执行以下调用
pipe = gds.lp_pipe("my-pipe")
其中 pipe 是一个管道对象。
接着,为了构建、配置和训练管道,我们将直接在链接预测管道对象上调用方法。以下是此类对象方法的描述
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
返回管道选定的特征步骤列表。 |
|
|
|
如果模型存在于 GDS 管道目录中则返回 |
|
|
|
管道在管道目录中显示的名称。 |
|
|
|
管道的类型。 |
|
|
|
管道创建的时间。 |
|
|
|
返回管道的节点属性步骤。 |
|
|
|
返回为数据集的特征-训练-测试拆分设置的配置。 |
|
|
|
返回训练时模型选择阶段所设置的模型参数空间。 |
|
|
|
返回为自动调优设置的配置。 |
|
|
|
|
2. 范围也可以作为长度为 2 的 |
|||
将上述方法与 Cypher API 的过程进行比较时,有两个主要区别:
-
由于 Python 方法是在管道对象上调用的,因此在调用它们时无需提供名称。
-
Cypher 调用中的配置参数在 Python 方法调用中由命名关键字参数表示。
请参阅 链接预测 Cypher 文档,了解这些方法期望的输入类型。
2.1.1. 示例
下面是一个关于如何配置和训练一个基础链接预测管道的小示例。注意,我们没有显式配置训练参数,而是使用了默认值。
为了演示这一点,我们引入了一个小型人员图
gds.run_cypher(
"""
CREATE
(a:Person {name: "Bob"}),
(b:Person {name: "Alice"}),
(c:Person {name: "Eve"}),
(d:Person {name: "Chad"}),
(e:Person {name: "Dan"}),
(f:Person {name: "Judy"}),
(a)-[:KNOWS]->(b),
(a)-[:KNOWS]->(c),
(a)-[:KNOWS]->(d),
(b)-[:KNOWS]->(d),
(c)-[:KNOWS]->(d),
(c)-[:KNOWS]->(e),
(d)-[:KNOWS]->(e),
(d)-[:KNOWS]->(f),
(e)-[:KNOWS]->(f)
"""
)
G, project_result = gds.graph.project("person_graph", "Person", {"KNOWS": {"orientation":"UNDIRECTED"}})
assert G.relationship_types() == ["KNOWS"]
pipe, _ = gds.beta.pipeline.linkPrediction.create("lp-pipe")
# Add FastRP as a property step producing "embedding" node properties
pipe.addNodeProperty("fastRP", embeddingDimension=128, mutateProperty="embedding", randomSeed=1337)
# Combine our "embedding" node properties with Hadamard to create link features for training
pipe.addFeature("hadamard", nodeProperties=["embedding"])
# Verify that the features to be used in model training are what we expect
steps = pipe.feature_steps()
assert len(steps) == 1
assert steps["name"][0] == "HADAMARD"
# Specify the fractions we want for our dataset split
pipe.configureSplit(trainFraction=0.2, testFraction=0.2, validationFolds=2)
# Add a random forest model with tuning over `maxDepth`
pipe.addRandomForest(maxDepth=(2, 20))
# Train the pipeline and produce a model named "friend-recommender"
friend_recommender, train_result = pipe.train(
G,
modelName="friend-recommender",
targetRelationshipType="KNOWS",
randomSeed=42
)
assert train_result["trainMillis"] >= 0
一个在 GDS 模型目录 中称为 "my-model" 的模型被生成。在下一节中,我们将介绍如何使用该模型进行预测。
2.2. 模型
如上一节所示,链接预测模型是在训练链接预测管道时创建的。除了继承所有 模型对象 的通用方法外,链接预测模型还具有以下方法
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
用于训练模型的输入链接特征。 |
|
|
|
管道在训练前用于计算节点属性的算法列表。 |
|
|
|
训练时指定的指标值。 |
|
|
|
在验证集中表现最好的训练方法参数。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
可以注意到,这些预测方法确实与 对应的 Cypher 方法 非常相似。三个主要区别在于:
2.2.1. 示例(续)
我们现在继续 上面的示例,使用我们在那里训练的链接预测模型 trained_pipe_model。
# Make sure we indeed obtained an AUCPR score
metrics = friend_recommender.metrics()
assert "AUCPR" in metrics
# Predict on `G` and mutate it with the relationship predictions
mutate_result = friend_recommender.predict_mutate(G, topN=5, mutateRelationshipType="PRED_REL")
assert mutate_result["relationshipsWritten"] == 5 * 2 # Undirected relationships
3. 节点回归
本节概述了如何使用 Python 客户端构建、配置和训练 节点回归管道,以及如何使用训练产生的模型进行预测。
3.1. 管道
要创建新的节点回归管道,可以执行以下调用
pipe = gds.nr_pipe("my-pipe")
其中 pipe 是一个管道对象。
接着,为了构建、配置和训练管道,我们将直接在节点回归管道对象上调用方法。以下是此类对象方法的描述
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
返回管道选定的特征属性列表。 |
|
|
|
如果模型存在于 GDS 管道目录中则返回 |
|
|
|
管道在管道目录中显示的名称。 |
|
|
|
管道的类型。 |
|
|
|
管道创建的时间。 |
|
|
|
返回管道的节点属性步骤。 |
|
|
|
返回为数据集的特征-训练-测试拆分设置的配置。 |
|
|
|
返回训练时模型选择阶段所设置的模型参数空间。 |
|
|
|
返回为自动调优设置的配置。 |
|
|
|
|
3. 范围也可以作为长度为 2 的 |
|||
将上述方法与 Cypher API 的过程进行比较时,有两个主要区别:
-
由于 Python 方法是在管道对象上调用的,因此在调用它们时无需提供名称。
-
Cypher 调用中的配置参数在 Python 方法调用中由命名关键字参数表示。
请参阅 节点回归 Cypher 文档,了解这些方法期望的输入类型。
3.1.1. 示例
下面是一个关于如何配置和训练一个基础节点回归管道的小示例。注意,我们没有显式配置拆分,而是使用了默认值。
为了演示这一点,我们引入了一个小型人员图
gds.run_cypher(
"""
CREATE
(a:Person {name: "Bob", age: 22}),
(b:Person {name: "Alice", age: 5}),
(c:Person {name: "Eve", age: 53}),
(d:Person {name: "Chad", age: 44}),
(e:Person {name: "Dan", age: 60}),
(f:UnknownPerson {name: "Judy"}),
(a)-[:KNOWS]->(b),
(a)-[:KNOWS]->(c),
(a)-[:KNOWS]->(d),
(b)-[:KNOWS]->(d),
(c)-[:KNOWS]->(d),
(c)-[:KNOWS]->(e),
(d)-[:KNOWS]->(e),
(d)-[:KNOWS]->(f),
(e)-[:KNOWS]->(f)
"""
)
G, project_result = gds.graph.project("person_graph", {"Person": {"properties": ["age"]}}, "KNOWS")
assert G.relationship_types() == ["KNOWS"]
pipe, _ = gds.alpha.pipeline.nodeRegression.create("nr-pipe")
# Add Degree centrality as a property step producing "rank" node properties
pipe.addNodeProperty("degree", mutateProperty="rank")
# Select our "rank" property as a feature for the model training
pipe.selectFeatures("rank")
# Verify that the features to be used in model training are what we expect
feature_properties = pipe.feature_properties()
assert len(feature_properties) == 1
assert feature_properties[0]["feature"] == "rank"
# Configure the model training to do cross-validation over linear regression
pipe.addLinearRegression(tolerance=(0.01, 0.1))
pipe.addLinearRegression(penalty=1.0)
# Train the pipeline targeting node property "age" as label and "MEAN_SQUARED_ERROR" as only metric
age_predictor, train_result = pipe.train(
G,
modelName="age-predictor",
targetProperty="age",
metrics=["MEAN_SQUARED_ERROR"],
randomSeed=42
)
assert train_result["trainMillis"] >= 0
一个在 GDS 模型目录 中称为 "my-model" 的模型被生成。在下一节中,我们将介绍如何使用该模型进行预测。
3.2. 模型
如上一节所示,节点回归模型是在训练节点回归管道时创建的。除了继承所有 模型对象 的通用方法外,节点回归模型还具有以下方法
| 名称 | 参数 | 返回类型 | 描述 |
|---|---|---|---|
|
|
|
返回用作输入模型特征的节点属性。 |
|
|
|
管道在训练前用于计算节点属性的算法列表。 |
|
|
|
训练时指定的指标值。 |
|
|
|
在验证集中表现最好的训练方法参数。 |
|
|
|
|
|
|
|
可以注意到,这些预测方法确实与 对应的 Cypher 方法 非常相似。三个主要区别在于:
3.2.1. 示例(续)
我们现在继续 上面的示例,使用我们在那里训练的节点回归模型 age_predictor。假设我们有一个想要进行预测的新图 H。
# Make sure we indeed obtained an MEAN_SQUARED_ERROR score
metrics = age_predictor.metrics()
assert "MEAN_SQUARED_ERROR" in metrics
H, project_result = gds.graph.project("full_person_graph", ["Person", "UnknownPerson"], "KNOWS")
# Predict on `H` and stream the results with a specific concurrency of 2
predictions = age_predictor.predict_stream(H, concurrency=2)
assert len(predictions) == H.node_count()
4. 管道目录
使用管道对象的主要方式是训练模型。此外,管道对象还可以用作 GDS 管道目录操作 的输入。例如,假设我们有一个管道对象 pipe,我们可以
exists_result = gds.pipeline.exists(pipe.name())
if exists_result["exists"]:
gds.pipeline.drop(pipe) # same as pipe.drop()
可以通过调用 get 方法并传入其名称来检索已经在管道目录中创建的管道对象。例如,我们可以从目录中列出所有管道,并使用找到的第一个管道名称来获取该管道的管道对象,这将是我们之前在 示例中 创建的 NodeClassification 管道。
list_result = gds.pipeline.list()
first_pipeline_name = list_result["pipelineName"][0]
pipe = gds.pipeline.get(first_pipeline_name)
assert pipe.name() == "my-pipe"