masalibの日記

システム開発、運用と猫の写真ブログです

Amazon SageMakerで画像分類をしてみた

前回は本当に触ってみた程度でした・・・

masalib.hatenablog.com

f:id:masalib:20190622225433j:plain

今回も触ってみたです程度でSageMaker Examplesを実行しただけです。サンプルコードを写経したでけですが本当にしらない事だらけで勉強になりました

S3バケットの作成

バケットはsagemaker-masalib-test4で作りました 今回は作成するリージョンが重要でした。リージョンの場所を間違えるとパーミッションエラーが置きます

まずは表示のリージョンを「米国北部バージニア」を選択します

f:id:masalib:20190623233941j:plain

リージョン以外は前回と同じです トレーニングデータとか保存する領域を事前に作る sagemaker-masalib-test4という名前で作りました

Amazon SageMaker ノートブックインスタンスの作成

くどいですが表示のリージョンを「米国北部バージニア」を選択します

https://console.aws.amazon.com/sagemaker/

に行ってノートブックインスタンスの作成のボタンを押す

初めての場合は下記の画面 f:id:masalib:20190622220432j:plain

2回目以降は下記の画面

f:id:masalib:20190622220510j:plain

編集画面でsagemaker-masalib-test4
(画面は別の内容ですがsagemaker-masalib-test4で作りました)

f:id:masalib:20190622220700j:plain

下にスクロールするとPermissions and encryptionという項目のIAM ロールがある

f:id:masalib:20190622221313j:plain

新規作成を選択するとIAM作成画面が表示されるので作成した「sagemaker-masalib-test4」というバケットにする

f:id:masalib:20190623235705j:plain

作成されると、作成されたIAMロール名が表示されます インスタンスを作成するのボタンを押す

f:id:masalib:20190622221504j:plain

作成直後は「ステータス」が「Pending」になり作成が完了すると、「InService」になります。

f:id:masalib:20190622221844j:plain

サンプルを開いて修正する

「SageMaker Examples」タブを選択し、「Introduction to Amazon algorithms」から「Image-classification-lst-format.ipynb」の「Use」ボタンを押下します

f:id:masalib:20190624000128j:plainf:id:masalib:20190624000132j:plain

以下の2点を修正する

バケット

バケットを自分が作った「sagemaker-masalib-test4」に変更する

クリックすると展開されます

 %%time
 import boto3
 from sagemaker import get_execution_role
 from sagemaker.amazon.amazon_estimator import get_image_uri
 
 role = get_execution_role()
 
+bucket='sagemaker-masalib-test4' # customize to your bucket
 
 training_image = get_image_uri(boto3.Session().region_name, 'image-classification')

モデルのインスタンスタイプを変更する

レーニング結果からモデルを作るところのインスタンスタイプを変更する

ml.p2.xlarge -> ml.m4.xlarge

理由としては

今回は検証のみでそれほどパフォーマンスが必要ないため、エンドポイントを実行するインスタンスを「ml.p2.xlarge」から「ml.m4.xlarge」に変更します

クリックすると展開されます

 from time import gmtime, strftime
 
 timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
 endpoint_config_name = job_name_prefix + '-epc-' + timestamp
 endpoint_config_response = sage.create_endpoint_config(
     EndpointConfigName = endpoint_config_name,
     ProductionVariants=[{
+        'InstanceType':'ml.m4.xlarge',
         'InitialInstanceCount':1,
         'ModelName':model_name,
         'VariantName':'AllTraffic'}])
 
 print('Endpoint configuration name: {}'.format(endpoint_config_name))
 print('Endpoint configuration arn:  {}'.format(endpoint_config_response['EndpointConfigArn']))

サンプルを実行する

自分の勉強のために記載します

このサンプルのトレーニングは 転移学習モードでAmazon sagemaker画像分類アルゴリズムを使用して、 事前に学習済みのモデル(imagenetデータで学習済み)を微調整して、 新しいデータセットの分類を学習します。 事前に訓練されたモデルは、caltech-256データセットを使用して微調整されます。

caltech-256データセットは以下を参考にする http://www.vision.caltech.edu/Image_Datasets/Caltech256/

