この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
おはようございます、もきゅりんです。
最近は個人的な取り組みの一環として、機械学習の学習に取り組み始めました。
さて、AWSで機械学習に取りかかるならば、Amazon SageMaker。
まずは、組み込みアルゴリズムのLinearLearner。
そんなオレは、ML beginner。
(LinearLearnerが何だ?という話は、ドキュメントを確認して欲しいのですが、ターゲットの分類や予測したい数値を推定するために使用される、教師あり学習アルゴリズムです。)
初めてのデータセットは、みんな大好きな Iris でやってみます。
作業の流れは、完全に下記の通りで進めます。
なお、自分は専門的なデータサイエンティストでも何でもないので、無駄、非効率な作業を行っているかもしれない点、ご了承下さい。
前提
- IAM権限を設定・更新できること
やること
3つの品種のIris(お花です)を、個体が持つ特徴(花びらの長さとか幅とか)だけで分類しようぜ!
が趣旨です。
- S3バケットの作成
- SageMakerノートブックインスタンスの作成
- Jupyterノートブックの作成
- データのロード、データを探索、処理、S3アップロード
- モデルでの学習
- モデルのデプロイ
- モデルの検証
- 後片付け
1. S3バケットの作成
S3バケットはコンソールでも何でもデフォルト設定で作成すれば問題ないです。
このバケットは、元のデータや加工したデータを格納します。
aws s3 mb s3://YOUR_BUCKT_NAME
2. SageMakerノートブックインスタンスの作成
さて、ここからドキドキの初めての体験です。
コンソールからSageMakerにいきます。
先ほど作成したS3バケットへのIAMロールを作成します。
そしたら作成します。
3. Jupyterノートブックの作成
ステータスが Inservice
になったことを確認したら、ノートブックを開きます。
4. データのロード、データを探索、処理、S3アップロード
データのロード
Iris
なのでsklearnのデータセットからロードしちゃいます。
import numpy as np
import os
from sklearn import datasets
iris = datasets.load_iris()
とくに今回はデータ探索を行うことはありません。
データはサンプルサイズは150,特徴量が4つです。
iris['data'].shape
データの分割
訓練データ、検証データ、テストデータに分割していきます。
地道にデータを分けていきます。
まずはテストデータとして20%を取り分けます。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(iris['data'],iris['target'],test_size=0.2, random_state=42)
AWSでは、第1列目に教師データ(今回はラベル)がある必要があるようなので、データを加工します。
test_set = np.insert(X_test, 0, y_test, axis=1)
今度は検証データを分割します。
from sklearn.model_selection import train_test_split
X_train, X_validation, y_train, y_validation = train_test_split(X_train,y_train,random_state=42)
テストデータ同様、教師データを最初の列に挿入します。
train_set = np.insert(X_train, 0, y_train, axis=1)
valid_set = np.insert(X_validation, 0, y_validation, axis=1)
それぞれのデータのサイズを確認します。
test_set.shape
valid_set.shape
train_set.shape
教師データが挿入されたので、 column
は5つになっています。
データのアップロード
それぞれのデータをS3バケットにアップロードします。
%%time
import os
import boto3
import re
import copy
import time
import io
import struct
from time import gmtime, strftime
from sagemaker import get_execution_role
role = get_execution_role()
region = boto3.Session().region_name
bucket='YOUR_BUCKET_NAME' # Replace with your s3 bucket name
prefix = 'sagemaker/test' # Used as part of the path in the bucket where you store data
bucket_path = 'https://s3-{}.amazonaws.com/{}'.format(region,bucket) # The URL to access the bucket
def convert_data():
data_partitions = [('train', train_set), ('validation', valid_set), ('test', test_set)]
for data_partition_name, data_partition in data_partitions:
print('{}: {} {}'.format(data_partition_name, data_partition[0].shape, data_partition[1].shape))
labels = [t.tolist() for t in data_partition[:,0]]
features = [t.tolist() for t in data_partition[:,1:5]]
if data_partition_name != 'test':
examples = np.insert(features, 0, labels, axis=1)
else:
examples = features
np.savetxt('data.csv', examples, delimiter=',')
key = "{}/{}/examples".format(prefix,data_partition_name)
url = 's3://{}/{}'.format(bucket, key)
boto3.Session().resource('s3').Bucket(bucket).Object(key).upload_file('data.csv')
print('Done writing to {}'.format(url))
convert_data()
S3バケットを見に行くとちゃんとありました。
5. モデルでの学習
例では XGB
ですが、Linear-Learner
に変更します。
import sagemaker
from sagemaker.amazon.amazon_estimator import get_image_uri
container = get_image_uri(boto3.Session().region_name, 'linear-learner')
前ステップ4でアップロードしたS3から訓練データと検証データをダウンロードし、トレーニングの出力を保存する場所を設定します。
train_data = 's3://{}/{}/{}'.format(bucket, prefix, 'train')
validation_data = 's3://{}/{}/{}'.format(bucket, prefix, 'validation')
s3_output_location = 's3://{}/{}/{}'.format(bucket, prefix, 'linear-learner_model_sdk')
print(train_data)
モデルのハイパーパラメータを設定します。
特徴量は4、分類する種類は3なので、それぞれ設定します。
linear_model = sagemaker.estimator.Estimator(container,
role,
train_instance_count=1,
train_instance_type='ml.c4.xlarge',
output_path=s3_output_location,
sagemaker_session=sagemaker.Session())
linear_model.set_hyperparameters(feature_dim=4,num_classes=3,
mini_batch_size=32,
predictor_type='multiclass_classifier')
訓練(検証)を行うためのチャネルという概念があり、ここでは train
と validation
の両方のチャネルを作ります。
train
とか片方だけのチャネルでも可能のようです。
train_channel = sagemaker.session.s3_input(train_data, content_type='text/csv')
valid_channel = sagemaker.session.s3_input(validation_data, content_type='text/csv')
data_channels = {'train': train_channel, 'validation': valid_channel}
訓練データと検証データを使って訓練を開始します。
linear_model.fit(inputs = data_channels, logs=True)
完了すると下記のようなメッセージが表示されます。
2020-XX-XX XX:XX:XX Uploading - Uploading generated training model
2020-XX-XX XX:XX:XX Completed - Training job completed
Training seconds: 38
Billable seconds: 38
トレーニングのログ(CloudWatchLogs)をダッシュボードから移動します。
とりあえず accuracy
とかパッと分かりやすそうな値が良さそうなのが分かりますね。
6. モデルのデプロイ
訓練されたモデルをエンドポイントにデプロイすることもできますが、特にエンドポイントは必要ないのでバッチ変換します。
ステップ4で、S3バケットにアップロードしているコードを確認頂ければお分かりだと思いますが、テストデータは特徴量のみのデータとなっています。
ここでは、特徴量のみを与えられているテストデータを元に、分類してみるぞ!という作業です。
ちなみに、機械学習で「バッチ」とは大雑把に言うと、全部一度にってことです。
# The location of the test dataset
batch_input = 's3://{}/{}/test/examples'.format(bucket, prefix)
# The location to store the results of the batch transform job
batch_output = 's3://{}/{}/batch-inference'.format(bucket, prefix)
transformer = linear_model.transformer(instance_count=1, instance_type='ml.c4.xlarge', output_path=batch_output)
transformer.transform(data=batch_input, data_type='S3Prefix', content_type='text/csv', split_type='Line')
transformer.wait()
7. モデルの検証
モデルから予測された予測を答え合わせします。
テストデータから予測したファイルをダウンロードします。
s3.Bucket(bucket).download_file(prefix + '/batch-inference/examples.out', 'batch_results')
ちょっとファイルを整形します。
(何かうまいやり方がありそうだけど...)
with open('batch_results', "r") as f:
s = f.read()
s = s.replace("{\"predicted_label\":", "")
with open('batch_results_fixed', "w") as f:
f.write(s)
arr = []
f=open('batch_results_fixed','r')
for line in f:
l = line.split(',')[0]
arr.append(float(l))
f.close
結果です。
results = np.array(arr)
compare = results == test_set[:,0]
print(np.count_nonzero(compare == True))
あれ、、、全部正解しちゃいましたよ。
前に自分のローカルで試したときは、何個か不正解が出た気がします。
LinearLearner、優秀ですね。
8. 後片付け
不用ならインスタンスは削除しましょう。
S3バケットも忘れずサヨナラしましょう。
aws s3 rm s3://YOUR_BUCKT_NAME
以上です。
SageMakerのお作法にちょっと面食らったりしましたが、慣れてくれば色々とスムーズ進められそうです。
とりあえず距離は縮まりました。
どなたかのお役に立てば幸いです。