

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

# 调整自己的训练容器
<a name="adapt-training-container"></a>

要运行您自己的训练模型，请使用[亚马逊 SageMaker 培训工具包通过亚马逊](https://github.com/aws/sagemaker-training-toolkit) SageMaker 笔记本实例构建 Docker 容器。

## 步骤 1：创建 SageMaker 笔记本实例
<a name="byoc-training-step1"></a>

1. 打开 Amazon A SageMaker I 控制台，网址为[https://console.aws.amazon.com/sagemaker/](https://console.aws.amazon.com/sagemaker/)。

1. 在左侧导航窗格中，依次选择**笔记本**、**笔记本实例**和**创建笔记本实例**。

1. 在**创建笔记本实例**页面上提供以下信息：

   1. 对于 **Notebook instance name (笔记本实例名称)**，输入 **RunScriptNotebookInstance**。

   1. 对于**笔记本实例类型**，选择 **ml.t2.medium**。

   1. 展开**权限和加密**部分，执行以下操作：

      1. 对于 **IAM 角色**，选择**创建新角色**。这将打开一个新窗口。

      1. 在**创建 IAM 角色**页面上，选择**特定的 S3 存储桶**，指定一个名为 **sagemaker-run-script** 的 S3 存储桶，然后选择**创建角色**。

         SageMaker AI 创建了一个名为的 IAM 角色`AmazonSageMaker-ExecutionRole-YYYYMMDDTHHmmSS`。例如 `AmazonSageMaker-ExecutionRole-20190429T110788`。请注意，执行角色的命名约定会使用创建角色的日期和时间，由 `T` 分隔。

   1. 对于**根访问**，选择**已启用**。

   1. 选择**创建笔记本实例**。

1. 在**笔记本实例**页面上，**状态**是**待处理**。Amazon A SageMaker I 可能需要几分钟才能启动机器学习计算实例（在本例中为启动笔记本实例）并向其连接 ML 存储卷。笔记本实例有一个预配置的 Jupyter 笔记本服务器和一组 Anaconda 库。有关更多信息，请参阅 [ CreateNotebookInstance](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateNotebookInstance.html)。

   

1. 单击您刚刚创建的笔记本的**名称**。这将打开一个新页面。

1.  在**权限和加密**部分，复制 **IAM 角色 ARN 编号**，然后将其粘贴到记事本文件中以临时保存。稍后，您将使用此 IAM 角色 ARN 编号，在笔记本实例中配置本地训练估算器。**The IAM role ARN number (IAM 角色 ARN 编号)** 如下所示：`'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'`

1. 笔记本实例的状态更改为后 **InService**，选择**打开 JupyterLab**。

## 步骤 2：创建并上传 Dockerfile 和 Python 训练脚本
<a name="byoc-training-step2"></a>

1.  JupyterLab 打开后，在您的主目录中创建一个新文件夹 JupyterLab。在左上角，选择**新建文件夹**图标，然后输入文件夹名称 `docker_test_folder`。

1. 在 `docker_test_folder` 目录中创建 `Dockerfile` 文本文件。

   1. 选择左上角的**新启动程序**图标 (\$1)。

   1. 在右窗格的**其他**部分下，选择**文本文件**。

   1. 将以下 `Dockerfile` 示例代码粘贴到您的文本文件中。

      ```
      #Download an open source TensorFlow Docker image
      FROM tensorflow/tensorflow:latest-gpu-jupyter
      
      # Install sagemaker-training toolkit that contains the common functionality necessary to create a container compatible with SageMaker AI and the Python SDK.
      RUN pip3 install sagemaker-training
      
      # Copies the training code inside the container
      COPY train.py /opt/ml/code/train.py
      
      # Defines train.py as script entrypoint
      ENV SAGEMAKER_PROGRAM train.py
      ```

      Dockerfile 脚本将执行以下任务：
      + `FROM tensorflow/tensorflow:latest-gpu-jupyter`— 下载最新的 TensorFlow Docker 基础镜像。您可以将其替换为要用于构建容器的任何 Docker 基础镜像以及 AWS 预先构建的容器基础镜像。
      + `RUN pip install sagemaker-training`— 安装 [SageMaker AI 训练工具包](https://github.com/aws/sagemaker-training-toolkit)，其中包含创建与 SageMaker AI 兼容的容器所需的常用功能。
      + `COPY train.py /opt/ml/code/train.py`— 将脚本复制到 SageMaker AI 预期的容器内位置。该脚本必须位于此文件夹中。
      + `ENV SAGEMAKER_PROGRAM train.py` – 以您的训练脚本 `train.py` 作为入口点脚本，复制到容器的 `/opt/ml/code` 文件夹中。这是在您构建自己的容器时唯一必须指定的环境变量。

   1.  在左侧目录导航窗格中，文本文件可能会自动命名为 `untitled.txt`。要重命名文件，请右键单击该文件，然后选择**重命名**，将文件重命名为没有 `.txt` 扩展名的 `Dockerfile`，然后按 `Ctrl+s` 或 `Command+s` 以保存文件。

1. 将训练脚本 `train.py` 上传到 `docker_test_folder`。对于本练习，您可以使用以下示例脚本创建在 [MNIST 数据集](https://en.wikipedia.org/wiki/MNIST_database)上训练的模型来读取手写数字。

   ```
   import tensorflow as tf
   import os
   
   mnist = tf.keras.datasets.mnist
   
   (x_train, y_train), (x_test, y_test) = mnist.load_data()
   x_train, x_test = x_train / 255.0, x_test / 255.0
   
   model = tf.keras.models.Sequential([
   tf.keras.layers.Flatten(input_shape=(28, 28)),
   tf.keras.layers.Dense(128, activation='relu'),
   tf.keras.layers.Dropout(0.2),
   tf.keras.layers.Dense(10, activation='softmax')
   ])
   
   model.compile(optimizer='adam',
   loss='sparse_categorical_crossentropy',
   metrics=['accuracy'])
   
   model.fit(x_train, y_train, epochs=1)
   model_save_dir = f"{os.environ.get('SM_MODEL_DIR')}/1"
   
   model.evaluate(x_test, y_test)
   tf.saved_model.save(model, model_save_dir)
   ```

## 步骤 3：构建容器
<a name="byoc-training-step3"></a>

1. 在 JupyterLab 主目录中，打开 Jupyter 笔记本。要打开新笔记本，请选择**新启动**图标，然后在**笔记本**部分选择 **conda\$1tensorflow2**。

1. 在第一个笔记本单元格中运行以下命令，以便更改到 `docker_test_folder` 目录：

   ```
   cd ~/SageMaker/docker_test_folder
   ```

   这会将您返回到当前目录，如下所示。

   ```
   ! pwd
   ```

   `output: /home/ec2-user/SageMaker/docker_test_folder`

1. 要构建 Docker 容器，请运行以下 Docker 构建命令，包括末尾句点后的空格：

   ```
   ! docker build -t tf-custom-container-test .
   ```

   Docker 构建命令必须从您创建的 Docker 目录运行，在此例中为 `docker_test_folder`。
**注意**  
如果您收到以下错误消息，提示 Docker 找不到 Dockerfile，请确保 Dockerfile 的名称正确并已保存到目录中。  

   ```
   unable to prepare context: unable to evaluate symlinks in Dockerfile path: 
   lstat /home/ec2-user/SageMaker/docker/Dockerfile: no such file or directory
   ```
请记住，`docker` 在当前目录中查找名为 `Dockerfile` 的文件，没有任何扩展名。如果您将其改为其他名称，可以使用 `-f` 标记手动传入文件名。例如，如果您将 Dockerfile 命名为 `Dockerfile-text.txt`，请运行以下命令：  

   ```
   ! docker build -t tf-custom-container-test -f Dockerfile-text.txt .
   ```

## 步骤 4：测试容器
<a name="byoc-training-step4"></a>

1. 要在笔记本实例中本地测试容器，请打开 Jupyter 笔记本。选择**新启动程序**，然后在**笔记本**部分选择 **conda\$1tensorflow2** 的最新版本。

1. 将以下示例脚本粘贴到笔记本代码单元中以配置 A SageMaker I 估算器。

   ```
   import sagemaker
   from sagemaker.estimator import Estimator
   
   estimator = Estimator(image_uri='tf-custom-container-test',
                         role=sagemaker.get_execution_role(),
                         instance_count=1,
                         instance_type='local')
   
   estimator.fit()
   ```

   在前面的代码示例中，指定`role`参数以自动检索`sagemaker.get_execution_role()`为 SageMaker AI 会话设置的角色。您也可以将其替换为在配置笔记本实例时使用的 **IAM 角色 ARN 编号**的字符串值。ARN 应如下所示：`'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'`。

1. 运行代码单元。该测试输出训练环境配置、用于环境变量的值、数据源以及训练期间获得的损失和准确率。

## 步骤 5：将容器推送至 Amazon Elastic Container Registry (Amazon ECR)
<a name="byoc-training-step5"></a>

1. 成功运行本地模式测试后，您可以将 Docker 容器推送到 [Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) 并用它来运行训练作业。如果您想使用私有 Docker 注册表而不是 Amazon ECR，请参阅[将您的训练容器推送到私有注册表](https://docs.aws.amazon.com/sagemaker/latest/dg/docker-containers-adapt-your-own-private-registry.html)。

   在笔记本单元格中运行以下命令行。

   ```
   %%sh
   
   # Specify an algorithm name
   algorithm_name=tf-custom-container-test
   
   account=$(aws sts get-caller-identity --query Account --output text)
   
   # Get the region defined in the current configuration (default to us-west-2 if none defined)
   region=$(aws configure get region)
   region=${region:-us-west-2}
   
   fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest"
   
   # If the repository doesn't exist in ECR, create it.
   
   aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1
   if [ $? -ne 0 ]
   then
   aws ecr create-repository --repository-name "${algorithm_name}" > /dev/null
   fi
   
   # Get the login command from ECR and execute it directly
   
   aws ecr get-login-password --region ${region}|docker login --username AWS --password-stdin ${fullname}
   
   # Build the docker image locally with the image name and then push it to ECR
   # with the full name.
   
   docker build -t ${algorithm_name} .
   docker tag ${algorithm_name} ${fullname}
   
   docker push ${fullname}
   ```
**注意**  
此 bash shell 脚本可能会引发权限问题，类似于以下错误消息：  

   ```
   "denied: User: [ARN] is not authorized to perform: ecr:InitiateLayerUpload on resource:
   arn:aws:ecr:us-east-1:[id]:repository/tf-custom-container-test"
   ```
如果发生此错误，您需要将 A **mazon EC2 ContainerRegistryFullAccess** 策略附加到您的 IAM 角色。前往 [IAM 控制台](https://console.aws.amazon.com/iam/home)，从左侧导航窗格中选择 “**角色**”，查找 IAMrole 您用于笔记本实例的 “角色”。在 “**权限**” 选项卡下，选择 “**附加政策**” 按钮，然后搜索 **Amazon EC2 ContainerRegistryFullAccess** 政策。选中策略的复选框，选择**附加策略**以完成操作。

1. 在 Studio 笔记本单元格中运行以下代码，调用您的训练容器的 Amazon ECR 映像。

   ```
   import boto3
   
   account_id = boto3.client('sts').get_caller_identity().get('Account')
   ecr_repository = 'tf-custom-container-test'
   tag = ':latest'
   
   region = boto3.session.Session().region_name
   
   uri_suffix = 'amazonaws.com'
   if region in ['cn-north-1', 'cn-northwest-1']:
       uri_suffix = 'amazonaws.com.cn'
   
   byoc_image_uri = '{}.dkr.ecr.{}.{}/{}'.format(account_id, region, uri_suffix, ecr_repository + tag)
   
   byoc_image_uri
   # This should return something like
   # 111122223333.dkr.ecr.us-east-2.amazonaws.com/sagemaker-byoc-test:latest
   ```

1. 使用从上一步中`ecr_image`检索到的来配置 A SageMaker I 估算器对象。以下代码示例使用配置 A SageMaker I 估算器，`byoc_image_uri`并在 Amazon EC2 实例上启动训练作业。

------
#### [ SageMaker Python SDK v1 ]

   ```
   import sagemaker
   from sagemaker import get_execution_role
   from sagemaker.estimator import Estimator
   
   estimator = Estimator(image_uri=byoc_image_uri,
                         role=get_execution_role(),
                         base_job_name='tf-custom-container-test-job',
                         instance_count=1,
                         instance_type='ml.g4dn.xlarge')
   
   #train your model
   estimator.fit()
   ```

------
#### [ SageMaker Python SDK v2 ]

   ```
   import sagemaker
   from sagemaker import get_execution_role
   from sagemaker.estimator import Estimator
   
   estimator = Estimator(image_uri=byoc_image_uri,
                         role=get_execution_role(),
                         base_job_name='tf-custom-container-test-job',
                         instance_count=1,
                         instance_type='ml.g4dn.xlarge')
   
   #train your model
   estimator.fit()
   ```

------

1. 如果您要使用自己的容器部署模型，请参阅[调整自己的推理容器](https://docs.aws.amazon.com/sagemaker/latest/dg/adapt-inference-container.html)。您也可以使用可以部署 TensorFlow 模型的 AWS框架容器。要部署示例模型以读取手写数字，请将以下示例脚本输入到您在上一个子步骤中用于训练模型的同一个笔记本中，以获取部署所需的图像 URIs （通用资源标识符），然后部署模型。

   ```
   import boto3
   import sagemaker
   
   #obtain image uris
   from sagemaker import image_uris
   container = image_uris.retrieve(framework='tensorflow',region='us-west-2',version='2.11.0',
                       image_scope='inference',instance_type='ml.g4dn.xlarge')
   
   #create the model entity, endpoint configuration and endpoint
   predictor = estimator.deploy(1,instance_type='ml.g4dn.xlarge',image_uri=container)
   ```

   通过以下代码示例，使用 MNIST 数据集中的手写数字样本测试您的模型。

   ```
   #Retrieve an example test dataset to test
   import numpy as np
   import matplotlib.pyplot as plt
   from keras.datasets import mnist
   
   # Load the MNIST dataset and split it into training and testing sets
   (x_train, y_train), (x_test, y_test) = mnist.load_data()
   # Select a random example from the training set
   example_index = np.random.randint(0, x_train.shape[0])
   example_image = x_train[example_index]
   example_label = y_train[example_index]
   
   # Print the label and show the image
   print(f"Label: {example_label}")
   plt.imshow(example_image, cmap='gray')
   plt.show()
   ```

   将测试手写数字转换为 TensorFlow 可以提取并进行测试预测的形式。

   ```
   from sagemaker.serializers import JSONSerializer
   data = {"instances": example_image.tolist()}
   predictor.serializer=JSONSerializer() #update the predictor to use the JSONSerializer
   predictor.predict(data) #make the prediction
   ```

有关演示如何在本地测试自定义容器并将其推送到 Amazon ECR 映像的完整示例，请参阅[构建自己的 TensorFlow 容器](https://sagemaker-examples.readthedocs.io/en/latest/advanced_functionality/tensorflow_bring_your_own/tensorflow_bring_your_own.html)示例笔记本。

**提示**  
要分析和调试训练作业以监控系统利用率问题（例如 CPU 瓶颈和 GPU 利用率不足）并识别训练问题（例如过度拟合、过度训练、张量爆炸和梯度消失），请使用 Amazon Debugger。 SageMaker 有关更多信息，请参阅 [使用 Debugger 和自定义训练容器](debugger-bring-your-own-container.md)。

## 步骤 6：清理资源
<a name="byoc-training-step6"></a>

**在完成“开始使用”示例后清理资源**

1. 打开 [SageMaker AI 控制台](https://console.aws.amazon.com/sagemaker/)，选择笔记本实例 **RunScriptNotebookInstance**，选择**操作**，然后选择**停止**。停止实例可能需要几分钟时间。

1. 在实例**状态**更改为**已停止**之后，选择**操作**，选择**删除**，然后在对话框中选择**删除**。删除实例可能需要几分钟时间。删除后，笔记本实例将从表中消失。

1. 打开 [Amazon S3 控制台](https://console.aws.amazon.com/s3/)并删除为存储模型构件和训练数据集创建的存储桶。

1. 打开 [IAM 控制台](https://console.aws.amazon.com/iam/)，然后删除 IAM 角色。如果您已创建权限策略，也可以将其删除。
**注意**  
 Docker 容器在运行后会自动关闭。您不需要删除该容器。

## 博客和案例研究
<a name="byoc-blogs-and-examples"></a>

以下博客讨论了有关在 Amazon A SageMaker I 中使用自定义训练容器的案例研究。
+ [为什么要把自己的容器带到 Amazon SageMaker AI 以及如何正确操作，](https://medium.com/@pandey.vikesh/why-bring-your-own-container-to-amazon-sagemaker-and-how-to-do-it-right-bc158fe41ed1)*中等*（2023 年 1 月 20 日）