

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

# 步骤 2：创建运行时脚本
<a name="step2"></a>

![创建运行时脚本。](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/ml-production-ready-pipelines/images/step2.png)


 在此步骤中，您将在第 1 步中开发的模型及其相关辅助代码集成到机器学习平台中，以便生产就绪的训练和推理。具体而言，这涉及开发运行时脚本，以便可以将模型整合到 SageMaker 人工智能中。这些独立的 Python 脚本包括预定义的 SageMaker AI 回调函数和环境变量。它们在托管在亚马逊弹性计算云 (Amazon EC2) 实例上的 A SageMaker I 容器中运行。[Amazon SageMaker AI Python SDK 文档](https://sagemaker.readthedocs.io/en/stable/index.html)提供了有关这些回调和辅助设置如何协同工作以进行训练和推理的详细信息。以下各节根据我们与 AWS 客户合作的经验，提供了有关开发机器学习运行时脚本的其他建议。

## 使用处理作业
<a name="proc-job"></a>

SageMaker AI 为执行批处理模式模型推断提供了两个选项。您可以使用 A SageMaker I *处理作业*或*批处理转换作业*。每种选择都有优势和劣势。

处理作业由在 SageMaker AI 容器内运行的 Python 文件组成。处理作业由您在 Python 文件中输入的任何逻辑组成。它具有以下优点：
+ 当你了解训练作业的基本逻辑时，处理作业便易于设置且易于理解。它们与训练作业共享相同的抽象概念（例如，调整实例数量和数据分布）。
+ 数据科学家和机器学习工程师可以完全控制数据操作选项。
+ 除了熟悉的 read/write 功能外，数据科学家不必管理任何 I/O 组件逻辑。
+ 在非 SageMaker AI 环境中运行文件要容易一些，这有助于快速开发和本地测试。
+ 如果出现错误，处理作业会在脚本失败时立即失败，并且不会意外出现等待重试的情况。

另一方面，批量转换作业是 A SageMaker I 端点概念的扩展。在运行时，这些作业会导入回调函数，然后由 I/O 回调函数处理读取数据、加载模型和进行预测。批量转换作业具有以下优点：
+ 他们使用的数据分布抽象与训练作业使用的抽象不同。
+ 他们在批量推理和实时推理中使用相同的核心文件和函数结构，非常方便。
+ 他们具有内置的、基于重试的容错机制。例如，如果一批记录发生错误，则在作业因失败而终止之前，它将多次重试。

由于其透明性、在多种环境中的易用性以及与训练作业共享的抽象性，我们决定在本指南介绍的参考架构中使用处理作业而不是批量转换作业。

在云部署 Python 运行时脚本之前，应在本地运行它们。具体而言，我们建议您在构建 Python 脚本和执行单元测试时使用主保护条款。

## 使用主保护条款
<a name="main-guard"></a>

使用主保护条款来支持模块导入和运行 Python 脚本。单独运行 Python 脚本有利于调试和隔离机器学习管道中的问题。我们建议您完成以下步骤：
+ 在 Python 处理文件中使用参数解析器来指定 input/output 文件及其位置。
+ 为每个 Python 文件提供主要指南和测试函数。
+ 测试 Python 文件后，无论你使用的是 AWS Step Functions 模型还是 SageMaker AI 处理作业，都要将其合并到机器学习管道的不同阶段。
+ 在脚本的关键部分使用 **Assert** 语句来以便测试和调试。例如，您可以使用 **Assert** 语句以确保加载后数据集要素的数量保持一致。

## 单元测试
<a name="unit-test"></a>

在机器学习管道开发过程中，为管道编写的运行时脚本的单元测试是一项经常被忽视的重要任务。这是因为机器学习和数据科学是相对较新的领域，并且在采用单元测试等成熟的软件工程实践方面进展缓慢。由于机器学习管道将在生产环境中使用，因此在将机器学习模型应用于实际应用程序之前，必须测试管道代码。

对运行时脚本进行单元测试还为机器学习模型提供了以下独特优势：
+ 它可以防止意外的数据转换。大多数机器学习管道都涉及许多数据转换，因此这些转换能否按预期执行至关重要。
+ 它验证代码的可重复性。代码中的任何随机性都可以通过使用不同用例进行单元测试来检测。
+ 它加强了代码的模块化。单元测试通常与测试覆盖率衡量标准相关联，测试覆盖率衡量标准是特定测试套件（测试用例集合）运行程序源代码的程度。为了实现较高的测试覆盖率，开发人员对代码进行了模块化，因为如果不将其分解为函数或类，就很难为大量代码编写单元测试。
+ 它可以防止将低质量的代码或错误引入生产中。

我们建议您使用成熟的单元测试框架（例如 [pytest](https://docs.pytest.org/en/stable/)）来编写单元测试用例，因为这样可以更轻松地在框架内管理大量的单元测试。

**重要**  
单元测试不能保证所有极端案例都经过测试，但它可以帮助您在部署模型之前主动避免错误。我们建议您在部署后也对模型进行监控，以确保卓越运营。