全部產品
Search
文件中心

Platform For AI:提交訓練作業

更新時間:Jul 13, 2024

PAI Python SDK提供了更易用的API(即HighLevel API),支援您將訓練作業提交到PAI,並使用雲上資源運行訓練作業。本文為您介紹如何準備訓練作業指令碼並使用SDK提交訓練作業。

計費說明

在提交訓練作業時,會調用DLC計算資源執行任務,由此會產生與DLC相關的資源費用。計費詳情,請參見分布式訓練(DLC)計費說明

概要介紹

SDK提供了HighLevel的訓練API pai.estimator.Estimator,支援您將訓練作業提交到PAI:

  • 使用pai.estimator.Estimator配置使用的訓練指令碼、作業啟動命令、超參、訓練鏡像以及訓練資源等作業資訊。

  • 通過pai.estimator.Estimator.fit方法,指定訓練資料,提交訓練作業。

範例程式碼如下:

from pai.estimator import Estimator

# 通過Estimator配置訓練作業。
est = Estimator(
    command="<LaunchCommand>"
    source_dir="<SourceCodeDirectory>"
    image_uri="<TrainingImageUri>"
    instance_type="<TrainingInstanceType>",
    hyperparameters={
        "n_estimators": 500,
        "max_depth": 5,
    },
)

# 指定訓練資料,提交訓練作業。
est.fit(
    inputs={
        "train_data": "oss://<YourOssBucket>/path/to/train/data/",
    }
)

# 擷取輸出模型路徑。
print(est.model_data())

以下內容為您介紹了提交訓練作業的具體操作流程和相關原理介紹。

準備訓練指令碼和所需依賴

  • 準備訓練指令碼

    Estimator支援將您編寫的本地訓練指令碼提交到PAI上執行,PAI的訓練服務會按一定的規範準備訓練作業環境,運行訓練指令碼。訓練指令碼樣本如下:

    import argparse
    import os
    import json
    
    def train(hps, train_data, test_data):
        """使用者的模型訓練代碼"""
        pass
    
    def save_model(model):
        """儲存模型"""
        # 通過環境變數擷取輸出模型路徑,預設為/ml/output/model/。
        output_model_path = os.environ.get("PAI_OUTPUT_MODEL")
    
        # 將模型寫出到output_model_path路徑下。
        pass
    
    def load_hyperparameters():
        """讀取輸入超參"""
        # 通過環境變數 PAI_CONFIG_DIR 擷取超參儲存目錄,預設為/ml/input/config/。
        hps_path = os.path.join(os.environ.get("PAI_CONFIG_DIR"), "hyperparameters.json")
        with open(hps_path, "r") as f:
            hyperparameters = json.load(f)
        return hyperparameters
    
    def run():
        # 1、載入使用者訓練作業的超參。
        hps = load_hyperparameters()
        print("Hyperparameters: ", hps)
    
        # 2、訓練作業的輸入資料。
        # 通過est.fit()方法,使用者可以指定儲存在NAS或OSS上的訓練資料,將資料準備到訓練容器中。
        # 訓練指令碼可以通過環境變數(PAI_INPUT_{CHANNEL_NAME})擷取輸入資料的本地路徑。
        train_data = os.environ.get("PAI_INPUT_TRAIN")
        test_data = os.environ.get("PAI_INPUT_TEST")
    
        model = train(hps, train_data, test_data)
    
        # 3、作業訓練代碼,在訓練結束之後,寫出模型到輸出模型路徑。
        save_model(model)
    
    
    if __name__ == "__main__":
        run()

    訓練指令碼需要遵循相應規範,包括讀取超參和輸入資料,然後在訓練結束後寫出模型。

    • 訓練作業超參:

      當您通過pai.estimator.Estimatorhyperparameters參數配置了訓練作業的超參,超參檔案hyperparameters.json會被準備到PAI_CONFIG_DIR環境變數指定目錄下(預設為/ml/input/config/)。訓練作業指令碼可以通過讀取{PAI_CONFIG_DIR}/hyperparameters.json檔案擷取相應的超參。

      例如您傳遞的訓練作業超參為hyperparameters={"batch_size": 32, "learning_rate": 0.01},則超參檔案{PAI_CONFIG_DIR}/hyperparameters.json內容為:

      {
        "batch_size": "32",
      	"learning-rate": "0.01"
      }
      
    • 訓練作業的輸入資料:

      您可以通過pai.estimator.Estimator.fit()inputs參數指定訓練所需的輸入資料,輸入參數需是一個字典, 其中Key是輸入資料的名稱(ChannelName),Value是輸入資料的儲存路徑,具體樣本如下:

      estimator.fits(
        	inputs={
          		"train": "oss://<YourOssBucket>/train/data/train.csv",
          		"test": "oss://<YourOssBucket>/test/data/",
        	}
      )
      

      對應的輸入資料路徑會被掛載到/ml/input/data/{ChannelName}路徑下,您的訓練代碼可以通過環境變數PAI_INPUT_{ChannelName}擷取到資料的本地路徑,您的訓練作業指令碼可以通過讀取本地檔案的方式獲得指定的輸入資料。以上的樣本中,我們能通過PAI_INPUT_TRAINPAI_INPUT_TEST環境變數擷取到輸入的OSS URI對應的本地路徑。

    • 訓練作業模型儲存:

      訓練作業的輸出模型需要儲存到指定路徑,才能將模型持久化儲存。您可以通過PAI_OUTPUT_MODEL環境變數擷取到模型儲存路徑(預設為/ml/output/model),然後將模型儲存到對應路徑。

  • 當您的訓練指令碼有額外的Python包依賴,訓練使用的鏡像中沒有提供時,您可以通過在訓練指令碼所在目錄中編寫requirements.txt,相應的三方庫依賴會在您的指令碼執行前被安裝到作業環境中。

