構築済みコンテナを拡張する - Amazon SageMaker

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

構築済みコンテナを拡張する

構築済みの SageMaker コンテナがすべての要件を満たさない場合は、ニーズに合わせて既存のイメージを拡張できます。環境やフレームワークを直接サポートしている場合でも、機能をさらに追加したり、コンテナ環境を異なる方法で構成したりすることもできます。構築済みのイメージを拡張することで、最初からイメージを作成しなくても、付属の深層学習ライブラリと設定を活用できます。コンテナを拡張することで、ライブラリの追加、設定の変更、追加の依存関係のインストールを行うことができます。

次のチュートリアルでは、構築済みの SageMaker イメージを拡張して Amazon ECR に公開する方法を示します。

構築済みコンテナを拡張するための要件

構築済みの SageMaker イメージを拡張するには、Dockerfile 内で次の環境変数を設定する必要があります。コンテナを使用する SageMaker環境変数の詳細については、SageMaker 「Training Toolkit GitHub repo」を参照してください。

  • SAGEMAKER_SUBMIT_DIRECTORY: トレーニング用の Python スクリプトが配置されているコンテナ内のディレクトリ。

  • SAGEMAKER_PROGRAM: 呼び出され、トレーニングのエントリポイントとして使用される Python スクリプト。

Dockerfile に以下を含めることで、追加のライブラリをインストールすることもできます。

RUN pip install <library>

次のチュートリアルでは、これらの環境変数の使用方法について説明します。

コンテナを拡張 SageMakerして Python スクリプトを実行する

このチュートリアルでは、CIFAR-10 データセットを使用する Python ファイルを使用して SageMaker PyTorch コンテナを拡張する方法について説明します。 SageMaker PyTorch コンテナを拡張することで、 で機能するように作成された既存のトレーニングソリューションを利用します SageMaker。このチュートリアルでは、トレーニングイメージを拡張しますが、推論イメージを拡張するのにも同じ手順で行うことができます。利用可能なイメージの完全なリストについては、「使用可能な Deep Learning Containers イメージ」を参照してください。

SageMaker コンテナを使用して独自のトレーニングモデルを実行するには、ノートブックインスタンスを使用して Docker SageMaker コンテナを構築します。

ステップ 1: SageMaker ノートブックインスタンスを作成する

  1. SageMaker コンソールを開きます。

  2. 左側のナビゲーションペインで、[Notebook] (ノートブック)、[Notebook instances] (ノートブックインスタンス)、[Create notebook instance] (ノートブックインスタンスの作成) の順に選択します。

  3. [ノートブックインスタンスの作成] ページで、次の情報を入力します。

    1. [ノートブックインスタンス名] に「RunScriptNotebookInstance」と入力します。

    2. [ノートブックインスタンスタイプ] で、[ml.t2.medium] を選択します。

    3. [Permissions and encryption] (アクセス許可と暗号化) セクションで、以下の操作を行います。

      1. [IAM role] (IAM ロール) は、[Create a new role] (新しいロールの作成) を選択します。

      2. [Create an IAM role] (IAM ロールの作成) ページで、[Specific S3 buckets] (特定の S3 バケット) を選択し、sagemaker-run-script という名前の Amazon S3 バケットを指定して、[Create role] (ロールの作成) を選択します。

        SageMaker は、 AmazonSageMaker-ExecutionRole-YYYYMMDDTHHmmSSなどの という名前の IAM ロールを作成しますAmazonSageMaker-ExecutionRole-20190429T110788。実行ロールの命名規則では、ロールが作成された日時を T で区切って使用することに注意してください。

    4. [Root Access] (ルートアクセス) で、[Enable] (有効) を選択します。

    5. [Create notebook instance] (ノートブックインスタンスの作成) を選択します。

  4. [Notebook instances] (ノートブックインスタンス) ページでは [Status] (ステータス) は [Pending] (保留中) となっています。Amazon CloudWatch Internet Monitor が機械学習コンピューティングインスタンスを起動するまでに数分かかることがあります。この場合はノートブックインスタンスを起動し、機械学習ストレージボリュームをアタッチします。ノートブックインスタンスには、事前設定された Jupyter ノートブックサーバーと一連の Anaconda ライブラリがあります。詳細については、「」を参照してください。 
