{ "cells": [ { "cell_type": "markdown", "id": "b7988a32", "metadata": {}, "source": [ "# Amazon SageMaker 持ち込みPyTorchコンテナによる MNIST の学習(ノートブックclassic用)" ] }, { "cell_type": "markdown", "id": "276f719d", "metadata": {}, "source": [ "### 1.背景\n", "\n", "MNISTは、手書き文字の分類に広く使用されているデータセットです。 70,000個のラベル付きの28x28ピクセルの手書き数字のグレースケール画像で構成されています。 データセットは、60,000個のトレーニング画像と10,000個のテスト画像に分割されます。 手書きの数字 0から9の合計10のクラスがあります。 \n", "\n", "このチュートリアルでは、SageMaker のマネージドコンテナイメージ以外に、独自のコンテナイメージを持ち込める持ち込みのことを学習していただくために、持ち込みの独自コンテナを使用して SageMaker で MNIST モデルをトレーニングする方法を示します。" ] }, { "cell_type": "markdown", "id": "b3aea93a", "metadata": {}, "source": [ "### 2.セットアップ\n", "\n", "SageMaker セッションを作成し、設定を開始し\n", "Dockerfileから、持ち込み用のコンテンナを作成していきます。\n", "Dockerfileはcontainerディレクトリ配下に配置されていて、PyTorchコンテナにrequirements.txt(pip installするパッケージリスト)経由でSageMaker Training Toolkitをpipインストールするように記述されています。\n", "\n", "SageMaker Training Toolkitは、どのDockerコンテナにも簡単に追加でき、SageMakerと互換性のあるモデルをトレーニングすることができるパッケージです。詳細は下記をご確認ください。\n", "https://github.com/aws/sagemaker-training-toolkit\n", "\n", "最後にdocker buildコマンドによりビルドしていきます。" ] }, { "cell_type": "code", "execution_count": null, "id": "849ba57c", "metadata": {}, "outputs": [], "source": [ "import boto3" ] }, { "cell_type": "code", "execution_count": null, "id": "434c5464", "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%time\n", "\n", "IMAGE_NAME = 'toolkit-container-pytorch'\n", "TAG=':1.11'\n", "\n", "REGION = boto3.session.Session().region_name\n", "\n", "%cd ./container\n", "!docker build -t {IMAGE_NAME}{TAG} .\n", "%cd ../" ] }, { "cell_type": "markdown", "id": "11fd123e", "metadata": {}, "source": [ "### 3.Amazon ECRリポジトリの作成とDockerImageの登録\n", "\n", "Amazon ECRにsagemaker-toolkit-container-pytorchというレポジトリを作成し、ノートブックインスタンスに作成したDockerImageをdocker pushコマンドでコミットしていきます。\n", "\n", "なお、ノートブックインスタンスに設定しているIAM RoleにSagemakerFullAccessポリシーをアタッチしている場合(ノートブックインスタンス起動時にdefaultでアタッチされています)はレポジトリ名にsagemakerというキーワードを含める必要がありますのでご注意ください" ] }, { "cell_type": "code", "execution_count": null, "id": "e808459f", "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%time\n", "\n", "MY_ACCOUNT_ID = boto3.client('sts').get_caller_identity().get('Account')\n", "\n", "MY_ECR_ENDPOINT = f'{MY_ACCOUNT_ID}.dkr.ecr.{REGION}.amazonaws.com/'\n", "\n", "MY_REPOSITORY_URI = f'{MY_ECR_ENDPOINT}sagemaker-{IMAGE_NAME}'\n", "MY_IMAGE_URI = f'{MY_REPOSITORY_URI}{TAG}'\n", "\n", "!$(aws ecr get-login --region {REGION} --registry-ids {MY_ACCOUNT_ID} --no-include-email)\n", " \n", "# リポジトリの作成\n", "!aws ecr delete-repository --repository-name sagemaker-{IMAGE_NAME} --force # 同名のリポジトリがあった場合削除\n", "!aws ecr create-repository --repository-name sagemaker-{IMAGE_NAME}\n", " \n", "!docker tag {IMAGE_NAME}{TAG} {MY_IMAGE_URI}\n", "!docker push {MY_IMAGE_URI}\n", "\n", "print(f'コンテナイメージは {MY_IMAGE_URI} へ登録されています。')" ] }, { "cell_type": "markdown", "id": "a12b7ffc", "metadata": {}, "source": [ "### 4.セットアップ\n", "\n", "学習およびモデルデータに使用する S3 バケットとプレフィックスは、ノートブックインスタンス、トレーニング、およびホスティングと同じリージョン内にある必要があります。\n", "\n", "データへの学習およびホスティングアクセスを提供するために使用される IAM ロール arn を用います。 ノートブックインスタンス、学習インスタンス、および/またはホスティングインスタンスに複数のロールが必要な場合は、 sagemaker.get_execution_role() を、適切な IAM ロール arn 文字列に置き換えてください。" ] }, { "cell_type": "code", "execution_count": null, "id": "1ad59e54", "metadata": {}, "outputs": [], "source": [ "import sagemaker\n", "from sagemaker.pytorch import PyTorch\n", "bucket = sagemaker.session.Session().default_bucket()\n", "prefix = 'sagemaker/DEMO-pytorch-mnist-byoc'\n", "role = sagemaker.get_execution_role()\n", "print(bucket)" ] }, { "cell_type": "markdown", "id": "3a83ac4d", "metadata": {}, "source": [ "このノートブックのコードは、以前からのノートブックインスタンスで実行する場合と、SageMaker Studio のノートブックで実行する場合とで挙動が異なります。以下のセルを実行することで、いまの実行環境が以前からのノートブックインスタンスなのか、SageMaker Studio のノートブックなのかを判定して、on_studioに記録します。この結果に基づいて、以降のノートブックの実行を次のように変更します。\n", "\n", "データセットの展開先を変更します。SageMaker Studio を利用する場合、home のディレクトリは EFS をマウントして実現されており、データセットを展開する際にやや時間を要します。そこで home 以外のところへ展開するようにします。" ] }, { "cell_type": "markdown", "id": "c7c350a2", "metadata": {}, "source": [ "### 5.データの取得" ] }, { "cell_type": "code", "execution_count": null, "id": "6a87723c", "metadata": {}, "outputs": [], "source": [ "!aws s3 cp s3://fast-ai-imageclas/mnist_png.tgz . --no-sign-request\n", "!tar -xvzf mnist_png.tgz" ] }, { "cell_type": "code", "execution_count": null, "id": "2f1e2254", "metadata": {}, "outputs": [], "source": [ "from torchvision import datasets, transforms\n", "from torch.utils.data import DataLoader\n", "import torch\n", "import os\n", "\n", "data_dir = 'data'\n", "training_dir = 'mnist_png/training'\n", "test_dir = 'mnist_png/testing'\n", "\n", "os.makedirs(data_dir, exist_ok=True)\n", "\n", "training_data = datasets.ImageFolder(root=training_dir,\n", " transform=transforms.Compose([\n", " transforms.Grayscale(),\n", " transforms.ToTensor(),\n", " transforms.Normalize((0.1307,), (0.3081,))]))\n", "test_data = datasets.ImageFolder(root=test_dir,\n", " transform=transforms.Compose([\n", " transforms.Grayscale(),\n", " transforms.ToTensor(),\n", " transforms.Normalize((0.1307,), (0.3081,))]))\n", "\n", "training_data_loader = DataLoader(training_data, batch_size=len(training_data))\n", "training_data_loaded = next(iter(training_data_loader))\n", "torch.save(training_data_loaded, os.path.join(data_dir, 'training.pt'))\n", "\n", "test_data_loader = DataLoader(test_data, batch_size=len(test_data))\n", "test_data_loaded = next(iter(test_data_loader))\n", "torch.save(test_data_loaded, os.path.join(data_dir, 'test.pt'))" ] }, { "cell_type": "markdown", "id": "abab1caf", "metadata": {}, "source": [ "### 6.データをS3にアップロードする\n", "\n", "データセットを S3 にアップロードするには、 sagemaker.Session.upload_data 関数を使用します。 戻り値として入力した S3 のロケーションは、後で学習ジョブを実行するときに使用します。" ] }, { "cell_type": "code", "execution_count": null, "id": "b6423d81", "metadata": {}, "outputs": [], "source": [ "inputs = sagemaker.session.Session().upload_data(path=data_dir, bucket=bucket, key_prefix=prefix)\n", "print('input spec (in this case, just an S3 path): {}'.format(inputs))" ] }, { "cell_type": "markdown", "id": "879f6591", "metadata": {}, "source": [ "### 7.学習を開始する\n", "学習の条件を設定するため、Estimator クラスの子クラスの PyTorch オブジェクトを作成します。 ここでは、PyTorchスクリプト、IAMロール、および(ジョブごとの)ハードウェア構成を渡す PyTorch Estimator を定義しています。また合わせてentry_point を指定することで、依存するスクリプト群をコンテナにコピーして、学習時に使用することが可能です。\n", "\n", "トレーニングジョブを開始する際、Amazon S3のどこにソースが格納されているか、起動するモジュールは何かをsagemaker-training-toolkitライブラリに知らせる必要があります。今回はPython SDKのフレームワーク使用していますので自動的に設定されています。\n", "Estimator Classを利用する際は必要になりますのでご注意ください。\n", "\n", "最後に、Amazon SageMaker Python SDKで定義されている汎用Estimatorオブジェクトのfit()メソッドを呼び出すことで、学習ジョブを実行することができます" ] }, { "cell_type": "code", "execution_count": null, "id": "b43311d6", "metadata": {}, "outputs": [], "source": [ "estimator = PyTorch(\n", " entry_point='train.py',\n", " image_uri=MY_IMAGE_URI,\n", " role=sagemaker.get_execution_role(),\n", " hyperparameters={\n", " 'lr':0.01,\n", " 'batch-size':16\n", " },\n", " instance_count=1,\n", " instance_type='ml.g4dn.xlarge',\n", ")\n", "estimator.fit({'training': inputs})\n", "\n", "#Estimatorクラスで学習する場合\n", "#estimator = sagemaker.estimator.Estimator(\n", "# image_uri=MY_IMAGE_URI,\n", "# role=sagemaker.get_execution_role(),\n", "# hyperparameters={\n", "# 'lr':0.01,\n", "# 'batch-size':16,\n", "# 'sagemaker_program' : 'train.py',\n", "# 'sagemaker_submit_directory' : 's3://'+bucket+'/'+estimator._current_job_name+'/source/sourcedir.tar.gz'\n", "# },\n", "# instance_count=1,\n", "# instance_type='ml.g4dn.xlarge',\n", "#)\n", "#estimator.fit({'training': inputs})" ] } ], "metadata": { "kernelspec": { "display_name": "conda_pytorch_p36", "language": "python", "name": "conda_pytorch_p36" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.13" } }, "nbformat": 4, "nbformat_minor": 5 }