您需要將訓練指令碼和相關依賴檔案存放到指定目錄,例如,您在本地建立了目錄train_src,您需要將準備好的訓練指令碼和依賴檔案存放到該目錄中。後續在Estimator構建時指定source_dir="train_src",則train_src目錄會被打包上傳到訓練環境的指定路徑中。

|-- train_src # 使用者指定上傳的訓練指令碼目錄。
	|-- requirements.txt # 作業的requirements資訊。
	`-- train.py # 訓練指令碼,使用者可以通過 python train.py 的命令拉起指令碼
	`-- utils.py

擷取PAI提供的公用鏡像

您在提交訓練作業時,需要指定作業的運行鏡像,鏡像中需要包含作業指令碼的執行依賴,例如使用的機器學習架構,以及相關的第三方依賴。您可以使用儲存在阿里雲鏡像倉庫(ACR)中的鏡像提交訓練作業,也可以使用PAI提供的公用鏡像。對於常見的機器學習架構,PAI提供了公用鏡像供您使用。您可以使用pai.image.retrieve方法,並指定所需的機器學習架構來擷取PAI提供的公用鏡像。範例程式碼如下:

說明

您可以通過(可選)準備鏡像查看PAI提供的鏡像內安裝的Python三方庫資訊。

from pai.image import retrieve, list_images, ImageScope


# 擷取PAI提供的所有PyTorch訓練鏡像。
for image_info in list_images(framework_name="PyTorch"):
 print(image_info)

# 擷取PAI提供的TensorFlow 2.3版本的CPU訓練鏡像。
print(retrieve(framework_name="TensorFlow", framework_version="2.3"))

# 擷取PAI提供的最新的TensorFlow的GPU訓練鏡像。
# 通過參數framework_version="latest",retrieve方法會返回最新的TensorFlow鏡像。
print(retrieve(framework_name="TensorFlow", framework_version="latest",
		accelerator_type="GPU"))

# 擷取PAI提供的PyTorch 1.12版本的GPU訓練鏡像。
print(retrieve(framework_name="PyTorch", framework_version="1.12",
 accelerator_type="GPU"))

運行訓練作業

將訓練作業提交到PAI上運行

您可以通過構建pai.estimator.Estimator指定訓練作業的指令碼目錄、啟動指令碼、超參和機器資源等,然後通過fit方法提交訓練作業。在提交作業之後,會列印訓練作業的控制台連結,並持續列印工作的輸出日誌資訊,直到訓練作業結束退出(作業狀態為成功、失敗或被停止)。您可以通過點擊作業連結,去控制台查看作業執行詳情、日誌、機器的資源使用方式,以及訓練的Metric等資訊。