CreateNotebookInstance

  5. [Permissions and encryption] (アクセス許可と暗号化) セクションで、[the IAM role ARN number] (IAM ロールの ARN 番号) をコピーし、メモ帳ファイルに貼り付けて、一時的に保存します。この IAM ロールの ARN 番号は、後でノートブックインスタンスでローカルトレーニング推定器を構成するために使用します。[the IAM role ARN number (IAM ロールの ARN 番号)] は、次のようになります。'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'

  6. ノートブックインスタンスのステータスが に変わったらInServiceを開く JupyterLabを選択します。

ステップ 2: Dockerfile および Python トレーニングスクリプトを作成してアップロードする

  1. JupyterLab が開いたら、 のホームディレクトリに新しいフォルダを作成します JupyterLab。左上隅で、[New Folder] (新しいフォルダ) アイコンをクリックし、フォルダ名 docker_test_folder を入力します。

  2. docker_test_folder ディレクトリに Dockerfile という名前のテキストファイルを作成します。

    1. 左上隅の [New Launcher] (新しいランチャー) アイコン (+) を選択します。

    2. 右ペインの[Other] (その他) セクションで、[Text File] (テキストファイル) を選択します。

    3. 次の Dockerfile サンプルコードをテキストファイルに貼り付けます。

      # SageMaker PyTorch image FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04 ENV PATH="/opt/ml/code:${PATH}" # this environment variable is used by the SageMaker PyTorch container to determine our user code directory. ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code # /opt/ml and all subdirectories are utilized by SageMaker, use the /code subdirectory to store your user code. COPY cifar10.py /opt/ml/code/cifar10.py # Defines cifar10.py as script entrypoint ENV SAGEMAKER_PROGRAM cifar10.py

      Dockerfile のスクリプトは以下のタスクを実行します。

      • FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04 - SageMaker PyTorch ベースイメージをダウンロードします。これを、コンテナの構築に使用する任意の SageMaker ベースイメージに置き換えることができます。

      • ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code - /opt/ml/code をトレーニングスクリプトディレクトリに設定します。

      • COPY cifar10.py /opt/ml/code/cifar10.py - スクリプトを、 が期待するコンテナ内の場所にコピーします SageMaker。スクリプトは、このフォルダにある必要があります。

      • ENV SAGEMAKER_PROGRAM cifar10.py - cifar10.py トレーニングスクリプトをエントリポイントスクリプトに設定します。

    4. 左側のディレクトリナビゲーションペインでは、テキストファイル名は自動的に untitled.txt に設定されます。ファイルの名前を変更するには、ファイルを右クリックし、[Rename] (名前の変更) で、ファイル名を .txt 拡張子のない Dockerfile に変更し、Ctrl+s または Command+s を押してファイルを保存します。

  3. トレーニングスクリプト cifar10.pydocker_test_folder に作成またはアップロードします。この演習では次のサンプルスクリプトを使用できます。

    import ast import argparse import logging import os import torch import torch.distributed as dist import torch.nn as nn import torch.nn.parallel import torch.optim import torch.utils.data import torch.utils.data.distributed import torchvision import torchvision.models import torchvision.transforms as transforms import torch.nn.functional as F logger=logging.getLogger(__name__) logger.setLevel(logging.DEBUG) classes=('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') # https://github.com/pytorch/tutorials/blob/master/beginner_source/blitz/cifar10_tutorial.py#L118 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1=nn.Conv2d(3, 6, 5) self.pool=nn.MaxPool2d(2, 2) self.conv2=nn.Conv2d(6, 16, 5) self.fc1=nn.Linear(16 * 5 * 5, 120) self.fc2=nn.Linear(120, 84) self.fc3=nn.Linear(84, 10) def forward(self, x): x=self.pool(F.relu(self.conv1(x))) x=self.pool(F.relu(self.conv2(x))) x=x.view(-1, 16 * 5 * 5) x=F.relu(self.fc1(x)) x=F.relu(self.fc2(x)) x=self.fc3(x) return x def _train(args): is_distributed=len(args.hosts) > 1 and args.dist_backend is not None logger.debug("Distributed training - {}".format(is_distributed)) if is_distributed: # Initialize the distributed environment. world_size=len(args.hosts) os.environ['WORLD_SIZE']=str(world_size) host_rank=args.hosts.index(args.current_host) dist.init_process_group(backend=args.dist_backend, rank=host_rank, world_size=world_size) logger.info( 'Initialized the distributed environment: \'{}\' backend on {} nodes. '.format( args.dist_backend, dist.get_world_size()) + 'Current host rank is {}. Using cuda: {}. Number of gpus: {}'.format( dist.get_rank(), torch.cuda.is_available(), args.num_gpus)) device='cuda' if torch.cuda.is_available() else 'cpu' logger.info("Device Type: {}".format(device)) logger.info("Loading Cifar10 dataset") transform=transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset=torchvision.datasets.CIFAR10(root=args.data_dir, train=True, download=False, transform=transform) train_loader=torch.utils.data.DataLoader(trainset, batch_size=args.batch_size, shuffle=True, num_workers=args.workers) testset=torchvision.datasets.CIFAR10(root=args.data_dir, train=False, download=False, transform=transform) test_loader=torch.utils.data.DataLoader(testset, batch_size=args.batch_size, shuffle=False, num_workers=args.workers) logger.info("Model loaded") model=Net() if torch.cuda.device_count() > 1: logger.info("Gpu count: {}".format(torch.cuda.device_count())) model=nn.DataParallel(model) model=model.to(device) criterion=nn.CrossEntropyLoss().to(device) optimizer=torch.optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum) for epoch in range(0, args.epochs): running_loss=0.0 for i, data in enumerate(train_loader): # get the inputs inputs, labels=data inputs, labels=inputs.to(device), labels.to(device) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs=model(inputs) loss=criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 2000 == 1999: # print every 2000 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss=0.0 print('Finished Training') return _save_model(model, args.model_dir) def _save_model(model, model_dir): logger.info("Saving the model.") path=os.path.join(model_dir, 'model.pth') # recommended way from http://pytorch.org/docs/master/notes/serialization.html torch.save(model.cpu().state_dict(), path) def model_fn(model_dir): logger.info('model_fn') device="cuda" if torch.cuda.is_available() else "cpu" model=Net() if torch.cuda.device_count() > 1: logger.info("Gpu count: {}".format(torch.cuda.device_count())) model=nn.DataParallel(model) with open(os.path.join(model_dir, 'model.pth'), 'rb') as f: model.load_state_dict(torch.load(f)) return model.to(device) if __name__ == '__main__': parser=argparse.ArgumentParser() parser.add_argument('--workers', type=int, default=2, metavar='W', help='number of data loading workers (default: 2)') parser.add_argument('--epochs', type=int, default=2, metavar='E', help='number of total epochs to run (default: 2)') parser.add_argument('--batch-size', type=int, default=4, metavar='BS', help='batch size (default: 4)') parser.add_argument('--lr', type=float, default=0.001, metavar='LR', help='initial learning rate (default: 0.001)') parser.add_argument('--momentum', type=float, default=0.9, metavar='M', help='momentum (default: 0.9)') parser.add_argument('--dist-backend', type=str, default='gloo', help='distributed backend (default: gloo)') # The parameters below retrieve their default values from SageMaker environment variables, which are # instantiated by the SageMaker containers framework. # https://github.com/aws/sagemaker-containers#how-a-script-is-executed-inside-the-container parser.add_argument('--hosts', type=str, default=ast.literal_eval(os.environ['SM_HOSTS'])) parser.add_argument('--current-host', type=str, default=os.environ['SM_CURRENT_HOST']) parser.add_argument('--model-dir', type=str, default=os.environ['SM_MODEL_DIR']) parser.add_argument('--data-dir', type=str, default=os.environ['SM_CHANNEL_TRAINING']) parser.add_argument('--num-gpus', type=int, default=os.environ['SM_NUM_GPUS']) _train(parser.parse_args())

