AWS GreengrassにKerasのモデルをデプロイしてみた

AWS GreengrassにKerasのモデルをデプロイしてみました。

# きっかけ

Re:Invent 2017で発表された新サービス「[AWS Greengrass ML Inference](https://aws.amazon.com/jp/greengrass/ml/)」にプレビュー申請したところ、残念ながら結果は<font color="Red">Not Approved</font>。

GAまで待つのもちょっと悔しいので、普通のGreengrassにkerasのモデルをデプロイしてみることにしました。
# 必要なもの
* AWSアカウント
* Raspberry Pi

# 作業概要
1. Kerasの環境準備(Mac)
2. greengrassチュートリアル実施
3. Raspberry PiにKeras等をインストール
4. Kerasのモデル作成
5. デプロイ用のLambda作成
6. Greengrassへデプロイ
7. 動作テスト

# 1. Kerasの環境準備(Mac)

MacにKerasの環境を準備します。

```bash
$ brew upgrade pyenv
$ pyenv install 2.7.14
$ pyenv virtualenv 2.7.14 keras
$ cd hoge/huga
$ pyenv local keras
$ pip install tensorflow jupyter keras h5py
```

# 2. Greengrassチュートリアル実施

Raspberry Piの環境構築を兼ねて、[AWSドキュメントにあるGreengrassのチュートリアル](https://docs.aws.amazon.com/ja_jp/greengrass/latest/developerguide/gg-gs.html)を実施します。

「モジュール 3-I: AWS Greengrass での AWS Lambda」までの実施でOKです。

# 3. Raspberry PiにKeras等をインストール

[こちらの記事](https://qiita.com/kazunori279/items/1e23679c534a49c0e837)を参考にさせて頂きました。
Raspberry Piにsshでログインしてインストールします。
熱暴走するかもとの事だったので、自分はUSB扇風機で風を当てながら一晩熟成させました。

```bash
$ sudo pip install http://ci.tensorflow.org/view/Nightly/job/nightly-pi/lastStableBuild/artifact/output-artifacts/tensorflow-1.5.0rc1-cp27-none-any.whl
$ sudo pip install keras
$ sudo apt-get install python-h5py
```

# 4. Kerasのモデル作成
今回はkerasのexampleから[MNISTの文字分類のソースコード](https://github.com/keras-team/keras/blob/master/examples/mnist_mlp.py)を拝借して、Kerasのモデルを作成します。

**1. 上記ソースコードをダウンロードする**
**2. 下記3行を追記して用意した環境で実行する**

```python
model.save('mnist_mlp.h5')
np.save('x_test.npy', x_test)
np.save('y_test.npy', y_test)
```
**3. 実行後、下記3ファイルが生成される**

- mnist_mlp.h5 (Kerasのモデル)
- x_test.npy (画像データ)
- y_test.npy (画像データに対応する正解ラベル)

# 5. デプロイ用のLambda作成

GreengrassへデプロイするLambdaを作成します。

**1. BlueprintsからLambdaを作成する**
AWSマネジメントコンソールでLambdaを選択後、blueprintsから「greengrass-hello-world」を選択して、Lambdaを作成します。
ロールはチュートリアルで作成したものを指定してください。
**2. ソースコードを置き換える**
AWSマネジメントコンソール上で、Lambdaのコードを下記へ置き換えます。

```python
from __future__ import print_function


import greengrasssdk
from threading import Timer
import time
import keras
from keras.models import load_model
import numpy as np
import random

client = greengrasssdk.client('iot-data')
x_test = np.load('x_test.npy')
y_test = np.load('y_test.npy')
x_test = x_test.reshape(10000, 784).astype('float32') / 255
model = load_model('mnist_mlp.h5')


def greengrass_keras_prediction_run():
    r = random.randrange(10000)
    prediction = model.predict(x_test[r].reshape(1, 784))
    predicted_value = np.argmax(prediction[0])
    answer = y_test[r]

    message = 'predicted value: {0}, answer:{1}'.format(predicted_value, answer)
    client.publish(topic='keras/prediction', payload=message)

    Timer(5, greengrass_keras_prediction_run).start()


greengrass_keras_prediction_run()


def function_handler(event, context):
    return
```
**3. デプロイメントパッケージをダウンロードする**
AWSマネジメントコンソールから、Lamdbaのデプロイメントパッケージをダウンロードします。
**4. mnist_mlp.h5 / x_test.npy / y_test.npyの3ファイルをデプロイメントパッケージに含める**
ダウンロードしたデプロイメントパッケージを展開後、3ファイルを含めて再度zip圧縮します。
zipファイルにはフォルダを含めないように注意してください。

```bash
$ zip -r ../keras_prediction.zip *
```
**5. デプロイメントパッケージをアップロードして、Lambdaを更新する**
**6. 新しいバージョンを発行して、発行したバージョンに対しエイリアスを作成する**
手順はGreengrassのチュートリアルと同じです。

# 6. Greengrassへデプロイ
手順はGreengrassのチュートリアルと同じです。Greengrassのコンソール画面から操作します。
**1. Lamdbaを登録する**
一覧から作成したLambdaを選択後、Lambdaのエイリアスを指定して登録します。
**2. Lamdbaの設定を変更する**

- タイムアウト：25秒
- ライフサイクル：Make this function long-lived and keep it running indefinitely

**3. subscriptionを追加する**

- ソース：Lambda
- ターゲット：IoT Cloud
- トピック：keras/prediction

<img width="980" alt="subscription.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/57396f88-198a-3fc2-4f3e-60f7d0f7760c.png">

# 7. 動作テスト
**1. Greengrassのコンソール画面の左側のTestをクリック**
**2. Subscription Topicにkeras/predictionを指定**
**3. Subscribe to topicをクリック**
下記が表示されれば成功です。
<img width="1103" alt="test2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/ce60bfe0-5cb8-c17b-8296-aa7cb6f09867.png">

# 雑感
AWS Greengrass ML Inferenceでは、上記のように煩雑でなく簡単に学習モデルがデプロイできるようになるでしょうか。
似たようなサービスに[Azure IoT Edge](https://docs.microsoft.com/ja-jp/azure/iot-edge/)(こちらも未だプレビュー)がありますが、今度はこっちをさわってみたいと思います。