預設情況下,fit方法在作業執行完成後會退出。您可以使用estimator.model_data()方法擷取訓練作業輸出模型在OSS上的儲存路徑。

範例程式碼如下:

from pai.estimator import Estimator
from pai.image import retrieve

# 擷取PAI支援的最新PyTorch鏡像。
torch_image_uri = retrieve("PyTorch", framework_version="1.12").image_uri

est = Estimator(
    # 訓練作業的啟動命令。
    command="python train.py",
    # 訓練作業指令碼,可以是一個本地目錄相對路徑或是絕對路徑,或是OSS上的tar包(例如oss://<YourOssBucket>/your-code-path-to/source.tar.gz)。
    # 當目錄中有requirements.txt檔案時,對應的依賴會被自動安裝,然後再啟動使用者的訓練指令碼。
    source_dir="./train_src/",
    # 訓練作業使用的鏡像。
    image_uri=torch_image_uri,
    # 訓練作業使用的機器類型。
    instance_type="ecs.c6.large",
    # 訓練作業的超參。
    hyperparameters={
        "n_estimators": 500,
        "objective": "reg:squarederror",
        "max_depth": 5,
    },
    # 訓練作業名稱首碼,使用者提交的訓練作業使用的Name為{base_job_name}_{submitted-datetime}。
    base_job_name="example_train_job",
)

# 提交訓練作業,同時列印訓練作業的Web詳情頁URL。fit調用預設等待到作業終止(成功、失敗、或被停止)。
est.fit()

# 輸出的模型路徑。
print(est.model_data())

本地執行訓練作業

在PAI上提交的訓練作業調試較為困難,因此Estimator也提供了本地執行的模式,方便您在本地環境中類比執行作業,調試相應的指令碼。構建Estimator時,若傳遞參數instance_type="local",訓練作業將在本地通過Docker容器運行,以類比PAI環境中的作業執行過程。

estimator = Estimator(
    image_uri=image_uri,
    entry_point="train.py",
    # instance_type="local" 表示運行在本地環境。
    instance_type="local",
)

estimator.fit(
    inputs={
        # local模式下,OSS上的資料會被下載到本地,然後掛載到工作容器內。
        "train": "oss://<BucketName>/path-to-data/",
        # local模式下,支援本地檔案資料,對應的資料會被掛載到相應的channel目錄。
        "test": "/data/to/test/data"
    }
)

# 返回一個本地的模型輸出目錄。
print(estimator.model_data())

相關文檔

附錄

訓練作業預置環境變數