画像分類モデルの微調整

データを準備する

caltech 256データセットは257のカテゴリー(最後のものは雑然としたカテゴリーです)からのイメージから成り立っていて、
カテゴリーあたり最小80イメージと最大約800イメージで30kイメージを持っています。

画像分類アルゴリズムは、2種類の入力フォーマットをとることができる。
1つ目はRecordIOフォーマット(コンテンツタイプ:application / x-recordio)、
もう1つはlst フォーマット(コンテンツタイプ:application / x-image)です。
これら両方のフォーマットのファイルは
http://data.dmlc.ml/mxnet/data/caltech-256/
にあります。
この例では、トレーニングにlstフォーマットを使用し、
ここで指定されたトレーニング/検証分割を使用します。

クリックすると展開されます

import os
import urllib.request

def download(url):
    filename = url.split("/")[-1]
    if not os.path.exists(filename):
        urllib.request.urlretrieve(url, filename)


# Caltech-256 image files
download('http://www.vision.caltech.edu/Image_Datasets/Caltech256/256_ObjectCategories.tar')
!tar -xf 256_ObjectCategories.tar

# Tool for creating lst file
download('https://raw.githubusercontent.com/apache/incubator-mxnet/master/tools/im2rec.py')

以下はpythonではありません

クリックすると展開されます

%%bash