ステップ 3: コンテナを構築する

  1. JupyterLab ホームディレクトリで Jupyter Notebook を開きます。新しいノートブックを開くには、[新しい起動] アイコンを選択し、次に [ノートブック] セクションで [conda_pytorch_p36] を選択します。

  2. 最初のノートブックセルで次のコマンドを実行して、docker_test_folder ディレクトリに変更します。

    % cd ~/SageMaker/docker_test_folder

    これにより、次のように現在のディレクトリが返されます。

    ! pwd

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

  3. Docker にログインして、ベースコンテナにアクセスします。

    ! aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com
  4. Docker コンテナを構築するには、次の Docker ビルドコマンド (最後のスペースとピリオドも含めます) を実行します。

    ! docker build -t pytorch-extended-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: コンテナをテストする

  1. ノートブックインスタンスでローカルにコンテナをテストするには、Jupyter ノートブックを開きます。[New Launcher] (新しいランチャー) を選択し、conda_pytorch_p39 フレームワークで [Notebook] (ノートブック) を選択します。残りのコードスニペットは Jupyter ノートブックインスタンスから実行する必要があります。

  2. CIFAR-10 データセットをダウンロードします。

    import torch import torchvision import torchvision.transforms as transforms def _get_transform(): return transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) def get_train_data_loader(data_dir='/tmp/pytorch/cifar-10-data'): transform=_get_transform() trainset=torchvision.datasets.CIFAR10(root=data_dir, train=True, download=True, transform=transform) return torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) def get_test_data_loader(data_dir='/tmp/pytorch/cifar-10-data'): transform=_get_transform() testset=torchvision.datasets.CIFAR10(root=data_dir, train=False, download=True, transform=transform) return torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2) trainloader=get_train_data_loader('/tmp/pytorch-example/cifar-10-data') testloader=get_test_data_loader('/tmp/pytorch-example/cifar-10-data')
  3. role を Jupyter ノートブックの作成に使用したロールに設定します。これは SageMaker 推定器を設定するために使用されます。

    from sagemaker import get_execution_role role=get_execution_role()
  4. 次のサンプルスクリプトをノートブックのコードセルに貼り付けて、拡張コンテナを使用して SageMaker 推定器を設定します。

    from sagemaker.estimator import Estimator hyperparameters={'epochs': 1} estimator=Estimator( image_uri='pytorch-extended-container-test', role=role, instance_count=1, instance_type='local', hyperparameters=hyperparameters ) estimator.fit('file:///tmp/pytorch-example/cifar-10-data')
  5. コードセルを実行します。このテストでは、トレーニングの環境設定、環境変数に使用された値、データのソース、およびトレーニング中に得られた損失と正確性が出力されます。

