

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

# 調整您的訓練指令碼以註冊勾點
<a name="debugger-modify-script"></a>

Amazon SageMaker Debugger 隨附一個名為 [`sagemaker-debugger`Python SDK ](https://sagemaker-debugger.readthedocs.io/en/website)的用戶端程式庫。`sagemaker-debugger` Python SDK 提供工具，可在訓練前調整您的訓練指令碼，並在訓練後調整分析工具。在此頁面中，您將了解如何使用用戶端程式庫調整訓練指令碼。

`sagemaker-debugger` Python SDK 提供包裝函式，可協助註冊勾點以擷取模型張量，而不必變更訓練指令碼。若要開始收集模型輸出張量並對其進行偵錯以尋找訓練問題，請在訓練指令碼中進行下列修改。

**提示**  
依照此頁面操作時，請使用 [`sagemaker-debugger` 開放原始碼軟體開發套件文件](https://sagemaker-debugger.readthedocs.io/en/website/index.html)進行 API 參考。

**Topics**
+ [調整 PyTorch 訓練指令碼](debugger-modify-script-pytorch.md)
+ [調整您的 TensorFlow 訓練指令碼](debugger-modify-script-tensorflow.md)

# 調整 PyTorch 訓練指令碼
<a name="debugger-modify-script-pytorch"></a>

若要開始收集模型輸出張量並對訓練問題進行偵錯，請對 PyTorch 訓練指令碼進行下列修改。

**注意**  
SageMaker Debugger 無法從 [https://pytorch.org/docs/stable/nn.functional.html](https://pytorch.org/docs/stable/nn.functional.html) API 作業收集模型輸出張量。當您撰寫 PyTorch 訓練指令碼時，建議改用 [https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html](https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html) 模組。

## 適用於 PyTorch 1.12.0
<a name="debugger-modify-script-pytorch-1-12-0"></a>

若使用 PyTorch 訓練指令碼，您可以執行訓練任務，並在訓練指令碼中使用一些額外的程式碼行擷取模型輸出張量。您需要使用 `sagemaker-debugger` 用戶端程式庫中的[勾點 API](https://sagemaker-debugger.readthedocs.io/en/website/hook-api.html)。逐步執行下列指示，以程式碼範例分解各步驟。

1. 建立勾點。

   **(建議) 適用於 SageMaker AI 內的訓練工作**

   ```
   import smdebug.pytorch as smd
   hook=smd.get_hook(create_if_not_exists=True)
   ```

   當您在 [使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md) 中啟動訓練任務時，在估算器中使用任何 DebuggerHookConfig、TensorBoardConfig 或 Rules，SageMaker AI 會將 JSON 組態檔案新增至您的訓練執行個體，並由 `get_hook` 函式選取。請注意，如果您沒有在估算器中包含任何組態 API，就不會有要尋找勾點的組態檔案，且函式會傳回 `None`。

   **(選用) 適用於 SageMaker AI 以外的訓練工作**

   如果您以本機模式執行訓練任務，請直接在 SageMaker 筆記本執行個體、Amazon EC2 執行個體或您自己的本機裝置上執行訓練任務，並使用 `smd.Hook` 類別建立勾點。不過，這種方法只能儲存張量集合，且僅可用於 TensorBoard 視覺化。SageMaker Debugger 的內建規則不適用於本機模式，因為規則會要求 SageMaker AI ML 訓練執行個體和 S3 即時儲存來自遠端執行個體的輸出。在這種情況下，`smd.get_hook` API 會傳回 `None`。

   如果您想要建立手動勾點以在本機模式下儲存張量，請使用下列程式碼片段與邏輯來檢查 `smd.get_hook` API 是否傳回 `None`，並使用 `smd.Hook` 類別建立手動勾點。請注意，您可以在本機機器中指定任何輸出目錄。

   ```
   import smdebug.pytorch as smd
   hook=smd.get_hook(create_if_not_exists=True)
   
   if hook is None:
       hook=smd.Hook(
           out_dir='/path/to/your/local/output/',
           export_tensorboard=True
       )
   ```

1. 用勾點的類別方法包裝您的模型。

   `hook.register_module()` 方法採用您的模型並逐一查看每一層，尋找與您透過 [使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md) 組態提供的規則表達式所符合的任何張量。透過此勾點的可收式張量方法為加權、誤差、啟用、漸層、輸入和輸出。

   ```
   hook.register_module(model)
   ```
**提示**  
如果從大型深度學習模型收集整個輸出張量，則這些集合的大小總計可能會呈指數級增長，並可能導致瓶頸。如果想要儲存特定張量，也可以使用 `hook.save_tensor()` 方法。此方法可協助您為特定張量選取變數，並儲存至所需命名的自訂集合。如需詳細資訊，請參閱此指示的[步驟 7](#debugger-modify-script-pytorch-save-custom-tensor)。

1. 使用勾點的類別方法扭曲損失函式。

   `hook.register_loss` 方法是去包裝損失函式。它會擷取每一個您會在 [使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md) 配置過程中設定的 `save_interval` 損失值，並將它們儲存到 `"losses"` 集合。

   ```
   hook.register_loss(loss_function)
   ```

1. 在訓練區塊中新增 `hook.set_mode(ModeKeys.TRAIN)`。這表示張量集合是在訓練階段擷取的。

   ```
   def train():
       ...
       hook.set_mode(ModeKeys.TRAIN)
   ```

1. 在驗證區塊中新增 `hook.set_mode(ModeKeys.EVAL)`。這表示張量集合是在驗證階段擷取的。

   ```
   def validation():
       ...
       hook.set_mode(ModeKeys.EVAL)
   ```

1. 使用 [https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_scalar](https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_scalar) 儲存自訂純量。您可以儲存不在模型中的純量值。例如，如要記錄在評估期間運算的精確度值，請在計算準確度的行下方新增下列程式碼行。

   ```
   hook.save_scalar("accuracy", accuracy)
   ```

   請注意，您需要提供一個字串作為第一個引數來命名自訂純量集合。這是將用於在 TensorBoard 中視覺化純量值的名稱，並且可以是您想要的任何字串。

1. <a name="debugger-modify-script-pytorch-save-custom-tensor"></a>使用 [https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_tensor](https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_tensor) 儲存自訂張量。類似於 [https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_scalar](https://sagemaker-debugger.readthedocs.io/en/website/hook-constructor.html#smdebug.core.hook.BaseHook.save_scalar)，您可以儲存其他張量，並定義自己的張量集合。例如，您可以透過新增以下程式碼行 (其中 `"images"` 是自訂張量的範例名稱)，來擷取傳遞到模型中的輸入映像資料並另存為自訂張量 (其中 `image_inputs` 是輸入映像資料的範例變數)。

   ```
   hook.save_tensor("images", image_inputs)
   ```

   請注意，您必須為第一個引數提供字串，才能命名自訂張量。`hook.save_tensor()` 具有第三個引數 `collections_to_write` 來指定張量集合以儲存自訂張量。預設值為 `collections_to_write="default"`。如果您沒有明確指定第三個引數，則自訂張量將儲存到 `"default"` 張量集合中。

完成訓練指令碼的調整後，請繼續前往[使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md)。

# 調整您的 TensorFlow 訓練指令碼
<a name="debugger-modify-script-tensorflow"></a>

若要開始收集模型輸出張量和針對訓練問題偵錯，請對 TensorFlow 訓練指令碼進行下列修改。

**為 SageMaker AI 中的訓練任務建立勾點**

```
import smdebug.tensorflow as smd

hook=smd.get_hook(hook_type="keras", create_if_not_exists=True)
```

這會在您啟動 SageMaker 訓練任務時建立勾點。當您在 [使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md) 於您的估算器中使用任何一個 `DebuggerHookConfig`、`TensorBoardConfig` 或 `Rules` 啟動訓練任務時，SageMaker AI 會將 JSON 組態檔案新增至您的訓練執行個體，該檔案將由 `smd.get_hook` 方法選取。請注意，如果您沒有在估算器中包含任何組態 API，就不會有要尋找勾點的組態檔案，且函式會傳回 `None`。

**(選用) 為 SageMaker AI 以外的訓練工作建立勾點**

如果您以本機模式執行訓練任務，請直接在 SageMaker 筆記本執行個體、Amazon EC2 執行個體或您自己的本機裝置上執行訓練任務，並使用 `smd.Hook` 類別建立勾點。不過，這種方法只能儲存張量集合，且僅可用於 TensorBoard 視覺化。SageMaker Debugger 的內建規則不適用於本機模式。在這種情況下，`smd.get_hook` 方法也會傳回 `None`。

如果您想要建立手動勾點，請使用下列程式碼片段與邏輯來檢查勾點是否傳回 `None`，並使用 `smd.Hook` 類別建立手動勾點。

```
import smdebug.tensorflow as smd

hook=smd.get_hook(hook_type="keras", create_if_not_exists=True) 

if hook is None:
    hook=smd.KerasHook(
        out_dir='/path/to/your/local/output/',
        export_tensorboard=True
    )
```

新增勾點建立程式碼之後，請繼續 TensorFlow Keras 的下列主題。

**注意**  
SageMaker Debugger 目前僅支援 TensorFlow Keras。

## 在您的 TensorFlow Keras 訓練指令碼中註冊勾點
<a name="debugger-modify-script-tensorflow-keras"></a>

以下程序將逐步引導您使用勾點及其方法，從模型和最佳化工具收集輸出純量與張量。

1. 利用勾點的類別方法包裝您的 Keras 模型和最佳化工具。

   `hook.register_model()` 方法採用您的模型並逐一查看每一層，尋找與您透過 [使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md) 組態提供的規則表達式所符合的任何張量。透過此勾點方法的可收式張量為加權、誤差和啟用。

   ```
   model=tf.keras.Model(...)
   hook.register_model(model)
   ```

1. 透過 `hook.wrap_optimizer()` 方法包裝最佳化工具。

   ```
   optimizer=tf.keras.optimizers.Adam(...)
   optimizer=hook.wrap_optimizer(optimizer)
   ```

1. 在 TensorFlow 中以嚴格模式編譯模型。

   若要從模型收集張量 (例如每層的輸入和輸出張量)，您必須以嚴格模式執行訓練。否則，SageMaker AI Debugger 將無法收集張量。不過，系統可以收集其他張量，例如模型加權、誤差和損失，而無須在嚴格模式中明確執行。

   ```
   model.compile(
       loss="categorical_crossentropy", 
       optimizer=optimizer, 
       metrics=["accuracy"],
       # Required for collecting tensors of each layer
       run_eagerly=True
   )
   ```

1. 將勾點註冊到 [https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit](https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit) 方法。

   若要從您註冊的勾點收集張量，請將 `callbacks=[hook]` 新增至 Keras `model.fit()` 類別方法。這會把 `sagemaker-debugger` 勾點作為 Keras 回呼來傳遞。

   ```
   model.fit(
       X_train, Y_train,
       batch_size=batch_size,
       epochs=epoch,
       validation_data=(X_valid, Y_valid),
       shuffle=True, 
       callbacks=[hook]
   )
   ```

1. TensorFlow 2.x 僅提供符號漸層變數，而這些變數不提供本身值的存取。如要收集漸層，請按照 [https://sagemaker-debugger.readthedocs.io/en/website/hook-methods.html#tensorflow-specific-hook-api](https://sagemaker-debugger.readthedocs.io/en/website/hook-methods.html#tensorflow-specific-hook-api) 方法包裝 `tf.GradientTape`，這需要您編寫自己的訓練步驟，如下所示。

   ```
   def training_step(model, dataset):
       with hook.wrap_tape(tf.GradientTape()) as tape:
           pred=model(data)
           loss_value=loss_fn(labels, pred)
       grads=tape.gradient(loss_value, model.trainable_variables)
       optimizer.apply_gradients(zip(grads, model.trainable_variables))
   ```

   透過包裝磁帶，`sagemaker-debugger` 勾點可以識別輸出張量，例如建層、參數和損失。包裝磁帶可確保圍繞磁帶物件函式的 `hook.wrap_tape()` 方法 (例如 `push_tape()`、`pop_tape()`、`gradient()`) 將設定 SageMaker Debugger 的寫入器，並儲存提供做為輸入 `gradient()` (可訓練的變數及損失) 和 `gradient()` (漸層) 輸出的張量。
**注意**  
如要透過自訂訓練循環進行收集，請務必使用嚴格模式。否則，SageMaker Debugger 無法收集任何張量。

如需 `sagemaker-debugger` 勾點 API 提供用來建構勾點和儲存張量的完整動作清單，請參閱 *`sagemaker-debugger`Python SDK 文件*中的[勾點方法](https://sagemaker-debugger.readthedocs.io/en/website/hook-methods.html)。

完成訓練指令碼的調整後，請繼續前往[使用 SageMaker Python SDK 搭配 Debugger 啟動訓練任務](debugger-configuration-for-debugging.md)。