Amazon SageMaker とりあえず触ってみた

リージョンはバージニア北部で作成していきます。

とりあえず触ってみた。


----------

###1.S3バケットの作成###

以下の2種類のデータを作成します。
・モデルのトレーニングデータ
・モデルのトレーニング中に生成するモデルアーティファクト

これらのデータを保存するAmazon S3(以下S3)バケットを作成します。

バケット名には、”sagemaker”という文字列を含めて作成してください。

手順は省きます。


###2.SageMaker ノートブックインスタンスの作成###

*SageMakerノートブックインスタンスとは？*
Jupyter Notebookがインストールされたフルマネージドな機械学習EC2コンピューティングインスタンスのことです。

[ノートブックインスタンス]は適当に入力、後はデフォルト値のままにします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/e0d769b0-a306-dda6-e11a-e625bd07a8c0.png)

IAMロールは「なし」で設定します。
【1.S3バケットの作成】で「sagemaker」が含まれる任意の S3 バケットを作成したのはこのためです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/2f79f236-6e38-5757-e6c9-d0ad87a7542b.png)


###3.組み込みのアルゴリズムでモデルをトレーニングし、デプロイする###

MNISTという１桁の手書き数字の画像のデータセットを、
K-MeansというSageMakerの組み込みアルゴリズムで分類してみます。

**1.Jupyterノートブックの作成**

Jupyterノートブックを開き、「conda_python3」にします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/51a82630-5214-91bc-ba31-c0839c008acd.png)

「Untitled」をクリックし、適当な名前を入力し、リネームします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/7660db73-2e1b-2a19-fb04-d9a4f5850555.png)

以下のPythonコードを編集、コピペし「Run」。

```python:
from sagemaker import get_execution_role
 
role = get_execution_role()
bucket='sagemaker-leonmaron'
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/45b03a05-c795-9c2d-5d1f-d95469a2c43e.png)

 
**2.トレーニングデータのダウンロード、調査**

MNISTデータセットのダウンロード

```python:
%%time
import pickle, gzip, numpy, urllib.request, json
 
# Load the dataset
urllib.request.urlretrieve("http://deeplearning.net/data/mnist/mnist.pkl.gz", "mnist.pkl.gz")
with gzip.open('mnist.pkl.gz', 'rb') as f:
    train_set, valid_set, test_set = pickle.load(f, encoding='latin1')
```

トレーニングデータセットの調査

```python:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (2,10)
 
 
def show_digit(img, caption='', subplot=None):
    if subplot==None:
        _,(subplot)=plt.subplots(1,1)
    imgr=img.reshape((28,28))
    subplot.axis('off')
    subplot.imshow(imgr, cmap='gray')
    plt.title(caption)
 
show_digit(train_set[0][30], 'This is a {}'.format(train_set[1][30]))
```

MNISTデータセットの３１枚目の画像データがラベルの内容（３）と共に表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/288543af-e801-c271-86ae-db1a798c0af9.png)


**3.モデルのトレーニング**

トレーニングアルゴリズムの選定
機械学習では、通常モデルに適したアルゴリズムをみつけるための評価プロセスが必要になりますが、
今回は SageMaker の組み込みアルゴリズムの1つである k-means を使うことが決まっているため評価プロセスはスキップ。

トレーニングジョブの作成

```python:
from sagemaker import KMeans
 
data_location = 's3://{}/kmeans_highlevel_example/data'.format(bucket)
output_location = 's3://{}/kmeans_example/output'.format(bucket)
 
print('training data will be uploaded to: {}'.format(data_location))
print('training artifacts will be uploaded to: {}'.format(output_location))
 
kmeans = KMeans(role=role,
                train_instance_count=2,
                train_instance_type='ml.c4.8xlarge',
                output_path=output_location,
                k=10,
                data_location=data_location)
```

トレーニングの実行

```python:
%%time
 
kmeans.fit(kmeans.record_set(train_set[0]))
```

トレーニング実行後に事前に準備したS3バケットを確認すると、トレーニング中に生成されるモデルアーティファクトが格納されています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/aeb26e43-9b18-b8df-baa4-48038601b06c.png)

SageMaker ホスティングサービスにモデルをデプロイする

```python:
%%time
 
kmeans_predictor = kmeans.deploy(initial_instance_count=1,
                                 instance_type='ml.m4.xlarge')
```

モデルの検証

```python:
result = kmeans_predictor.predict(valid_set[0][30:31])
print(result)
```

30番目の画像に対する推論結果が得られました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/1417e85a-4d46-ed89-23ce-7080c34d0436.png)

100個分の推論結果を取得してみます。

```python:
%%time 
 
result = kmeans_predictor.predict(valid_set[0][0:100])
clusters = [r.label['closest_cluster'].float32_tensor.values[0] for r in result]
```

```python:
for cluster in range(10):
    print('\n\n\nCluster {}:'.format(int(cluster)))
    digits = [ img for l, img in zip(clusters, valid_set[0]) if int(l) == cluster ]
    height = ((len(digits)-1)//5) + 1
    width = 5
    plt.rcParams["figure.figsize"] = (width,height)
    _, subplots = plt.subplots(height, width)
    subplots = numpy.ndarray.flatten(subplots)
    for subplot, image in zip(subplots, digits):
        show_digit(image, subplot=subplot)
    for subplot in subplots[len(digits):]:
        subplot.axis('off')
 
    plt.show()
```

30番目の画像に所属していた0はこんな感じ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/1bfc335e-f85c-8c1e-8771-f2a638a60f57.png)