

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Neptune ML 中开发自定义模型
<a name="machine-learning-custom-model-development"></a>

开始开发自定义模型的一个好方法是按照 [Neptune ML 工具包示例](https://github.com/awslabs/neptuneml-toolkit/tree/main/examples/custom-models/introduction)来构造和编写训练模块。Neptune ML 工具包还在 [modelzoo](https://github.com/awslabs/neptuneml-toolkit/tree/main/src/neptuneml_toolkit/modelzoo) 中实现了模块化图形 ML 模型组件，您可以将其堆叠并用于创建自定义模型。

此外，该工具包还提供实用程序函数，帮助您在模型训练和模型转换期间生成必要的构件。您可以在您的自定义实现中导入这个 Python 软件包。该工具包中提供的任何功能或模块也可在 Neptune ML 训练环境中使用。

如果您的 Python 模块具有其它外部依赖项，则可以通过在模块的目录中创建 `requirements.txt` 文件来包含这些额外的依赖项。然后，将在运行训练脚本之前安装 `requirements.txt` 文件中列出的软件包。

实现您的自定义模型的 Python 模块至少需要包含以下内容：
+ 训练脚本入口点
+ 转换脚本入口点
+ 一个 `model-hpo-configuration.json` 文件

## 在 Neptune ML 中开发自定义模型训练脚本
<a name="machine-learning-custom-model-training-script"></a>

自定义模型训练脚本应该是可执行的 Python 脚本，就像 Neptune ML 工具包的 [https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py) 示例一样。它必须接受超参数名称和值作为命令行参数。在模型训练期间，超参数名称是从 `model-hpo-configuration.json` 文件中获取的。如果超参数是可调整的，则超参数值在有效的超参数范围内，或者，如果超参数值不可调整，则采用默认的超参数值。

训练脚本使用如下语法在 SageMaker AI 训练实例上运行：

```
python3 (script entry point) --(1st parameter) (1st value) --(2nd parameter) (2nd value) (...)
```

对于所有任务，除了您指定的超参数外，Neptune ML AutoTrainer 还会向您的训练脚本发送几个必需的参数，并且您的脚本必须能够处理这些额外参数才能正常工作。

这些额外的必需参数因任务而稍有差异：

**对于节点分类或节点回归**
+ **`task`** – Neptune ML 在内部使用的任务类型。对于节点分类，这是 `node_class`；对于节点回归，这是 `node_regression`。
+ **`model`** – Neptune ML 在内部使用的模型名称，在本例中为 `custom`。
+ **`name`** – Neptune ML 在内部使用的任务名称，在本例中，`node_class-custom` 用于节点分类，`node_regression-custom` 用于节点回归。
+ **`target_ntype`** – 用于分类或回归的节点类型的名称。
+ **`property`** – 用于分类或回归的节点属性的名称。

**对于链接预测**
+ **`task`** – Neptune ML 在内部使用的任务类型。对于链接预测，这是 `link_predict`。
+ **`model`** – Neptune ML 在内部使用的模型名称，在本例中为 `custom`。
+ **`name`** – Neptune ML 在内部使用的任务名称，在本例中为 `link_predict-custom`。

**对于边缘分类或边缘回归**
+ **`task`** – Neptune ML 在内部使用的任务类型。对于边缘分类，这是 `edge_class`；对于边缘回归，这是 `edge_regression`。
+ **`model`** – Neptune ML 在内部使用的模型名称，在本例中为 `custom`。
+ **`name`** – Neptune ML 在内部使用的任务名称，在本例中，`edge_class-custom` 用于边缘分类，`edge_regression-custom` 用于边缘回归。
+ **`target_etype`** – 用于分类或回归的边缘类型的名称。
+ **`property`** – 用于分类或回归的边缘属性的名称。

您的脚本应保存模型参数以及训练结束时所需的任何其它构件。

您可以使用 Neptune ML 工具包实用程序函数来确定处理后的图形数据的位置、模型参数应保存的位置以及训练实例上有哪些 GPU 设备可用。有关如何使用这些实用程序函数的示例，请参阅 [train.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/train.py) 示例训练脚本。

## 在 Neptune ML 中开发自定义模型转换脚本
<a name="machine-learning-custom-model-transform-script"></a>

需要一个转换脚本来利用 Neptune ML [增量工作流程](machine-learning-overview-evolving-data-incremental.md#machine-learning-overview-incremental)在不断演变的图形上进行模型推理，而无需重新训练模型。即使模型部署所需的所有构件都是由训练脚本生成的，但如果您想在不重新训练模型的情况下生成更新的模型，您仍然需要提供转换脚本。

**注意**  
自定义模型目前不支持[实时归纳推理](machine-learning-overview-evolving-data.md#inductive-vs-transductive-inference)。

自定义模型转换脚本应该是可执行的 Python 脚本，就像 Neptune ML 工具包的 [transform.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/transform.py) 示例脚本一样。由于此脚本是在模型训练期间调用的，没有命令行参数，因此该脚本接受的任何命令行参数都必须具有默认值。

该脚本在 SageMaker AI 训练实例上运行，其语法如下所示：

```
python3 (your transform script entry point)
```

您的转换脚本需要各种信息，例如：
+ 处理的图形数据的位置。
+ 保存模型参数的位置以及应保存新模型构件的位置。
+ 实例上可用的设备。
+ 生成了最佳模型的超参数。

这些输入是使用脚本可以调用的 Neptune ML 实用程序函数获得的。有关如何执行此操作的示例，请参阅该工具包的示例 [transform.py](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/transform.py) 脚本。

该脚本应保存节点嵌入、节点 ID 映射以及每个任务的模型部署所需的任何其它构件。有关不同 Neptune ML 任务所需的模型构件的更多信息，请参阅[模型构件文档](machine-learning-model-artifacts.md)。

## Neptune ML 中的自定义 `model-hpo-configuration.json` 文件
<a name="machine-learning-custom-model-hpo-configuration-file"></a>

`model-hpo-configuration.json` 文件为您的自定义模型定义超参数。它的[格式](machine-learning-customizing-hyperparams.md)与 Neptune ML 内置模型中使用的 `model-hpo-configuration.json` 文件格式相同，并且优先于由 Neptune ML 自动生成并上传到处理过的数据所在位置的版本。

向模型添加新的超参数时，还必须在此文件中为该超参数添加一个条目，以便将超参数传递给您的训练脚本。

如果您希望超参数可调整，则必须为其提供一个范围，并将其设置为 `tier-1`、`tier-2` 或 `tier-3` 参数。如果配置的训练任务总数允许在其层中调整超参数，则将调整超参数。对于不可调整的参数，必须提供默认值并将超参数添加到文件的 `fixed-param` 部分。有关如何执行此操作的示例，请参阅工具包的[示例 `model-hpo-configuration.json` 文件](https://github.com/awslabs/neptuneml-toolkit/blob/main/examples/custom-models/introduction/movie-lens-rgcn/node-class/src/model-hpo-configuration.json)。

您还必须提供指标定义，SageMaker AI 超参数优化任务将使用该定义来评估经过训练的候选模型。为此，您需要向 `model-hpo-configuration.json` 文件中添加一个 `eval_metric` JSON 对象，如下所示：

```
"eval_metric": {
  "tuning_objective": {
      "MetricName": "(metric_name)",
      "Type": "Maximize"
  },
  "metric_definitions": [
    {
      "Name": "(metric_name)",
      "Regex": "(metric regular expression)"
    }
  ]
},
```

`eval_metric` 对象中的 `metric_definitions` 数组列出了您希望 SageMaker AI 从训练实例中提取的每个指标的指标定义对象。每个指标定义对象都有一个 `Name` 键，它允许您为指标提供名称（例如“accuracy”、“f1”等）。`Regex` 键允许您提供与该特定指标在训练日志中的输出方式相匹配的正则表达式字符串。有关如何定义指标的更多详细信息，请参阅 [SageMaker AI 超参数调整页面](https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning-define-metrics.html)。

然后，`eval_metric` 中的 `tuning_objective` 对象允许您指定应将 `metric_definitions` 中的哪些指标用作评估指标（作为超参数优化的目标指标）。`MetricName` 的值必须与 `metric_definitions` 中定义之一的 `Name` 的值相匹配。`Type` 的值应为“Maximize”或“Minimize”，具体取决于该指标应解释为越大越好（如“accuracy”），还是应解释为越小越好（例如“mean-squared-error”）。

`model-hpo-configuration.json` 文件的此部分中的错误可能导致 Neptune ML 模型训练 API 作业失败，因为 SageMaker AI 超参数调整作业将无法选择最佳模型。

## 在 Neptune ML 中对您的自定义模型实现进行本地测试
<a name="machine-learning-custom-model-testing"></a>

您可以使用 Neptune ML 工具包 Conda 环境在本地运行代码，以便测试和验证您的模型。如果您在 Neptune 笔记本实例上进行开发，那么这个 Conda 环境将预安装在 Neptune 笔记本实例上。如果您在其它实例上进行开发，则需要按照 Neptune ML 工具包中的[本地设置说明](https://github.com/awslabs/neptuneml-toolkit#local-installation)进行操作。

当您调用[模型训练 API](machine-learning-api-modeltraining.md) 时，Conda 环境可以准确地重现模型的运行环境。所有示例训练脚本和转换脚本都允许您传递命令行 `--local` 标志，以便在本地环境中运行脚本来便于调试。在开发自己的模型时，这是一种很好的做法，因为它允许您以交互方式和迭代方式测试模型实现。在 Neptune ML 生产训练环境中进行模型训练期间，忽略此参数。