{ "cells": [ { "cell_type": "markdown", "id": "d92539de", "metadata": {}, "source": [ "## SageMaker SDK のバージョンを最新にしておく" ] }, { "cell_type": "code", "execution_count": null, "id": "5b151364", "metadata": { "scrolled": true }, "outputs": [], "source": [ "pip install sagemaker -U" ] }, { "cell_type": "code", "execution_count": null, "id": "d3963dd2", "metadata": {}, "outputs": [], "source": [ "import sagemaker\n", "print(sagemaker.__version__)" ] }, { "cell_type": "markdown", "id": "4848683c", "metadata": {}, "source": [ "## 1-1. Hello SageMaker Training!\n", "AWS のマネジメントコンテナ(AWS Deep Learning Container / SageMaker Scikit-learn Container) で Training Job を実行する\n", "各マネジメントコンテナ用のクラスが SageMaker SDK に準備されていて、その class をインスタンス化( `estimator` 変数でインスタンス化する)する際に引数でバージョンを指定することで利用するコンテナが確定する\n", "\n", "| class | コンテナ | コンテナ詳細 | \n", "| ---- | ---- | ---- | \n", "| [`sagemaker.tensorflow.TensorFlow`](https://sagemaker.readthedocs.io/en/stable/frameworks/tensorflow/sagemaker.tensorflow.html#sagemaker.tensorflow.estimator.TensorFlow) | TensorFlow | [利用可能なバージョン一覧及びソース](https://github.com/aws/deep-learning-containers/blob/master/available_images.md) | \n", "| [`sagemaker.pytorch.PyTorch`](https://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/sagemaker.pytorch.html#sagemaker.pytorch.estimator.PyTorch) | PyTorch |^|\n", "| [`sagemaker.pytorch.MXNet`](https://sagemaker.readthedocs.io/en/stable/frameworks/mxnet/sagemaker.mxnet.html#sagemaker.mxnet.estimator.MXNet) | MXNet |^|\n", "| [`sagemaker.pytorch.HuggingFace`](https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/sagemaker.huggingface.html#sagemaker.huggingface.HuggingFace) | HuggingFace |^|\n", "| [`sagemaker.sklearn.SKLearn`](https://sagemaker.readthedocs.io/en/stable/frameworks/sklearn/sagemaker.sklearn.html) | scikit-learn |[コンテナソース](https://github.com/aws/sagemaker-scikit-learn-container)|\n" ] }, { "cell_type": "markdown", "id": "58d97523", "metadata": {}, "source": [ "### 用意したコードの確認\n", "`Hello SageMaker Training` という文字列を出力して終えるだけの簡単なスクリプトを予め準備" ] }, { "cell_type": "code", "execution_count": null, "id": "9585ee2c", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-1/hello_sagemaker_training.py" ] }, { "cell_type": "markdown", "id": "2b3de3a1", "metadata": {}, "source": [ "#### 書き換えたい人向け" ] }, { "cell_type": "code", "execution_count": null, "id": "89ec96b8", "metadata": {}, "outputs": [], "source": [ "# %%writefile ./src/1-1/hello_sagemaker_training.py\n", "# print('Hello SageMaker Training')\n", "# exit()" ] }, { "cell_type": "markdown", "id": "5d29ee76", "metadata": {}, "source": [ "### TensorFlow コンテナで実行\n", "各フレームワーク(TensorFlow, PyTorch, MXNet, HuggingFace, scikit-learn) 毎に用意された estimator class で ジョブを定義し、estimator インスタンスを生成する。\n", "* `entry_point` 引数に用意したコードを指定することで使える\n", "* フレームワーク毎のクラス + py_version + framework_version + instance_type で使用するコンテナイメージが確定する。\n", " * 以下の場合は python3.8 が入った TensorFlow が 2.7.1 の CPU に最適化されたコンテナイメージ \n", " 763104351884.dkr.ecr.{REGION}.amazonaws.com/tensorflow-training:2.7.1-cpu-py38-ubuntu20.04-sagemaker\n", " * estimator インスタンスの `training_image_uri` メソッドでコンテナイメージの URI を確認できる\n", "* estimator 生成時に `image_uri` 引数を指定することで直接コンテナイメージを指定することもできる" ] }, { "cell_type": "code", "execution_count": null, "id": "8cfcc9f7", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# TensorFlow コンテナで Training Job\n", "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='./src/1-1/hello_sagemaker_training.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='ml.m5.xlarge',\n", " role=sagemaker.get_execution_role()\n", ")\n", "print(f'トレーニングに使用するコンテナイメージは {estimator.training_image_uri()} です')\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "48048f4e", "metadata": {}, "source": [ "### PyTorch コンテナで実行\n", "他のフレームワークでも使い方は全く一緒" ] }, { "cell_type": "code", "execution_count": null, "id": "c1abfa27", "metadata": {}, "outputs": [], "source": [ "# PyTorch コンテナで Training Job\n", "from sagemaker.pytorch import PyTorch\n", "estimator = PyTorch(\n", " entry_point='./src/1-1/hello_sagemaker_training.py',\n", " py_version='py38', \n", " framework_version='1.9.1',\n", " instance_count=1,\n", " instance_type='ml.m5.xlarge',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "48543aa8", "metadata": {}, "source": [ "### MXNet コンテナで実行" ] }, { "cell_type": "code", "execution_count": null, "id": "e73763e7", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# MXNet コンテナで Training Job\n", "from sagemaker.mxnet import MXNet\n", "estimator = MXNet(\n", " entry_point='./src/1-1/hello_sagemaker_training.py',\n", " py_version='py37', \n", " framework_version='1.8.0',\n", " instance_count=1,\n", " instance_type='ml.m4.xlarge',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "e76cb185", "metadata": {}, "source": [ "### HuggingFace コンテナで実行" ] }, { "cell_type": "code", "execution_count": null, "id": "23bda80e", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# HuggingFace コンテナで Training Job\n", "# 注意 : GPU のクオータ緩和をしないと使えません\n", "# from sagemaker.huggingface import HuggingFace\n", "# estimator = HuggingFace(\n", "# entry_point='./src/1-1/hello_sagemaker_training.py',\n", "# py_version='py37', \n", "# transformers_version='4.6.1',\n", "# tensorflow_version='2.4.1',\n", "# instance_count=1,\n", "# instance_type='ml.g4dn.xlarge',\n", "# role=sagemaker.get_execution_role()\n", "# )\n", "# estimator.fit()" ] }, { "cell_type": "markdown", "id": "70f25995", "metadata": {}, "source": [ "### scikit-learn コンテナで実行" ] }, { "cell_type": "code", "execution_count": null, "id": "929b623a", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# scikit-learn コンテナで Training Job\n", "from sagemaker.sklearn import SKLearn\n", "estimator = SKLearn(\n", " entry_point='./src/1-1/hello_sagemaker_training.py',\n", " py_version='py3', \n", " framework_version='0.23-1',\n", " instance_count=1,\n", " instance_type='ml.c5.xlarge',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "9fd75090", "metadata": {}, "source": [ "### ジョブの実行結果確認\n", "使用したコンテナイメージ URI や実行時間、使ったコードのありかなどが記録される" ] }, { "cell_type": "code", "execution_count": null, "id": "8e96be4c", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# ジョブ定義や実行結果を確認\n", "estimator.latest_training_job.describe()" ] }, { "cell_type": "markdown", "id": "94cf8d8c", "metadata": {}, "source": [ "### イメージ URI を指定してトレーニングを実行する場合" ] }, { "cell_type": "code", "execution_count": null, "id": "9b3032b8", "metadata": { "scrolled": true }, "outputs": [], "source": [ "from sagemaker.sklearn import SKLearn\n", "estimator = SKLearn(\n", " entry_point='./src/1-1/hello_sagemaker_training.py',\n", " image_uri = estimator.latest_training_job.describe()['AlgorithmSpecification']['TrainingImage'],\n", " instance_count=1,\n", " instance_type='ml.c5.xlarge',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "1d2066e4", "metadata": {}, "source": [ "## 1-2. データをトレーニングインスタンスに持ち込む\n", "### 1-2-1. 単一のファイルを持ち込む\n", "#### 持ち込むデータの確認\n", "算数の計算問題を記載したデータを用意" ] }, { "cell_type": "code", "execution_count": null, "id": "8db4d553", "metadata": {}, "outputs": [], "source": [ "with open('./data/1-2-1/calc.txt','rt') as f:\n", " input_text_lines = f.read()\n", "print('---データの確認---')\n", "print(input_text_lines)\n", "print('---計算結果---')\n", "for input_text in input_text_lines.split('\\n'):\n", " print(eval(input_text))" ] }, { "cell_type": "markdown", "id": "6b71a367", "metadata": {}, "source": [ "##### 書き換えたい方向け" ] }, { "cell_type": "code", "execution_count": null, "id": "50510fc2", "metadata": {}, "outputs": [], "source": [ "# text = \"\"\"3+4\n", "# 4-2\n", "# 5*1\n", "# 6/2\"\"\"\n", "# with open('./data/1-2-1/calc.txt','wt') as f:\n", "# f.write(text)" ] }, { "cell_type": "markdown", "id": "74ff0117", "metadata": {}, "source": [ "#### 持ち込むデータを S3 にアップロード\n", "`upload_data` メソッドを使うと S3 にデータをアップロードできる。返り値は S3 の URI" ] }, { "cell_type": "code", "execution_count": null, "id": "7cd53438", "metadata": {}, "outputs": [], "source": [ "# S3 にデータをアップロード\n", "import sagemaker\n", "input_s3_uri = sagemaker.session.Session().upload_data(path='./data/1-2-1/calc.txt', bucket=sagemaker.session.Session().default_bucket(), key_prefix='training/1-2-1')\n", "print(input_s3_uri)" ] }, { "cell_type": "markdown", "id": "da82feb8", "metadata": {}, "source": [ "#### 用意したコードを確認\n", "* トレーニングインスタンスに連携するデータはデフォルトだと環境変数 `SM_CHANNEL_TRAINING`(=`/opt/ml/input/training`) の値が示すディレクトリに格納される\n", "* SM_CHANNEL_TRAINING にあるファイルを読み込み、1 行ずつデータを読み込んで文字列を数式として解釈して演算するコードを準備" ] }, { "cell_type": "code", "execution_count": null, "id": "03bb28e3", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-2-1/calc.py" ] }, { "cell_type": "markdown", "id": "12605d1a", "metadata": {}, "source": [ "#### トレーニングジョブの実行\n", "データをトレーニングインスタンスに持ち込む場合は fit メソッドの引数に持ち込みたい S3 URI を指定指定" ] }, { "cell_type": "code", "execution_count": null, "id": "0c124230", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# トレーニングジョブの実行\n", "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='./src/1-2-1/calc.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit(input_s3_uri)" ] }, { "cell_type": "markdown", "id": "b850b53b", "metadata": {}, "source": [ "### 1-2-2. ディレクトリごとトレーニングインスタンスに持ち込む\n", "#### 持ち込むデータの確認\n", "算数の計算問題が書かれたデータを同じディレクトリに 2 つファイルを準備" ] }, { "cell_type": "code", "execution_count": null, "id": "26f5ac34", "metadata": {}, "outputs": [], "source": [ "FILE_NAME = './data/1-2-2/calc1.txt'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())\n", "\n", "FILE_NAME = './data/1-2-2/calc2.txt'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())\n" ] }, { "cell_type": "markdown", "id": "092d9af4", "metadata": {}, "source": [ "##### 書き換えたい方向け" ] }, { "cell_type": "code", "execution_count": null, "id": "92544cdc", "metadata": {}, "outputs": [], "source": [ "# text1 = \"\"\"2+2\n", "# 3-1\"\"\"\n", "# text2 = \"\"\"5*1\n", "# 16/2\"\"\"\n", "# with open('./data/1-2-2/calc1.txt','wt') as f:\n", "# f.write(text1)\n", "# with open('./data/1-2-2/calc2.txt','wt') as f:\n", "# f.write(text2)" ] }, { "cell_type": "markdown", "id": "b1132a97", "metadata": {}, "source": [ "#### 実行コードの確認\n", "複数ファイルに対応できるよう for 文で SM_CHANNEL_TRAINING が示すディレクトリを順繰りに処理する" ] }, { "cell_type": "code", "execution_count": null, "id": "b749c813", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-2-2/calc.py" ] }, { "cell_type": "markdown", "id": "39fbca7d", "metadata": {}, "source": [ "### トレーニングジョブの実行\n", "* upload_data でディレクトリを指定するとそのディレクトリの全ファイルを S3 にアップロードする\n", " * `.ipynb_checkpoint/` なども転送されるので注意\n", " * 返り値はファイル群を配置した prefix を返す\n", "* fit の引数には S3 URI の prefix 以下を入れればその prefix 以下のファイルをトレーニングインスタンスに転送する\n", " * 転送先は変わらず環境変数 `SM_CHANNEL_TRAINING` が示すディレクトリ" ] }, { "cell_type": "code", "execution_count": null, "id": "80b7e608", "metadata": { "scrolled": true }, "outputs": [], "source": [ "import sagemaker\n", "from sagemaker.tensorflow import TensorFlow\n", "input_s3_uri = sagemaker.session.Session().upload_data(path='./data/1-2-2/', bucket=sagemaker.session.Session().default_bucket(), key_prefix='training/1-2-2')\n", "print(input_s3_uri)\n", "estimator = TensorFlow(\n", " entry_point='./src/1-2-2/calc.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit(input_s3_uri)" ] }, { "cell_type": "markdown", "id": "59dd8916", "metadata": {}, "source": [ "### 1-2-3. 複数のディレクトリをトレーニングに持ち込む\n", "#### 持ち込むデータの確認\n", "`fold1` と `fold2` という 2 つのディレクトリにそれぞれ算数の演算データを配置" ] }, { "cell_type": "code", "execution_count": null, "id": "b0d6cf4e", "metadata": {}, "outputs": [], "source": [ "FILE_NAME = './data/1-2-3/fold1/calc.txt'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())\n", "\n", "FILE_NAME = './data/1-2-3/fold2/calc.txt'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "id": "f9934178", "metadata": {}, "source": [ "##### 書き換えたい方向け" ] }, { "cell_type": "code", "execution_count": null, "id": "2c70fe91", "metadata": {}, "outputs": [], "source": [ "# text1 = \"\"\"1+2\n", "# 3+4\"\"\"\n", "# text2 = \"\"\"5+6\n", "# 7+8\"\"\"\n", "# with open('./data/1-2-3/fold1/calc.txt','wt') as f:\n", "# f.write(text1)\n", "# with open('./data/1-2-3/fold2/calc.txt','wt') as f:\n", "# f.write(text2)" ] }, { "cell_type": "markdown", "id": "90f34cec", "metadata": {}, "source": [ "#### 実行コードの確認\n", "複数の S3 データソースをトレーニングインスタンスに持ち込む場合は、`SM_CHANNEL_{CHANNEL 名}` という環境変数が示すディレクトリに配置される。 \n", "CHANNEL 名についてはユーザが `fit` メソッドを呼ぶときに決められる。 \n", "`SM_CHANNELS` という環境変数に CHANNEL 名一覧が格納されるので、どのような CHANNEL 名が来てもいいように対応しておく\n" ] }, { "cell_type": "code", "execution_count": null, "id": "dbcca443", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-2-3/calc.py" ] }, { "cell_type": "markdown", "id": "4e957550", "metadata": {}, "source": [ "#### 持ち込むデータを S3 にアップロード\n", "ディレクトリごとに `upload_data` メソッドを実行する。" ] }, { "cell_type": "code", "execution_count": null, "id": "7f2912ad", "metadata": {}, "outputs": [], "source": [ "import sagemaker\n", "fold1_input_s3_uri = sagemaker.session.Session().upload_data(path='./data/1-2-3/fold1/', bucket=sagemaker.session.Session().default_bucket(), key_prefix='training/1-2-3/fold1')\n", "fold2_input_s3_uri = sagemaker.session.Session().upload_data(path='./data/1-2-3/fold2/', bucket=sagemaker.session.Session().default_bucket(), key_prefix='training/1-2-3/fold2')\n", "print(fold1_input_s3_uri, fold2_input_s3_uri)" ] }, { "cell_type": "markdown", "id": "7ddea110", "metadata": {}, "source": [ "#### トレーニングジョブの実行\n", "複数のデータをトレーニングインスタンスに持ち込む場合は、`fit` メソッドの引数に dict 型で持ち込むデータを入力する。 \n", "dict のキーはトレーニングインスタンスの channel 名になり、値は持ち込む S3 のデータを入力する。" ] }, { "cell_type": "code", "execution_count": null, "id": "7ace16a3", "metadata": { "scrolled": true }, "outputs": [], "source": [ "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='./src/1-2-3/calc.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit({\n", " 'fold1':fold1_input_s3_uri,\n", " 'fold2':fold2_input_s3_uri,\n", "})" ] }, { "cell_type": "markdown", "id": "2ef5540b", "metadata": {}, "source": [ "## 1-3. アーティファクトを S3 に転送する\n", "### 用意したデータの確認\n", "同じディレクトリに csv を 2 つ用意する。" ] }, { "cell_type": "code", "execution_count": null, "id": "a5b1566a", "metadata": {}, "outputs": [], "source": [ "FILE_NAME = './data/1-3/data1.csv'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())\n", "\n", "FILE_NAME = './data/1-3/data2.csv'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "id": "7dc05476", "metadata": {}, "source": [ "#### 書き換えたい方向け" ] }, { "cell_type": "code", "execution_count": null, "id": "7e0e6d6e", "metadata": {}, "outputs": [], "source": [ "# text1=\"\"\"1,2\n", "# 3,4\"\"\"\n", "# text2=\"\"\"5,6\n", "# 7,8\"\"\"\n", "# with open('./data/1-3/data1.csv','wt') as f:\n", "# f.write(text1)\n", "# with open('./data/1-3/data2.csv','wt') as f:\n", "# f.write(text2)" ] }, { "cell_type": "markdown", "id": "1638e552", "metadata": {}, "source": [ "### 用意したコードの確認\n", "用意したデータを連結する処理を記述。\n", "連結したデータは、環境変数 `SM_MODEL_DIR`(=`/opt/ml/model/`) が示すディレクトリに配置するか、環境変数 `SM_OUTPUT_DATA_DIR`(=`/opt/ml/output/data/`) が示すディレクトリに保存すると自動でトレーニング終了時に S3 に転送される。\n", "`SM_MODEL_DIR` と `SM_OUTPUT_DATA_DIR` の使い分けは、`SM_MODEL_DIR` は機械学習のモデルを保存し、それ以外(中間生成物など)は `SM_OUTPUT_DATA_DIR` に保存する。 \n", "`SM_MODEL_DIR` に保存したモデルは Amazon SageMaker Hosting でそのまま推論環境のホスティングに使うことができる。" ] }, { "cell_type": "code", "execution_count": null, "id": "d2399987", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-3/concat.py" ] }, { "cell_type": "markdown", "id": "a0b4a0eb", "metadata": {}, "source": [ "### トレーニングジョブの実行\n", "アーティファクトを連携するのに estimator 側は特に特記することはなし" ] }, { "cell_type": "code", "execution_count": null, "id": "6e0a8aa8", "metadata": { "scrolled": true }, "outputs": [], "source": [ "import sagemaker\n", "input_s3_uri = sagemaker.session.Session().upload_data(path='./data/1-3/', bucket=sagemaker.session.Session().default_bucket(), key_prefix='training/1-3')\n", "print(input_s3_uri)\n", "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='./src/1-3/concat.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit(input_s3_uri)" ] }, { "cell_type": "markdown", "id": "811abc41", "metadata": {}, "source": [ "### ジョブの詳細確認\n", "保存した model.tar.gz や、ジョブの詳細は `describe` メソッドで確認できる" ] }, { "cell_type": "code", "execution_count": null, "id": "7168ab4e", "metadata": { "scrolled": true }, "outputs": [], "source": [ "estimator.latest_training_job.describe()" ] }, { "cell_type": "markdown", "id": "c01ced36", "metadata": {}, "source": [ "### アーティファクトの確認\n", "アーティファクトが保存されているか、download_data メソッドを使って手元にダウンロードして確認する。 \n", "tar.gz に固められるため、解凍して中身を確認する" ] }, { "cell_type": "code", "execution_count": null, "id": "14cbdc27", "metadata": {}, "outputs": [], "source": [ "import tarfile\n", "prefix = estimator.latest_training_job.describe()['ModelArtifacts']['S3ModelArtifacts'].replace(f's3://{sagemaker.session.Session().default_bucket()}/','')\n", "sagemaker.session.Session().download_data('./', sagemaker.session.Session().default_bucket(), key_prefix=prefix)\n", "with tarfile.open('./model.tar.gz', 'r') as f:\n", " f.extractall()\n", "with open('./output.csv','rt') as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "id": "b3a65dc7", "metadata": {}, "source": [ "## 1-4. ライブラリの追加\n", "マネジメントコンテナには機械学習で必要なほとんどのライブラリがあるが、追加したいケースもある。コンテナイメージをいじらずにトレーニングジョブ実行時にライブラリをインストールする仕組みがあるのでそのやり方を以下に記載。\n", "### 用意したコード\n", "トレーニングコードと同じディレクトリに pip で利用する `requirements.txt` を準備しておく。" ] }, { "cell_type": "code", "execution_count": null, "id": "691c14ca", "metadata": {}, "outputs": [], "source": [ "FILE_NAME = './src/1-4/requirements.txt'\n", "print(f'check {FILE_NAME}')\n", "with open(FILE_NAME) as f:\n", " print(f.read())\n", "\n", "FILE_NAME = './src/1-4/my_module.py'\n", "print(f'check {FILE_NAME}') \n", "!pygmentize {FILE_NAME}\n", "\n", "FILE_NAME = './src/1-4/bs4_version_check.py'\n", "print(f'check {FILE_NAME}') \n", "!pygmentize {FILE_NAME}" ] }, { "cell_type": "markdown", "id": "e871f502", "metadata": {}, "source": [ "#### 書き換えたい方向け" ] }, { "cell_type": "code", "execution_count": null, "id": "e4af7bab", "metadata": {}, "outputs": [], "source": [ "requirements = \"\"\"beautifulsoup4==4.9.3\"\"\"\n", "module = \"\"\"def version_check(module):\n", " print(f' {module.__name__} version is {module.__version__}')\n", " return None\"\"\"\n", "code = \"\"\"import bs4, my_module\n", "my_module.version_check(bs4)\n", "exit()\"\"\"\n", "with open('./src/1-4/requirements.txt','wt') as f:\n", " f.write(requirements)\n", "with open('./src/1-4/my_module.py','wt') as f:\n", " f.write(module)\n", "with open('./src/1-4/bs4_version_check.py','wt') as f:\n", " f.write(code)" ] }, { "cell_type": "markdown", "id": "7dcb5b7d", "metadata": {}, "source": [ "### トレーニングジョブを実行\n", "`source_dir` 引数で `requirements.txt` とトレーニングコードを配置したディレクトリを指定する。 \n", "トレーニングコードも `requirements.txt` も `source_dir` のルートに配置する必要があるので注意。 \n", "また、`source_dir` で指定したファイルは全てトレーニングインスタンスに転送され、そのディレクトリ(環境変数 PWD で指定される `/opt/ml/code`)がカレントディレクトリになるので、自作モジュール(`model.py`など)も同ディレクトリ以下に配置しておくとトレーニングインスタンスで使用できる。\n", "標準出力をよく見るとトレーニングコード実行前に pip で `requirements.txt` の内容をインストールしていることがわかる。" ] }, { "cell_type": "code", "execution_count": null, "id": "fdb5a429", "metadata": { "scrolled": true }, "outputs": [], "source": [ "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='bs4_version_check.py',\n", " source_dir='./src/1-4',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role()\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "3c5779c2", "metadata": {}, "source": [ "## 1-5 ハイパーパラメータをコードの外部から入力\n", "トレーニングコードの外からハイパーパラメータを与えて、ハイパーパラメータの試行錯誤を行いたいケースがあるが、Amazon SageMaker Training はその機能を当然サポートしている。 \n", "### 用意したコード\n", "ハイパーパラメータを Amazon SageMaker Training で外部から与える場合、トレーニングコード側がその値を取得する方法は 2 つありどちらを使っても良い。 \n", "1 つ目はコマンドライン引数で受け取れるので以下の例のように argparse などを用いて、parse して利用する。 \n", "2 つめは環境変数 SM_HPS の値を読み込む。JSON 形式の文字列で格納されているので、`hps = json.loads(os.environ.get('SM_HPS'))` のように書くと `hps` 変数に一度に格納することができる。 \n", "いずれの方法でもデフォルト値を設定したほうが便利なので、add_argument メソッドに defalut 引数を入れるか、hps.setdefault メソッドを利用する、のが良い。 \n", "以下は `argparse` を使った例で、数字を 2 つ、演算子を 1 つ与えて、足し算か引き算を行うコード。`model_dir` 引数は、必ずコマンドライン引数に入るため、parse しないとエラーで落ちるために入れている。" ] }, { "cell_type": "code", "execution_count": null, "id": "f98ea243", "metadata": {}, "outputs": [], "source": [ "!pygmentize ./src/1-5/hp_calc.py" ] }, { "cell_type": "code", "execution_count": null, "id": "790d3aa9", "metadata": { "scrolled": true }, "outputs": [], "source": [ "from sagemaker.tensorflow import TensorFlow\n", "estimator = TensorFlow(\n", " entry_point='./src/1-5/hp_calc.py',\n", " py_version='py38', \n", " framework_version='2.7.1',\n", " instance_count=1,\n", " instance_type='local',\n", " role=sagemaker.get_execution_role(),\n", " hyperparameters={\n", " 'first-num':5,\n", " 'second-num':2,\n", " 'operator':'m'\n", " }\n", ")\n", "estimator.fit()" ] }, { "cell_type": "markdown", "id": "85adeffc", "metadata": {}, "source": [ "## トレーニングジョブの標準出力\n", "* 標準出力やメトリクスは Amazon CloudWatch に自動で連携される\n", "* ここでは Amazon CloudWatch Logs で最後に実行した標準出力の内容を表示する。\n", "* メトリクスについてはマネジメントコンソールで確認するのが簡単。" ] }, { "cell_type": "code", "execution_count": null, "id": "a1635fe3", "metadata": {}, "outputs": [], "source": [ "import boto3\n", "logs = boto3.client('logs')\n", "log_group_name = '/aws/sagemaker/TrainingJobs'\n", "latest_logstream_name = logs.describe_log_streams(\n", " logGroupName=log_group_name,\n", " orderBy='LastEventTime',\n", " descending=True\n", ")['logStreams'][0]['logStreamName']\n", "logs.get_log_events(\n", " logGroupName=log_group_name,\n", " logStreamName=latest_logstream_name,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "9a666955", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "instance_type": "ml.t3.medium", "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_python3" }, "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 }