您在PAI提交的訓練作業需要按規範讀取超參、擷取資料路徑,以及寫出模型到指定路徑。PAI的訓練服務會將這些資訊以環境變數的形式注入到訓練作業的容器中,您可以通過環境變數在訓練指令碼中,或是在Estimator.command指定的訓練作業啟動命令中,擷取超參數、輸入資料路徑和模型儲存路徑等資訊。

  • PAI_HPS_{HYPERPARAMETER_NAME}

    單個訓練作業超參的值,會以環境變數的形式注入到訓練作業的容器中。對於超參名中,環境變數中不支援的字元(預設的環境變數僅支援使用字母、數字,以及底線),會被替換為底線。

    例如您指定了超參{"epochs": 10, "batch-size": 32, "train.learning_rate": 0.001},對應的環境變數資訊如下:

    PAI_HPS_EPOCHS=10
    PAI_HPS_BATCH_SIZE=32
    PAI_HPS_TRAIN_LEARNING_RATE=0.001
    

    您可以在訓練啟動命令中直接引用這些環境變數,例如:

    est = Estimator(
     command="python train.py --epochs $PAI_HPS_EPOCHS --batch-size $PAI_HPS_BATCH_SZIE",
     hyperparameters={
     "epochs": 10,
     "batch-size": 32,
     },
     # more arguments for estimator..
    )
    

    以上的方式傳遞的參數,訓練指令碼train.py可以通過標準庫argparse擷取輸入參數。

  • PAI_USER_ARGS

    訓練作業的所有超參資訊,會以PAI_USER_ARGS環境變數,使用--{hyperparameter_name} {hyperparameter_value}的形式,注入到訓練作業的容器中。

    例如訓練作業指定了超參hyperparameters={"epochs": 10, "batch-size": 32, "learning-rate": 0.001},則PAI_USER_ARGS環境變數的值為:

    PAI_USER_ARGS="--epochs 10 --batch-size 32 --learning-rate 0.001"
    

    您可以在啟動命令中引用環境變數,例如以下的執行個體中,訓練作業指令碼會以python train.py --epochs 10 --batch-size 32 --learning-rate 0.001的命令執行。

    est = Estimator(
        command="python train.py $PAI_USER_ARGS",
        hyperparameters={
            "epochs": 10,
            "learning-rate": 0.001
            "batch-size": 32,
        },
        # more arguments for estimator..
    )
  • PAI_HPS

    您的訓練作業的超參資訊,會以JSON格式,通過PAI_HPS環境變數注入到訓練作業的容器中。

    例如您傳遞了超參{"epochs": 10, "batch-size": 32},則PAI_HPS環境變數的值為:

    PAI_HPS={"epochs": 10, "batch-size": 32}
    
  • PAI_INPUT_{channel_name}

    訓練作業的輸入資料,會以掛載的形式掛載到訓練作業上,您可以通過讀取本地檔案的方式讀取到OSS和NAS上的資料。對於每一個輸入的資料,會以PAI_INPUT_{channel_name}的環境變數注入到訓練作業的容器中。

    例如您的執行代碼為est.fit(inputs={"train": "oss://<YourOssBucket>/path-to-data/", "test": "oss://<YourOssBucket>/path-to/data/test.csv"}),對應的環境變數如下:

    PAI_INPUT_TRAIN=/ml/input/data/train/
    PAI_INPUT_TEST=/ml/input/data/test/test.csv
    

    對應的資料存放區路徑會被掛載到容器中,您可以通過這些本地路徑資訊,直接讀取到輸入的資料。

    說明

    PAI_INPUT_{ChannelName}指向您傳入的資料路徑,如果您指定了一個OSS目錄(以 / 結尾),則PAI的訓練服務會將輸入儲存作為目錄進行掛載,環境變數指向對應的資料目錄。如果您傳遞了一個OSS檔案路徑,PAI的訓練服務會掛載對應的檔案目錄,環境變數會指OSS URI對應的實際檔案。

  • PAI_OUTPUT_{channel_name}

    預設訓練作業會建立兩個輸出Channel,分別為modelcheckpoints,分別用於儲存模型輸出和訓練checkpoints。每一個Channel對應一個OSS URI,以及對應的掛載路徑。您可以通過PAI_OUTPUT_{channel_name}環境變數,擷取到對應的檔案路徑。

    PAI_OUTPUT_MODEL=/ml/output/model/
    PAI_OUTPUT_CHECKPOINTS=/ml/output/checkpoints/
    

    通過將需要儲存的模型或checkpoints,儲存到這些路徑下,PAI的訓練服務會自動將這些檔案上傳到對應的OSS路徑下。

訓練作業目錄結構

完整的訓練作業的輸入輸出目錄結構樣本如下:

/ml
|-- usercode                        # 使用者代碼載入到/ml/usercode目錄,這裡也是使用者代碼的工作目錄。可以通過環境變數 `PAI_WORKING_DIR` 獲得.
|   |-- requirements.txt
|   `-- train.py
|-- input                           # 作業輸入資料和配置資訊。
|   `-- config                      # config目錄包含了作業的配置資訊,可以通過PAI_CONFIG_DIR擷取。
|       |-- hyperparameters.json    # 訓練作業超參。
|   `-- data                        # 作業的InputChannels:以下目錄包含了兩個channel: train_data和test_data。
|       |-- test_data
|       |   `-- test.csv
|       `-- train_data
|           `-- train.csv
`-- output                          # 作業的輸出Channels:預設包含兩個OutputChannel: model/checkpoints。
        `-- model                   # 通過環境變數PAI_OUTPUT_{CHANNEL_NAME}可以獲輸出路徑。
        `-- checkpoints