{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SageMaker JumpStart Fine-Tune ハンズオン"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 目次\n",
"1. [概要](#anchor1)\n",
"1. [準備](#anchor2)\n",
"1. [Amazon SageMaker Ground Truthを用いたラベリング](#anchor3)\n",
"1. [Fine-Tuneの準備](#anchor4)\n",
"1. [Fine-Tuneの実行](#anchor5)\n",
"1. [デプロイ](#anchor6)\n",
"1. [推論](#anchor7)\n",
"1. [リソースの削除](#anchor8)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## 1. 概要\n",
"Amazon SageMaker JumpStartは、機械学習をすばやく簡単に開始するのに役立ちます。機械学習ワークロードを容易に開始するために、SageMaker JumpStartは最も一般的なユースケース向けの一連のソリューションを提供し、数回クリックするだけで簡単にデプロイできます。この学習モデルに独自のデータセットを加えたい場合、Fine-Tuneを行うことができます。このプロセスは転移学習とも呼ばれ、小さなデータセット・短いトレーニング時間でより正確なモデルを作成することができます。本ハンズオンでは、まずSageMaker Ground Truthを用いて学習モデルに加えたい独自のデータセットにラベル付けを行います。その後、予め用意された物体検出の学習モデルに独自のデータセットを加えてFine-Tuneを行います。\n",
"\n",
"---\n",
"\n",
"## 2. 準備\n",
"### 2.1. S3バケットの作成\n",
"本ハンズオンで扱うAmazon SageMaker Ground Truth, Amazon SageMaker JumpStart Fine-Tuneでは、データのやり取りをS3バケットを用いて行います。本節では以降の作業で必要なS3バケットの作成を行います。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import boto3\n",
"import uuid\n",
"S3_BUCKET = 'jumpstart-finetune-handson' + str(uuid.uuid4()) # 一意の文字列にするためUUIDを付与\n",
"region = boto3.session.Session().region_name\n",
"location = {'LocationConstraint': region}\n",
"s3_client = boto3.client('s3')\n",
"response = s3_client.create_bucket(Bucket=S3_BUCKET,CreateBucketConfiguration=location)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"次に、S3バケットに必要なフォルダを作成します。 \n",
"作成するS3バケットのディレクトリ構成は以下となります。\n",
"+ /S3Bucket\n",
" + /bounding_box\n",
" + /ground_truth\n",
" + /training\n",
" + /images\n",
" + /test \n",
"\n",
"作成するS3バケットのディレクトリは、それぞれ以下の用途で用いられます。\n",
"\n",
"__/bounding_box__ \n",
"+ Ground Truthの入力・出力データを格納するディレクトリです。/ground_truthに出力データを、/training/imagesにラベル付けするデータを格納します。 \n",
"\n",
"__/test__ \n",
"+ SageMaker JumpStartの学習モデルをFine-tuneした後、推論に用いるデータを格納します。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"BOUNDING_BOX_PREFIX = 'bounding_box'\n",
"GROUND_TRUTH_PREFIX = os.path.join(BOUNDING_BOX_PREFIX, 'ground_truth')\n",
"BB_TRAINING_PREFIX =os.path.join(BOUNDING_BOX_PREFIX, 'training')\n",
"INPUT_IMAGES_PREFIX = os.path.join(BB_TRAINING_PREFIX, 'images')\n",
"TEST_PREFIX = 'test'\n",
"\n",
"res = s3_client.put_object(Bucket=S3_BUCKET, Key=(BOUNDING_BOX_PREFIX+'/'))\n",
"res = s3_client.put_object(Bucket=S3_BUCKET, Key=(GROUND_TRUTH_PREFIX+'/'))\n",
"res = s3_client.put_object(Bucket=S3_BUCKET, Key=(BB_TRAINING_PREFIX+'/'))\n",
"res = s3_client.put_object(Bucket=S3_BUCKET, Key=(INPUT_IMAGES_PREFIX+'/'))\n",
"res = s3_client.put_object(Bucket=S3_BUCKET, Key=(TEST_PREFIX+'/'))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2.2. 画像データのアップロード\n",
"前節で作成したS3バケットに、画像データをアップロードします。まずは、tar.gzファイルを解凍します。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!tar -zxvf images.tar.gz --no-same-owner"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"以下の手順で、画像データをS3バケットにアップロードします。本画像データはGround Truthでのラベリング、SageMaker JumpStartのFine-Tuneに用います。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# images/train下の.jpgの一覧を取得し、S3にアップロード\n",
"train_dir = os.path.join('images','train')\n",
"images = os.listdir(path=train_dir)\n",
"\n",
"for image in images:\n",
" destination = os.path.join(INPUT_IMAGES_PREFIX,image)\n",
" s3_client.upload_file(os.path.join(train_dir,image), S3_BUCKET, destination)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 3. Amazon SageMaker Ground Truthを用いたラベリング\n",
"本章ではAmazon SageMaker Ground Truthを用いたラベリング作業を行います。**ラベリング作業を実施せず、SageMaker JumpStart Fine-Tuneのみを試したい場合は、本章は飛ばして4章の[Fine-Tuneの準備](#anchor4)へ進んで下さい。** \n",
"\n",
"Amazon SageMaker Ground Truth はフルマネージド型のデータラベル付けサービスで、機械学習のための高精度なトレーニングデータセットを簡単に構築することができます。カスタム、または組み込み済みのデータラベル付けワークフローを使用して、SageMaker Ground Truth コンソールから数分でデータのラベル付けを開始することができます。本章では、Fine-Tuneさせる画像データをGround Truthでラベル付けします。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### 3.1. Manifestファイルの準備\n",
"本節ではGround Truthで必要なManifestファイルを作成した後、S3にアップロードします。Manifestファイルはラベリングジョブの入力データセットとして使用されます。詳細は、[ドキュメント](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/sms-input-data-input-manifest.html)を参照下さい。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"def create_manifest(s3_bucket, image_path):\n",
" '''\n",
" Ground Truthでのラベリングに必要なmanifestファイルを生成します。\n",
" \n",
" Parameters\n",
" ----------\n",
" s3_bucket : str\n",
" manifestファイルを作成する画像データが格納されているS3Bucket名\n",
" \n",
" image_path : str\n",
" manifestファイルを作成する画像データのパス\n",
"\n",
" Returns:\n",
" -------\n",
" manifest_file : str\n",
" 作成したmanifestファイル名\n",
" '''\n",
" img_files = get_file_list_from_s3(s3_bucket, image_path)\n",
"\n",
" TOKEN = 'source-ref'\n",
" manifest_file = os.path.join('data', 'manifest.json')\n",
" if not (os.path.exists('data')):\n",
" os.mkdir('data')\n",
" with open(manifest_file, 'w') as fout:\n",
" for img_file in img_files:\n",
" fname = f's3://{s3_bucket}/{img_file.key}'\n",
" fout.write(f'{{\"{TOKEN}\": \"{fname}\"}}\\n')\n",
"\n",
" return manifest_file\n",
"\n",
"def get_file_list_from_s3(s3_bucket, image_path):\n",
" '''\n",
" S3に格納されている画像ファイルパスリストを取得する\n",
" \n",
" Parameters\n",
" ----------\n",
" s3_bucket : str\n",
" manifestファイルを作成する画像データが格納されているS3Bucket名\n",
" \n",
" image_path : str\n",
" manifestファイルを作成する画像データのパス\n",
"\n",
" Returns:\n",
" -------\n",
" img_files : list\n",
" S3に格納されている画像ファイルパスリスト\n",
" '''\n",
" s3_rec = boto3.resource('s3')\n",
" bucket = s3_rec.Bucket(s3_bucket)\n",
" objs = list(bucket.objects.filter(Prefix=image_path))\n",
" img_files = objs[1:] # first item is the folder name\n",
" n_imgs = len(img_files)\n",
" print(f'there are {n_imgs} images \\n')\n",
" return img_files\n",
" \n",
"\n",
"def upload_manifest(s3_bucket, prefix, manifest_file):\n",
" '''\n",
" manifestファイルをS3へアップロードします。\n",
"\n",
" Parameters\n",
" ----------\n",
" s3_bucket : str\n",
" manifestファイルを格納するS3Bucket名\n",
" \n",
" prefix : str\n",
" manifestファイルを格納するprefix名\n",
" \n",
" manifest_file : str\n",
" manifestファイル名\n",
"\n",
" '''\n",
"\n",
" s3_rec = boto3.resource('s3')\n",
" destination = os.path.join(prefix, 'manifest.json')\n",
" print(f'uploading manifest file to {destination} \\n')\n",
" s3_rec.meta.client.upload_file(manifest_file, s3_bucket, destination)\n",
"\n",
"man_file = create_manifest(S3_BUCKET, INPUT_IMAGES_PREFIX)\n",
"upload_manifest(S3_BUCKET, BOUNDING_BOX_PREFIX, man_file)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.2. ワーカーの登録\n",
"本ハンズオンではSageMaker Ground Truthで画像データをラベリングするために、ワーカーとしてプライベートチームを作成します(プライベートチーム以外にもワーカーとして選択することが可能です。その他のワーカーの選択肢については[SageMakerのドキュメント](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/sms-getting-started-step3.html)を参照してください。)。本節ではプライベートチームを作成します。\n",
"\n",
"1. **[SageMaker](https://console.aws.amazon.com/sagemaker/home)**のコンソール画面へアクセスし、左側のナビゲーションから**Ground Truth**を展開し、**ラベリングワークフォース**を選択します。\n",
"1. 画面上部の**プライベート**を選択し、**プライベートチームを作成**をクリックします。\n",
"1. 任意の**チーム名**を入力し、**ワーカーの追加**で**新しいAmazon Cognitoユーザーグループを作成する**を選択、最後に**プライベートチームを作成**をクリックします。\n",
"1. **ワーカー**欄にある**新しいワーカーを招待**をクリックします。\n",
"1. 今回のハンズオンでラベリングを実施するワーカーのメールアドレスを記載します。アドレスを複数登録する際、カンマ区切りで入力して下さい。\n",
"1. 上記で作成した**プライベートチーム**を押下した後、**ワーカー**を選択し、**チームにワーカーを追加**を押下します。\n",
"1. 手順3で作成した**プライベートチーム**名を選択した後、**ワーカー**を押下します。その後、**チームにワーカーを追加**を選択し、ワーカー一覧から今回のラベリング作業を実施させたいワーカーを選択します。\n",
"\n",
"以上でワーカーの登録は終了です。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.3 ラベリングジョブの作成\n",
"1. **[SageMaker](https://console.aws.amazon.com/sagemaker/home)**のコンソール画面へアクセスし、左側のナビゲーションから**Ground Truth**を展開し、**ラベリングジョブ**を選択します。\n",
"1. 画面上部にある**ラベリングジョブの作成**を押下します。\n",
"1. **ジョブ名**に**jumpstart-handson-labeljob**と記入します。**入力データのセットアップ**では**手動によるデータのセットアップ**を選択します。\n",
"1. **入力データセットの場所**を設定します。**S3の参照**を押下し、本ハンズオンで作成したS3バケットを指定し、[3.1 Manifestファイルの準備](#anchor3.1)で作成したmanifestファイル(bounding_box/manifest.json)を指定します。**出力データセットの場所**は[2. S3バケットの作成](#anchor2)で作成したground_truthディレクトリ(bounding_box/ground_truth)を指定します。\n",
"1. **IAMロール**でリストを展開し、**Create a new role**を選択します。**特定のS3バケット**を選択し、[2. S3バケットの作成](#anchor2)で作成した**S3バケット**名を指定し、**作成**ボタンを押下します。\n",
"1. **タスクの選択**で**境界ボックス**を選択し、**次へ**ボタンを押下します。\n",
"1. **ワーカータイプ**で**プライベート**を選択します。3.3で作成したワーカーチームを選択します。\n",
"1. **境界ボックスラベリングツール**欄にタスクの簡単な説明を入力します(例:For labeling usb cable.)。その後、**ラベル**にモデルへ追加したい画像データに必要なラベルを追加します。ラベルは最大50個まで追加することができます。本ハンズオンではusb-a, usb-b, lightningの3種類をラベルとして追加します。\n",
"1. 画面右下の**作成**ボタンを押下します。\n",
"1. ワーカーとして登録したメールアドレスに招待メールが届いていることを確認してください。メールに記載されているリンクを押下し、ユーザー名、パスワードを入力してラベリング画面へ進み、ラベリング作業を実施して下さい。(ラベリングジョブが画面一覧に表示されるまで少し時間がかかる場合があります。何も表示されていなかった場合は少し時間が経ってから再度試して下さい。)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.4 Groud Truthから出力されたoutput.manifestの取得\n",
"Ground Truthでラベリングした情報が記載されているoutput.manifestをS3から取得します。本ファイルはFine-Tuneを行うために必要なannotation.jsonを作成する際に使用します。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"LABELING_JOB_NAME = \"jumpstart-handson-labeljob\" # 独自のラベリングジョブ名にした場合はここを変更してください。\n",
"OUTPUT_MANIFEST_S3_PATH = os.path.join(GROUND_TRUTH_PREFIX, LABELING_JOB_NAME, \"manifests\", \"output\", \"output.manifest\")\n",
"s3 = boto3.resource('s3')\n",
"bucket = s3.Bucket(S3_BUCKET)\n",
"bucket.download_file(OUTPUT_MANIFEST_S3_PATH, os.path.join('data', 'output.manifest'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 4.Fine-Tuneの準備\n",
"本章ではモデルへ追加する独自のデータセットを、Fine-Tune可能な形式へ処理・変換します。本ハンズオンでは、Jump StartのVISIONモデルである'SSD MobileNet 1.0'を扱います。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.1.Fine-Tune実施に必要なJSONファイルの作成\n",
"ここではFine-Tuneを実施するために必要なannotations.jsonファイルを作成します。Fine-Tuneを実施する各モデルの**Fine-tune the Model on a New Dataset**の記載を参考にJSONファイルを作成します。\n",
"(annotations.jsonが作成されるまで少し時間が掛かります。)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# annotations.jsonを扱うクラスを定義\n",
"class AnnotationsJson:\n",
" '''annotaions.jsonを扱うクラス\n",
" Parameters\n",
" ----------\n",
" records : list\n",
" output.manifestの各行を辞書型で読み込みリスト化したもの\n",
" jobname : str\n",
" Ground Truthのラベリングジョブ名\n",
"\n",
" Attributes\n",
" ----------\n",
" self.__data : list\n",
" annotations.jsonに書き込むJSONデータ\n",
" \n",
" '''\n",
" def __init__(self, records, jobname):\n",
" self.__data = self.__generate_annotations_json(records, jobname)\n",
" \n",
" @property\n",
" def data(self):\n",
" return self.__data\n",
" \n",
" def save(self, path):\n",
" '''\n",
" annotaions.jsonを保存する\n",
" \n",
" Parameters\n",
" ----------\n",
" path : str\n",
" annotations.jsonを保存するパス\n",
" \n",
" '''\n",
" with open(path, 'w') as f:\n",
" json.dump(self.__data, f)\n",
" \n",
" def __generate_annotations_json(self, records, jobname):\n",
" '''\n",
" annotions.jsonに書き込むデータを作成する。\n",
" \n",
" Parameters\n",
" ----------\n",
" records : list\n",
" output.manifestの各行ごとのデータ\n",
" jobname : str\n",
" ラベリングジョブ名\n",
" \n",
" Return\n",
" ------\n",
" data : dict\n",
" annotations.jsonに書き込むデータ\n",
" \n",
" '''\n",
" data = []\n",
" image_id = 0\n",
" images = []\n",
" annotations =[]\n",
" for record in records:\n",
" record_json = json.loads(record)\n",
" images.append(self.__set_images(record_json, jobname, image_id))\n",
"\n",
" for class_map in record_json[jobname]['annotations']:\n",
" annotations.append(self.__set_annotations(class_map, image_id))\n",
" image_id += 1\n",
" data = dict()\n",
" data['images'] = images\n",
" data['annotations'] = annotations\n",
" return data\n",
" \n",
" def __set_images(self, record, jobname, image_id):\n",
" '''annotations['images']の値を生成する\n",
" Parameters\n",
" ----------\n",
" record : list\n",
" output.manifestの1行分データ\n",
" jobname : str\n",
" Ground Truthのラベリングジョブ名\n",
" image_id : int\n",
" 画像ID\n",
" \n",
" Return\n",
" ------\n",
" images : dict\n",
" annotations['images']の値\n",
" '''\n",
" filename = record['source-ref'].split('/')[-1]\n",
" class_map = record[jobname]\n",
" images = dict()\n",
" images['file_name'] = filename\n",
" # class_map['image_size']は辞書要素一つのリストなので[0]で取り出し\n",
" images['height'] = class_map['image_size'][0]['height']\n",
" images['width'] = class_map['image_size'][0]['width']\n",
" images['id'] = image_id\n",
"\n",
" return images\n",
" \n",
" def __set_annotations(self, classmap, image_id):\n",
" '''annotations['annotaions']の値を生成する\n",
" Parameters\n",
" ----------\n",
" classmap : dict\n",
" ラベリングジョブで付与したannotations情報\n",
" image_id : int\n",
" 画像ID\n",
" \n",
" Return\n",
" ------\n",
" annotations : dict\n",
" annotations['annotaions']の値\n",
" \n",
" '''\n",
" \n",
" annotations = dict()\n",
" annotations['image_id'] = image_id\n",
" try:\n",
" annotations['bbox'] = self.__calc_bbox(classmap)\n",
" except Exception as e:\n",
" print('iamge_id is {}'.format(image_id))\n",
" print('classmap is {}'.format(classmap))\n",
" raise e\n",
" annotations['category_id'] = classmap['class_id']\n",
"\n",
" return annotations\n",
" \n",
" def __calc_bbox(self,bbox_gt):\n",
" '''bounding_boxの座標を、Ground Truth用からGluonCV用へ変換する。\n",
" Parameter\n",
" ---------\n",
" bbox_gt : dict\n",
" Grount Truthで算出したbounding boxの値が格納されている辞書\n",
" (top, left, width, height)\n",
" \n",
" Return\n",
" ------\n",
" bbox : list\n",
" GluonCV用bounding_box\n",
" [xmin, ymin, xmax, ymax]\n",
" '''\n",
"\n",
" xmin = bbox_gt['left']\n",
" ymin = bbox_gt['top']\n",
" xmax = bbox_gt['left'] + bbox_gt['width']\n",
" ymax = bbox_gt['top'] + bbox_gt['height']\n",
" bbox = [xmin, ymin, xmax, ymax]\n",
"\n",
" # 座標に負の値が含まれていないか確認\n",
" if any((x < 0 for x in bbox)):\n",
" raise Exception('Value of bbox is invelid : {}'.format(bbox))\n",
"\n",
" return bbox"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"# annotations.jsonを作成し、S3にアップロードする\n",
"fileopen = open(os.path.join('data', 'output.manifest'))\n",
"record = fileopen.readlines()\n",
"fileopen.close()\n",
"\n",
"# 3章を実施していないとLABELING_JOB_NAMEが未定義のため\n",
"try:\n",
" aj = AnnotationsJson(record, LABELING_JOB_NAME)\n",
"except NameError:\n",
" LABELING_JOB_NAME = \"jumpstart-handson-labeljob\"\n",
" aj = AnnotationsJson(record, LABELING_JOB_NAME)\n",
"\n",
"LOCAL_ANNOTAIONS_PATH = os.path.join('data', 'annotations.json')\n",
"aj.save(LOCAL_ANNOTAIONS_PATH)\n",
"\n",
"# 3章を実施していないとbucketが未定義のため\n",
"try:\n",
" bucket.upload_file(LOCAL_ANNOTAIONS_PATH, os.path.join(BB_TRAINING_PREFIX, 'annotations.json'))\n",
"except NameError:\n",
" s3 = boto3.resource('s3')\n",
" bucket = s3.Bucket(S3_BUCKET)\n",
" bucket.upload_file(LOCAL_ANNOTAIONS_PATH, os.path.join(BB_TRAINING_PREFIX, 'annotations.json'))\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 5.Fine-Tune\n",
"ここからFine-Tuneを実施していきます。以下の手順で進めて下さい。\n",
"1. 画面左側下から2番目のSageMaker JumpStart Launch Assetsアイコンを選択し、**Browse JumpStart**を押下します。\n",
"1. **Search**欄に**Object Detection**と入力し、表示された一覧の中から**SSD MobileNet 1.0**を選択します。\n",
"1. **Fine-tune Model**セクションの**Data Source**で**Find S3 bucket**を選択します。\n",
"1. **S3 bucket name**に2.1節で作成したS3バケット名を、**Dataset directory name**に**/bounding_box/training**を選択します。\n",
"1. **Deployment Configuration**で、適当な**SageMaker Training Instance**を選択します。\n",
"1. **Hyper Parameter**で、**Epoch**数を30に設定します。\n",
"1. **Train**ボタンを押下します。\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## 6.デプロイ\n",
"Fine-Tuneが終了したら、以下の手順でモデルをデプロイします。\n",
"1. 画面左側下から2番目のSageMaker JumpStart Launch Assetsアイコンを選択し、**Browse JumpStart**下のドロップダウンリストから**Training Jobs**を選択します。\n",
"1. 3章で実施した**Training Job**を選択します。**Deploy Model**セクションの**Deployment Configuration**を展開し、**ml.m5.large**を選択します。また、**Endpoint Name**欄に入力されている文字列をコピーしておきます。\n",
"1. **Deploy**ボタンを押下します。 \n",
"\n",
"これにてデプロイが実施されます。終了するまで5 ~ 10分かかります。\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## 7.推論\n",
"エンドポイントのstatusが**In Service**となったら、推論を実行し結果を確認してみましょう。事前に**Endpoint Name**の文字列をコピーしておいて下さい。推論で扱う画像を以下で表示します。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from IPython.core.display import HTML\n",
"import boto3\n",
"# 推論する画像をアップロード\n",
"test_dir = os.path.join('images','test')\n",
"img_jpg = os.path.join(test_dir, 'test.jpg')\n",
"destination = os.path.join(TEST_PREFIX, 'test.jpg')\n",
"s3_client.upload_file(img_jpg, S3_BUCKET, destination)\n",
"\n",
"HTML('
'\n",
" 'test.jpg')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"では、上記の画像をエンドポイントへクエリし、推論結果を取得してみましょう。以下の変数**endpoint_name**にデプロイしたモデルのEndpoint Nameを代入してから、コードを実行して下さい。\n",
"(うまく物体検出がされない場合、confidenceの値を変化させるか、再度エポック数を変更してトレーニングを行う、またはGround Truthでのラベリング処理から再度やり直して下さい。)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"confidence = 0.7 # 信頼度\n",
"\n",
"import json\n",
"def query_endpoint(input_img):\n",
" endpoint_name = '***' #Endpoint Nameの文字列を代入\n",
" client = boto3.client('runtime.sagemaker')\n",
" response = client.invoke_endpoint(EndpointName=endpoint_name, ContentType='application/x-image', Body=input_img)\n",
" model_predictions = json.loads(response['Body'].read())\n",
" return model_predictions\n",
"\n",
"with open(img_jpg, 'rb') as file: input_img = file.read()\n",
"model_predictions = query_endpoint(input_img)\n",
"\n",
"import matplotlib.patches as patches\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
"from PIL import Image\n",
"from PIL import ImageColor\n",
"colors = list(ImageColor.colormap.values())\n",
"\n",
"labels = ['type-a','type-b','lightning']\n",
"image_np = np.array(Image.open(img_jpg))\n",
"plt.figure(figsize=(20,20))\n",
"ax = plt.axes()\n",
"ax.imshow(image_np)\n",
"bboxes, classes, confidences = model_predictions['normalized_boxes'], model_predictions['classes'], model_predictions['scores']\n",
"for idx in range(len(bboxes)):\n",
" if confidences[idx] > confidence:\n",
" class_num = int(classes[idx])\n",
" left, bot, right, top = bboxes[idx]\n",
" x, w = [val * image_np.shape[1] for val in [left, right - left]]\n",
" y, h = [val * image_np.shape[0] for val in [bot, top - bot]]\n",
" color = colors[hash(class_num) % len(colors)]\n",
" rect = patches.Rectangle((x, y), w, h, linewidth=3, edgecolor=color, facecolor='none')\n",
" ax.add_patch(rect)\n",
" ax.text(x, y, '{} {:.0f}%'.format(labels[class_num], confidences[idx]*100), bbox=dict(facecolor='white', alpha=0.5))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8.リソースの削除\n",
"\n",
"1. 1章で作成したS3バケットを削除します。**[S3のコンソール画面](https://s3.console.aws.amazon.com/s3/)**から該当のバケットを選択し、**空にする**を押下しバケットの中身を空にした後、バケットを削除します。\n",
"2. 4章でデプロイしたエンドポイントを削除します。**Delete Endpoint**セクションの**Delete**ボタンを押下して下さい。\n",
"3. SageMaker Studioで立ち上がっているインスタンス・カーネルセッションを停止させます。画面左側上から3つ目の停止アイコンを押下し、本ハンズオンで用いたインスタンス・カーネルセッションを停止させます。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (Data Science)",
"language": "python",
"name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-west-2:236514542706:image/datascience-1.0"
},
"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.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}