我正在尝试使用 Sagemaker 的训练作业和 Sagemaker Python SDK 来运行训练,训练脚本依赖于一些自定义库。根据我的理解,由于自定义脚本,我需要使用已注册到 ECR(弹性容器注册表)的 docker 容器生成自定义映像。下面的环境是 Sagemaker Studio 代码编辑器。
我得到的错误是
Failed to parse hyperparameter
。请参阅下文了解我的设置以及我尝试过的解决方案。
目录
working directory
—Dockerfile
—train.py
—requirements.txt
Dockerfile
# Use python image as base
FROM python:3.10
# Install system dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Set working directory in container
COPY code /opt/program
WORKDIR /code
# Install Python dependencies
COPY requirements.txt /code/
RUN pip install --no-cache-dir -r requirements.txt
RUN pip 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
# Set environment variables
ENV PYTHONUNBUFFERED=TRUE
ENV PYTHONDONTWRITEBYTECODE=TRUE
ENV PATH="/opt/program:${PATH}"
需求.txt
simpletransformers==0.70.0
pandas==2.1.1
numpy==1.26.0
torch==2.2.1
sklearn-deap==0.3.0
sklearn-genetic-opt==0.10.1
boto3==1.33.3
sagemaker
火车.py
import argparse
import os
import logging
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, f1_score
from simpletransformers.classification import ClassificationModel
import torch
from sagemaker_pytorch_estimator.pytorch_estimator import PyTorchModel
from sagemaker_containers.data_instances.data_buffer import BufferDataset, BufferedShuffledDataset
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--batch_size", type=int, default=32)
parser.add_argument("--test_size", type=float, default=0.2)
parser.add_argument("--target_column", type=str, default="annotation")
parser.add_argument("--vertical", type=str, default="some_category")
parser.add_argument("--model_dir", type=str, default=os.environ.get("SM_MODEL_DIR"))
parser.add_argument("--train", type=str, default=os.environ.get("SM_CHANNEL_TRAIN"))
parser.add_argument("--val", type=str, default=os.environ.get("SM_CHANNEL_VAL"))
parser.add_argument("--test", type=str, default=os.environ.get("SM_CHANNEL_TEST"))
args, _ = parser.parse_known_args()
model_data = None
role = None
entry_point = None
....(script continues)
启动脚本:
import sagemaker
from sagemaker.session import TrainingInput
from sagemaker.estimator import Estimator
vertical = 'some_category'
s3_bucket = 'some_bucker'
prefix = 'classification'
instance_type = 'ml.m4.xlarge'
print("Instance Type: {}".format(instance_type))
region = sagemaker.Session().boto_region_name
print("AWS Region: {}".format(region))
role = sagemaker.get_execution_role()
print("RoleArn: {}".format(role))
s3_output_location='s3://{}/{}/{}'.format(s3_bucket, prefix, 'classifier')
container = '############.###.###.##-####-#.amazonaws.com/some-name/ml-training:latest'
print("Image Container: {}".format(container))
estimator = Estimator(
image_uri=container,
role=role,
instance_count=1,
instance_type=instance_type,
volume_size=10,
output_path=s3_output_location,
sagemaker_session=sagemaker.Session()
)
estimator.set_hyperparameters(vertical=vertical,
s3_bucket=s3_bucket,
target_column='annotation',
test_size=0.2)
estimator.fit()
错误
Failed to parse hyperparameter
我尝试过的解决方案:
sagemaker-training
库来说似乎是一个 开放问题。唯一的建议是将超参数包装在一些用户建议的函数周围,但这似乎不是当前有效的解决方案(出现此错误:
TypeError: Estimator.set_hyperparameters() takes 1 positional argument but 2 were given
)argparse
与Sagemaker不兼容(所有官方aws sagemaker文档都使用argparse
)。我不清楚他们建议的解决方案。这里有几个话题需要讨论。首先,您不需要创建一个容器只是为了包含额外的依赖项。
您可以通过提供
source_dir
并在引用的源目录中包含requirements.txt 文件来向估算器添加依赖项。
来自 Estimator API 文档:
源目录 除条目外具有任何其他训练源代码依赖项的目录的绝对、相对或 S3 URI 路径 点文件。如果 source_dir 是 S3 URI,则它必须指向 tar.gz 文件。训练时会保留此目录中的结构 亚马逊 SageMaker。
包含
source_dir
的最直接方法是将其本地放在笔记本旁边。
|----- example-notebook.ipynb
|----- src
|----- train.py
|----- requirements.txt
然后,您可以将估算器配置为使用具有以下配置的源目录:
estimator = Estimator(
[...]
entry_point="train.py",
source_dir="src",
[...]
)
如果指定了
source_dir
,则entry_point
必须指向位于source_dir
根目录的文件。训练作业将自动安装所提供的依赖项requirements.txt
。
由于您使用的是 Scikit-Learn,因此您还可以使用 SKLearn Estimator,它已经捆绑了多个依赖项,并与通用 Estimator 相比提供了简化的界面。
如果您想按原样使用代码,那么您可以按如下方式调整代码:
import json
# JSON encode hyperparameters
def json_encode_hyperparameters(hyperparameters):
return {str(k): json.dumps(v) for (k, v) in hyperparameters.items()}
hyperparameters = json_encode_hyperparameters({
"vertical": vertical,
"s3_bucket": s3_bucket,
"target_column": target_column,
"test_size": 0.2
})
estimator = Estimator(
image_uri=container,
role=role,
instance_count=1,
instance_type=instance_type,
volume_size=10,
output_path=s3_output_location,
sagemaker_session=sagemaker.Session(),
hyperparameters=hyperparameters
)
set_hyperparameters
期望输入为 kwargs
,而 hyperparameters
属性接受不同格式的输入。因此,您不能将 JSON 编码的字典与 set_hyperparameters
一起使用;相反,请将其与 hyperparameters
属性一起使用。