

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 調整自有訓練容器
<a name="adapt-training-container"></a>

若要執行您自有的訓練模型，請透過 Amazon SageMaker 筆記本執行個體使用 [Amazon SageMaker Training Toolkit](https://github.com/aws/sagemaker-training-toolkit) 建立一個 Docker 容器。

## 步驟 1：建立一個 SageMaker 筆記本執行個體
<a name="byoc-training-step1"></a>

1. 開啟位在 [https://console.aws.amazon.com/sagemaker/](https://console.aws.amazon.com/sagemaker/) 的 Amazon SageMaker AI 主控台。

1. 從左邊導覽窗格中，選擇**筆記本**，選擇**筆記本執行個體**，然後選擇**建立筆記本執行個體**。

1. 在**建立筆記本執行個體**頁面上，提供下列資訊：

   1. 對於**筆記本執行個體名稱**，輸入 **RunScriptNotebookInstance**。

   1. 對於**筆記本執行個體類型**，選擇 **ml.t2.medium**。

   1. 在**許可與加密**區段內執行下列動作：

      1. 對於 **IAM 角色**，選擇**建立新角色**。這會開啟新視窗。

      1. 在**建立 IAM 角色**頁面上，選擇**特定的 S3 儲存貯體**，指定名為 **sagemaker-run-script** 的 Amazon S3 儲存貯體，然後選擇**建立角色**。

         SageMaker AI 會建立名為 `AmazonSageMaker-ExecutionRole-{{YYYYMMDD}}T{{HHmmSS}}` 的 IAM 角色。例如 `AmazonSageMaker-ExecutionRole-20190429T110788`。請注意，執行角色命名慣例會使用角色建立時的日期和時間，並以 `T` 分隔。

   1. 對於**根存取**，選擇**已啟用**。

   1. 選擇**建立筆記本執行個體**。

1. 在**筆記本執行個體**頁面上，**狀態**為**待定**。Amazon SageMaker AI 可能需要幾分鐘的時間才能啟動機器學習運算執行個體 (在此情況下，它會啟動筆記本執行個體)，並將機器學習 (ML) 儲存磁碟區連接到執行個體上。筆記本執行個體具備預先設定的 Jupyter 筆記本伺服器和一組 Anaconda 程式庫。如需詳細資訊，請參閱 [CreateNotebookInstance](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateNotebookInstance.html)。

   

1. 按一下您剛建立的筆記本的**名稱**。這會開啟新頁面。

1.  在**許可與加密**區段中，複製 **IAM 角色 ARN 編號**，然後將它貼到記事本檔案中暫存。稍後您可以使用此 IAM 角色 ARN 編號，在筆記本執行個體中設定本機訓練估算器。**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. 將下列 `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 Training Toolkit](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`。要重新命名檔案，請在檔案上按一下滑鼠右鍵，選擇**重新命名**，將檔案重新命名為 `Dockerfile` 且不含 `.txt` 副檔名，然後按下 `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\_tensorflow2**。

1. 在第一個筆記本儲存格執行下列命令，可切換至 `docker_test_folder` 目錄：

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

   這樣會返回目前的目錄，如下所示：

   ```
   ! pwd
   ```

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

1. 若要建立 Docker 容器，請執行以下 Docker build 命令 (包括在結尾處有句點的空格)：

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

   必須從您建立的 Docker 目錄中執行 Docker build 命令，在此案例中為 `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\_tensorflow2** 。

1. 將下列範例指令碼貼到筆記本程式碼儲存格，以設定 SageMaker AI 估算器。

   ```
   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"
   ```
如果發生此錯誤，您需要將 **AmazonEC2ContainerRegistryFullAccess** 政策連接至您的 IAM 角色。前往 [IAM 主控台](https://console.aws.amazon.com/iam/home)，從左側導覽窗格中選擇**角色**，然後查找您用於筆記本執行個體的 IAMrole。在**許可**標籤下，選擇**連接政策**按鈕，然後搜尋 **AmazonEC2ContainerRegistryFullAccess** 政策。選取政策的核取方塊，然後選擇**新增許可**來完成。

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` 以設定 SageMaker AI 估算器物件。下列程式碼範例會以 `byoc_image_uri` 設定 SageMaker AI 估算器，並在 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架構容器。若要部署讀取手寫數字的範例模型，請將下列範例指令碼輸入您在上一個子步驟中用來訓練模型的同一個筆記本，以取得部署所需的映像 URI (通用資源識別碼)，然後部署該模型。

   ```
   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 SageMaker Debugger。如需詳細資訊，請參閱[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 SageMaker AI 中使用自訂訓練容器的案例研究。
+ [為什麼要在 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 日)