ステップ 5: Amazon Elastic Container Registry (Amazon ECR) にコンテナをプッシュする

  1. このローカルモードテストが正常に実行されたら、Docker コンテナを Amazon ECR にプッシュし、それを使用してトレーニングジョブを実行できます。

    ノートブックセルで次のコマンドラインを実行します。

    %%sh # Specify an algorithm name algorithm_name=pytorch-extended-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) 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 # Log into Docker 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}
  2. コンテナをプッシュしたら、 SageMaker 環境内のどこからでも Amazon ECR イメージを呼び出すことができます。その次のノートブックセルで、以下のコード例を実行します。

    SageMaker Studio でこのトレーニングコンテナを使用して視覚化機能を使用する場合は、Studio ノートブックセルで次のコードを実行して、トレーニングコンテナの Amazon ECR イメージを呼び出すこともできます。

    import boto3 client=boto3.client('sts') account=client.get_caller_identity()['Account'] my_session=boto3.session.Session() region=my_session.region_name algorithm_name="pytorch-extended-container-test" ecr_image='{}.dkr.ecr.{}.amazonaws.com/{}:latest'.format(account, region, algorithm_name) ecr_image # This should return something like # 12-digits-of-your-account.dkr.ecr.us-east-2.amazonaws.com/tf-2.2-test:latest
  3. 前のステップからecr_image取得した を使用して、 SageMaker 推定器オブジェクトを設定します。次のコードサンプルは、 SageMaker PyTorch推定器を設定します。

    import sagemaker from sagemaker import get_execution_role from sagemaker.estimator import Estimator estimator=Estimator( image_uri=ecr_image, role=get_execution_role(), base_job_name='pytorch-extended-container-test', instance_count=1, instance_type='ml.p2.xlarge' ) # start training estimator.fit() # deploy the trained model predictor=estimator.deploy(1, instance_type)

ステップ 6: リソースをクリーンアップする

入門サンプルを終了したときにリソースをクリーンアップするには
  1. SageMaker コンソールを開き、ノートブックインスタンス を選択しRunScriptNotebookInstanceアクション を選択し、停止 を選択します。インスタンスが停止するまで、数分かかる場合があります。

  2. インスタンスの [Status] (ステータス) が[Stopped] (停止) に変化したら、[Actions] (アクション)、[Delete] (削除) の順に選択し、ダイアログボックスで [Delete] (削除) を選択します。インスタンスが削除されるまで、数分かかる場合があります。ノートブックインスタンスが削除されると、テーブルには表示されなくなります。

  3. Amazon S3 コンソールを開き、モデルのアーティファクトとトレーニングデータセットを保存するために作成したバケットを削除します。

  4. IAM コンソールを開き、IAM ロールを削除します。アクセス許可ポリシーを作成した場合は、それも削除することができます。

    注記

    Docker コンテナは、実行後に自動的にシャットダウンします。削除する必要はありません。