mkdir -p caltech_256_train_60
for i in 256_ObjectCategories/*; do
    c=`basename $i`
    mkdir -p caltech_256_train_60/$c
    for j in `ls $i/*.jpg | shuf | head -n 60`; do
        mv $j caltech_256_train_60/$c/
    done
done

python im2rec.py --list --recursive caltech-256-60-train caltech_256_train_60/
python im2rec.py --list --recursive caltech-256-60-val 256_ObjectCategories/

実行結果

001.ak47 0
002.american-flag 1
003.backpack 2
004.baseball-bat 3
005.baseball-glove 4
006.basketball-hoop 5
007.bat 6
008.bathtub 7
009.bear 8
010.beer-mug 9
011.billiards 10
012.binoculars 11

.lstファイルは、画像ファイルのリストを含む3列のタブ区切りファイルです。
最初の列は画像インデックスを指定し、2番目の列は画像のクラスラベルインデックスを指定し、3番目の列は画像ファイルの相対パスを指定します。

最初の列の画像インデックスは、すべての画像にわたって一意である必要があります。 ここではMXNetのim2recツールを使って画像リストファイルを作成します。 独自の方法で.lstファイルを作成することもできます。以下に.lstファイルの例を示します。

!head -n 3 ./caltech-256-60-train.lst > example.lst
f = open('example.lst','r')
lst_content = f.read()
print(lst_content)

実行結果

14204    236.000000  237.vcr/237_0068.jpg
14861   247.000000  248.yarmulke/248_0057.jpg
10123   168.000000  169.radio-telescope/169_0063.jpg


14204 236.000000 237.vcr/237_0068.jpg
 ↓
14204 ←画像インデックス
236.000000 ←画像のクラスラベルインデックス
237.vcr/237_0068.jpg ←画像ファイルの相対パス

間違えていたらすいません

独自の画像ファイルをトレーニングするときは、.lstファイルが上記と同じ形式になっていることを確認してください。
lstフォーマットインターフェースを使ってトレーニングするには、トレーニングと検証の両方のためのlstファイルを適切なフォーマットで渡すことが必須です。 データをトレーニング用に正しい形式で利用できるようになったら、
次のステップは、画像と.lstファイルをS3バケットにアップロードすることです。

クリックすると展開されます

# Four channels: train, validation, train_lst, and validation_lst
s3train = 's3://{}/image-classification/train/'.format(bucket)
s3validation = 's3://{}/image-classification/validation/'.format(bucket)
s3train_lst = 's3://{}/image-classification/train_lst/'.format(bucket)
s3validation_lst = 's3://{}/image-classification/validation_lst/'.format(bucket)

# upload the image files to train and validation channels
!aws s3 cp caltech_256_train_60 $s3train --recursive --quiet
!aws s3 cp 256_ObjectCategories $s3validation --recursive --quiet

# upload the lst files to train_lst and validation_lst channels
!aws s3 cp caltech-256-60-train.lst $s3train_lst --quiet
!aws s3 cp caltech-256-60-val.lst $s3validation_lst --quiet

上記は約3分ぐらいかかります

すべてのデータがS3バケットに格納されました。 画像とlstファイルは、画像分類アルゴリズムによってインターリーブ方式でRecordIOファイルに変換されます。

RecordIOファイルの作成に関する詳細は、
https://mxnet.incubator.apache.org/versions/master/
https://mxnet.incubator.apache.org/versions/master/faq/?highlight=im2rec
にあります。

クリックすると展開されます

%%bash
python im2rec.py --resize 256 --quality 90 --num-thread 16 caltech-256-60-val 256_ObjectCategories/
python im2rec.py --resize 256 --quality 90 --num-thread 16 caltech-256-60-train caltech_256_train_60/

RecordIOファイルを作成したら、トレーニングのためにそれらをトレインチャネルおよび検証チャネルにアップロードできます。

画像分類モデルの微調整

レーニングパラメータ

レーニングに設定する必要がある2種類のパラメータがあります。
最初のものはトレーニングジョブのためのパラメータです。これらが含まれます:

入力仕様:これらは、トレーニングデータが存在するパスを指定するトレーニングおよび検証チャネルです。
これらは "InputDataConfig"セクションで指定されています。設定する必要がある主なパラメータは、
入力データフォーマットに基づいて "application / x-recordio"または "application / x-image"に設定できる
"ContentType"と、バケットとフォルダを指定するS3Uriです。データが存在します。

出力指定:これは、 "OutputDataConfig"セクションで指定されています。トレーニング後に出力を保存できるパスを指定するだけです。

リソース構成:このセクションでは、 トレーニングを実行するインスタンスの種類と、 トレーニングに使用されるホストの数を指定します。 "InstanceCount"が1より大きい場合、トレーニングは分散的に実行されます。 上記の一連のパラメータとは別に、アルゴリズムに固有のハイパーパラメータがあります。

  • num_layers:ネットワークのレイヤ数(深さ)。このサンプルでは18を使用していますが、50、152などの他の値も使用できます。
  • image_shape:ネットワークの入力画像の寸法 'num_channels、height、width'。実際の画像サイズ以下にしてください。チャンネル数は実際の画像と同じでなければなりません。
  • num_training_samples:これはトレーニングサンプルの総数です。現在の分割のあるcaltechデータセットの場合は15240に設定されています。
  • num_classes:これは、新しいデータセットの出力クラスの数です。
  • Imagenetは1000の出力クラスでトレーニングされましたが、出力クラスの数は微調整のために変更することができます。
  • caltechでは、256のオブジェクトカテゴリと1のクラッタクラスがあるため、257を使用します。
  • mini_batch_size:各ミニバッチに使用されるトレーニングサンプルの数。分散トレーニングでは、バッチごとに使用されるトレーニングサンプルの数はN * mini_batch_sizeになります。ここで、Nはトレーニングが実行されるホストの数です。
  • エポック:トレーニングエポックの数。
  • learning_rate:トレーニングの学習率。
  • top_k:トレーニング中に上位kの精度を報告します。
  • サイズ変更:トレーニングに使用する前に画像のサイズを変更します。最も短い辺がこのパラメータになるように画像のサイズが変更されます。パラメータが設定されていない場合は、サイズ変更せずにトレーニングデータがそのまま使用されます。
  • checkpoint_frequency:モデルパラメータを保存する期間(エポック数)。
  • use_pretrained_model:転送学習に事前学習モデルを使用するには1に設定します

クリックすると展開されます

# The algorithm supports multiple network depth (number of layers). They are 18, 34, 50, 101, 152 and 200
# For this training, we will use 18 layers
num_layers = 18
# we need to specify the input image shape for the training data
image_shape = "3,224,224"
# we also need to specify the number of training samples in the training set
num_training_samples = 15240
# specify the number of output classes
num_classes = 257
# batch size for training
mini_batch_size = 128
# number of epochs
epochs = 6
# learning rate
learning_rate = 0.01
# report top_5 accuracy
top_k = 5
# resize image before training
resize = 256
# period to store model parameters (in number of epochs), in this case, we will save parameters from epoch 2, 4, and 6
checkpoint_frequency = 2
# Since we are using transfer learning, we set use_pretrained_model to 1 so that weights can be 
# initialized with pre-trained weights
use_pretrained_model = 1

レーニン

Amazon sagemaker CreateTrainingJob APIを使用してトレーニングを実行する

クリックすると展開されます

%%time
import time
import boto3
from time import gmtime, strftime


s3 = boto3.client('s3')
# create unique job name 
job_name_prefix = 'sagemaker-imageclassification-notebook'
timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
job_name = job_name_prefix + timestamp
training_params = \
{
    # specify the training docker image
    "AlgorithmSpecification": {
        "TrainingImage": training_image,
        "TrainingInputMode": "File"
    },
    "RoleArn": role,
    "OutputDataConfig": {
        "S3OutputPath": 's3://{}/{}/output'.format(bucket, job_name_prefix)
    },
    "ResourceConfig": {
        "InstanceCount": 1,
        "InstanceType": "ml.p2.xlarge",
        "VolumeSizeInGB": 50
    },
    "TrainingJobName": job_name,
    "HyperParameters": {
        "image_shape": image_shape,
        "num_layers": str(num_layers),
        "num_training_samples": str(num_training_samples),
        "num_classes": str(num_classes),
        "mini_batch_size": str(mini_batch_size),
        "epochs": str(epochs),
        "learning_rate": str(learning_rate),
        "top_k": str(top_k),
        "resize": str(resize),
        "checkpoint_frequency": str(checkpoint_frequency),
        "use_pretrained_model": str(use_pretrained_model)    
    },
    "StoppingCondition": {
        "MaxRuntimeInSeconds": 360000
    },
#Training data should be inside a subdirectory called "train"
#Validation data should be inside a subdirectory called "validation"
#The algorithm currently only supports fullyreplicated model (where data is copied onto each machine)
    "InputDataConfig": [
        {
            "ChannelName": "train",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3train,
                    "S3DataDistributionType": "FullyReplicated"
                }
            },
            "ContentType": "application/x-image",
            "CompressionType": "None"
        },
        {
            "ChannelName": "validation",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3validation,
                    "S3DataDistributionType": "FullyReplicated"
                }
            },
            "ContentType": "application/x-image",
            "CompressionType": "None"
        },
        {
            "ChannelName": "train_lst",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3train_lst,
                    "S3DataDistributionType": "FullyReplicated"
                }
            },
            "ContentType": "application/x-image",
            "CompressionType": "None"
        },
        {
            "ChannelName": "validation_lst",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3validation_lst,
                    "S3DataDistributionType": "FullyReplicated"
                }
            },
            "ContentType": "application/x-image",
            "CompressionType": "None"
        }
    ]
}
print('Training job name: {}'.format(job_name))
print('\nInput Data Location: {}'.format(training_params['InputDataConfig'][0]['DataSource']['S3DataSource']))

クリックすると展開されます

# create the Amazon SageMaker training job
sagemaker = boto3.client(service_name='sagemaker')
sagemaker.create_training_job(**training_params)

# confirm that the training job has started
status = sagemaker.describe_training_job(TrainingJobName=job_name)['TrainingJobStatus']
print('Training job current status: {}'.format(status))

try:
    # wait for the job to finish and report the ending status
    sagemaker.get_waiter('training_job_completed_or_stopped').wait(TrainingJobName=job_name)
    training_info = sagemaker.describe_training_job(TrainingJobName=job_name)
    status = training_info['TrainingJobStatus']
    print("Training job ended with status: " + status)
except:
    print('Training failed to start')
     # if exception is raised, that means it has failed
    message = sagemaker.describe_training_job(TrainingJobName=job_name)['FailureReason']
    print('Training failed with the following error: {}'.format(message))

training_info = sagemaker.describe_training_job(TrainingJobName=job_name)
status = training_info['TrainingJobStatus']
print("Training job ended with status: " + status)
print (training_info)

Training job ended with status: Completed

このメッセージが表示されればトレーニングが正常に完了した事になります。出力モデルがで指定された出力パスに格納されたことを意味します。このトレーニングには約20分ぐらいかかります

AWS SageMakerコンソールを使用して、トレーニングジョブに関する情報とステータスを表示することもできます。

f:id:masalib:20190624021639j:plainf:id:masalib:20190624021642j:plainf:id:masalib:20190624021645j:plainf:id:masalib:20190624021647j:plainf:id:masalib:20190624021649j:plainf:id:masalib:20190624021653j:plainf:id:masalib:20190624021656j:plainf:id:masalib:20190624021658j:plainf:id:masalib:20190624021701j:plainf:id:masalib:20190624021703j:plain
レーニング時のデータ

モデルをデプロイする

訓練されたモデルはそれ自身では何もしません。 今度はモデルを使用して推論を実行します。 このセクションにはいくつかのステップがあります。

  • モデル作成 - トレーニング出力用のモデル作成
  • バッチ変換 - バッチ推論を実行するための変換ジョブを作成します。

モデルを作成

クリックすると展開されます

%%time
import boto3
from time import gmtime, strftime

sage = boto3.Session().client(service_name='sagemaker') 

timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
model_name="image-classification-model" + timestamp
print(model_name)
info = sage.describe_training_job(TrainingJobName=job_name)
model_data = info['ModelArtifacts']['S3ModelArtifacts']
print(model_data)

hosting_image = get_image_uri(boto3.Session().region_name, 'image-classification')

primary_container = {
    'Image': hosting_image,
    'ModelDataUrl': model_data,
}

create_model_response = sage.create_model(
    ModelName = model_name,
    ExecutionRoleArn = role,
    PrimaryContainer = primary_container)

print(create_model_response['ModelArn'])

約8分ぐらいかかります

バッチ変換

作成したモデルを使用してSageMaker Batch Transformジョブを作成し、バッチ予測を実行します。

クリックすると展開されます

timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
batch_job_name="image-classification-model" + timestamp
batch_input = s3validation + "001.ak47/"
request = \
{
    "TransformJobName": batch_job_name,
    "ModelName": model_name,
    "MaxConcurrentTransforms": 16,
    "MaxPayloadInMB": 6,
    "BatchStrategy": "SingleRecord",
    "TransformOutput": {
        "S3OutputPath": 's3://{}/{}/output'.format(bucket, batch_job_name)
    },
    "TransformInput": {
        "DataSource": {
            "S3DataSource": {
                "S3DataType": "S3Prefix",
                "S3Uri": batch_input
            }
        },
        "ContentType": "application/x-image",
        "SplitType": "None",
        "CompressionType": "None"
    },
    "TransformResources": {
            "InstanceType": "ml.p2.xlarge",
            "InstanceCount": 1
    }
}

print('Transform job name: {}'.format(batch_job_name))
print('\nInput Data Location: {}'.format(batch_input))

クリックすると展開されます

sagemaker = boto3.client('sagemaker')
sagemaker.create_transform_job(**request)

print("Created Transform job with name: ", batch_job_name)

while(True):
    response = sagemaker.describe_transform_job(TransformJobName=batch_job_name)
    status = response['TransformJobStatus']
    if status == 'Completed':
        print("Transform job ended with status: " + status)
        break
    if status == 'Failed':
        message = response['FailureReason']
        print('Transform failed with the following error: {}'.format(message))
        raise Exception('Transform job failed') 
    time.sleep(30)

リアルタイム推論

推論エンドポイントを作成し、リアルタイム推論を実行します。

エンドポイント設定を作成して、そこからエンドポイントを作成する

エンドポイント設定の作成

エンドポイント設定ではモデルの展開に 必要なインスタンスタイプについて設定、 起動時には自動スケーリング設定します。

インスタンスタイプがml.m4.xlargeになっているけど
推論なのでもっと安いプランでもできると思う

from time import gmtime, strftime

timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
endpoint_config_name = job_name_prefix + '-epc-' + timestamp
endpoint_config_response = sage.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType':'ml.m4.xlarge',
        'InitialInstanceCount':1,
        'ModelName':model_name,
        'VariantName':'AllTraffic'}])

print('Endpoint configuration name: {}'.format(endpoint_config_name))
print('Endpoint configuration arn:  {}'.format(endpoint_config_response['EndpointConfigArn']))

エンドポイントを作成する

上記で定義した設定(EndpointConfigName)を指定して、 モデルを提供するエンドポイントを作成します。 最終的な結果は、検証して本番アプリケーションに 組み込むことができるエンドポイントです。 これには9〜11分かかります。

%%time
import time

timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
endpoint_name = job_name_prefix + '-ep-' + timestamp
print('Endpoint name: {}'.format(endpoint_name))

endpoint_params = {
    'EndpointName': endpoint_name,
    'EndpointConfigName': endpoint_config_name,
}
endpoint_response = sagemaker.create_endpoint(**endpoint_params)
print('EndpointArn = {}'.format(endpoint_response['EndpointArn']))

以下を実行するとエンドポイントの作成が完了してサービス開始されるのを待ちます 「Create endpoint ended with status: InService」というメッセージが表示されればOKです

GUIで待っても問題ないです

クリックすると展開されます

# get the status of the endpoint
response = sagemaker.describe_endpoint(EndpointName=endpoint_name)
status = response['EndpointStatus']
print('EndpointStatus = {}'.format(status))
    
try:
    sagemaker.get_waiter('endpoint_in_service').wait(EndpointName=endpoint_name)
finally:
    resp = sagemaker.describe_endpoint(EndpointName=endpoint_name)
    status = resp['EndpointStatus']
    print("Arn: " + resp['EndpointArn'])
    print("Create endpoint ended with status: " + status)

    if status != 'InService':
        message = sagemaker.describe_endpoint(EndpointName=endpoint_name)['FailureReason']
        print('Training failed with the following error: {}'.format(message))
        raise Exception('Endpoint creation did not succeed')

推論を実行する

データをダウンロードして実行します

クリックすると展開されます

import boto3
runtime = boto3.Session().client(service_name='runtime.sagemaker') 

!wget -O /tmp/test.jpg http://www.vision.caltech.edu/Image_Datasets/Caltech256/images/008.bathtub/008_0007.jpg
file_name = '/tmp/test.jpg'
# test image
from IPython.display import Image
Image(file_name)  
import json
import numpy as np
with open(file_name, 'rb') as f:
    payload = f.read()
    payload = bytearray(payload)
response = runtime.invoke_endpoint(EndpointName=endpoint_name, 
                                   ContentType='application/x-image', 
                                   Body=payload)
result = response['Body'].read()
# result will be in json format and convert it to ndarray
result = json.loads(result)
# the result will output the probabilities for all classes
# find the class with maximum probability and print the class index
index = np.argmax(result)
object_categories = ['ak47', 'american-flag', 'backpack', 'baseball-bat', 'baseball-glove', 'basketball-hoop', 'bat', 'bathtub', 'bear', 'beer-mug', 'billiards', 'binoculars', 'birdbath', 'blimp', 'bonsai-101', 'boom-box', 'bowling-ball', 'bowling-pin', 'boxing-glove', 'brain-101', 'breadmaker', 'buddha-101', 'bulldozer', 'butterfly', 'cactus', 'cake', 'calculator', 'camel', 'cannon', 'canoe', 'car-tire', 'cartman', 'cd', 'centipede', 'cereal-box', 'chandelier-101', 'chess-board', 'chimp', 'chopsticks', 'cockroach', 'coffee-mug', 'coffin', 'coin', 'comet', 'computer-keyboard', 'computer-monitor', 'computer-mouse', 'conch', 'cormorant', 'covered-wagon', 'cowboy-hat', 'crab-101', 'desk-globe', 'diamond-ring', 'dice', 'dog', 'dolphin-101', 'doorknob', 'drinking-straw', 'duck', 'dumb-bell', 'eiffel-tower', 'electric-guitar-101', 'elephant-101', 'elk', 'ewer-101', 'eyeglasses', 'fern', 'fighter-jet', 'fire-extinguisher', 'fire-hydrant', 'fire-truck', 'fireworks', 'flashlight', 'floppy-disk', 'football-helmet', 'french-horn', 'fried-egg', 'frisbee', 'frog', 'frying-pan', 'galaxy', 'gas-pump', 'giraffe', 'goat', 'golden-gate-bridge', 'goldfish', 'golf-ball', 'goose', 'gorilla', 'grand-piano-101', 'grapes', 'grasshopper', 'guitar-pick', 'hamburger', 'hammock', 'harmonica', 'harp', 'harpsichord', 'hawksbill-101', 'head-phones', 'helicopter-101', 'hibiscus', 'homer-simpson', 'horse', 'horseshoe-crab', 'hot-air-balloon', 'hot-dog', 'hot-tub', 'hourglass', 'house-fly', 'human-skeleton', 'hummingbird', 'ibis-101', 'ice-cream-cone', 'iguana', 'ipod', 'iris', 'jesus-christ', 'joy-stick', 'kangaroo-101', 'kayak', 'ketch-101', 'killer-whale', 'knife', 'ladder', 'laptop-101', 'lathe', 'leopards-101', 'license-plate', 'lightbulb', 'light-house', 'lightning', 'llama-101', 'mailbox', 'mandolin', 'mars', 'mattress', 'megaphone', 'menorah-101', 'microscope', 'microwave', 'minaret', 'minotaur', 'motorbikes-101', 'mountain-bike', 'mushroom', 'mussels', 'necktie', 'octopus', 'ostrich', 'owl', 'palm-pilot', 'palm-tree', 'paperclip', 'paper-shredder', 'pci-card', 'penguin', 'people', 'pez-dispenser', 'photocopier', 'picnic-table', 'playing-card', 'porcupine', 'pram', 'praying-mantis', 'pyramid', 'raccoon', 'radio-telescope', 'rainbow', 'refrigerator', 'revolver-101', 'rifle', 'rotary-phone', 'roulette-wheel', 'saddle', 'saturn', 'school-bus', 'scorpion-101', 'screwdriver', 'segway', 'self-propelled-lawn-mower', 'sextant', 'sheet-music', 'skateboard', 'skunk', 'skyscraper', 'smokestack', 'snail', 'snake', 'sneaker', 'snowmobile', 'soccer-ball', 'socks', 'soda-can', 'spaghetti', 'speed-boat', 'spider', 'spoon', 'stained-glass', 'starfish-101', 'steering-wheel', 'stirrups', 'sunflower-101', 'superman', 'sushi', 'swan', 'swiss-army-knife', 'sword', 'syringe', 'tambourine', 'teapot', 'teddy-bear', 'teepee', 'telephone-box', 'tennis-ball', 'tennis-court', 'tennis-racket', 'theodolite', 'toaster', 'tomato', 'tombstone', 'top-hat', 'touring-bike', 'tower-pisa', 'traffic-light', 'treadmill', 'triceratops', 'tricycle', 'trilobite-101', 'tripod', 't-shirt', 'tuning-fork', 'tweezer', 'umbrella-101', 'unicorn', 'vcr', 'video-projector', 'washing-machine', 'watch-101', 'waterfall', 'watermelon', 'welding-mask', 'wheelbarrow', 'windmill', 'wine-bottle', 'xylophone', 'yarmulke', 'yo-yo', 'zebra', 'airplanes-101', 'car-side-101', 'faces-easy-101', 'greyhound', 'tennis-shoes', 'toad', 'clutter']
print("Result: label - " + object_categories[index] + ", probability - " + str(result[index]))

実行結果

Result: label - bathtub, probability - 0.9933144450187683

サンプルの実行が完了したら エンドポイント設定の削除、エンドポイントの削除、インスタンスの停止 をおこないます

感想

2回もやるとなんとなくわかってきた。 知らない事ばかりで本当に勉強しないと!!と思ってしまう。

次はエンドポイントを利用してWEBアプリのサンプルを作りたい あとはエンドポイントのインスタンスタイプが「ml.m4.xlarge」だったが もっと安いタイプで実行できるのか検証したい