AWS Lambda環境でTensorFlowを動かしてみた:準備編


## この記事を3行で

* AWS Lambda環境においてTensorFlowを使った小さなコードが動作しました。
* 環境一式を含んだZIPファイルは[gist:9b11f081186b98fe130e](https://gist.github.com/nayutaya/9b11f081186b98fe130e)に置いています。
* 本格的な検証はまだこれから。

## 1. 動機

勉強会で『[TensorFlowを使ってテキストをクラス分類してみた](http://qiita.com/yuyakato/items/762d4fcb925de5d46fb7)』と題して発表しました。
それなりの結果を得ることができたので、それならば本格的に使ってみようと考え、大好きな[AWS Lambda](https://aws.amazon.com/jp/lambda/)と[Amazon API Gateway](https://aws.amazon.com/jp/api-gateway/)を使ってAPIを構築してみることにしました。

## 2. 結果

TensorFlowを使って「1 + 2」を計算し、正しく「3」という結果を得ることができました。
少なくとも、AWS Lambda環境においてTensorFlowが`import`できることを確認できました。

## 3. 実験方法

### 3.1. Amazon EC2環境でネイティブモジュールの準備

AWS LambdaはAmazon Linux上で動作しています。
具体的な環境については公式ページの『[Lambda 実行環境と利用できるライブラリ - AWS Lambda](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html)』にて確認できます。

今回は東京リージョンで動作させたいので、前述のページから`ami-383c1956`を使えば良いことが分かります。AMIはリージョン毎に異なることにご注意ください。
Amazon EC2上に`ami-383c1956`の`t2.micro`インスタンスを作成し、ネイティブモジュールを準備しました。

完成したZIPファイルは`ami-383c1956-python2.7-tensorflow0.7.1-20160320.zip`として[gist:9b11f081186b98fe130e](https://gist.github.com/nayutaya/9b11f081186b98fe130e)に置いています。
ファイルサイズは約23MiB、SHA-1ハッシュ値は`3157f010853fee1769a1149afbed15383bf2be96`です。

構築の手順は以下の通りです。

```plain
# 環境を確認
$ uname -a
Linux ip-xxx-xxx-xxx-xxx 4.1.10-17.31.amzn1.x86_64 #1 SMP Sat Oct 24 01:31:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/system-release
Amazon Linux AMI release 2015.09

# パッケージをアップデート、インストール
$ sudo yum -y update
$ sudo yum -y upgrade
$ sudo yum -y groupinstall "Development Tools"
$ sudo yum -y install python27-devel python27-pip gcc

# virtualenvを準備
$ export ENV_ROOT=~/env
$ virtualenv ${ENV_ROOT}
$ source ${ENV_ROOT}/bin/activate

# Pythonのバージョン、パスを確認
(env)$ python2.7 --version
Python 2.7.10
(env)$ which python2.7
~/env/bin/python2.7
(env)$ which pip2.7
~/env/bin/pip2.7

# TensorFlowと依存ライブラリをインストール
(env)$ pip2.7 install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl
Successfully installed numpy-1.10.4 protobuf-3.0.0b2 setuptools-20.3.1 six-1.10.0 tensorflow-0.7.1 wheel-0.29.0

(env)$ deactivate

# ZIPファイルを作成する
$ export OUT_FILE=~/ami-383c1956-python2.7-tensorflow0.7.1-20160320.zip
$ cd ${ENV_ROOT}/lib/python2.7/site-packages
$ touch google/__init__.py
$ zip -r9v ${OUT_FILE} . --exclude \*.pyc
$ cd ${ENV_ROOT}/lib64/python2.7/site-packages
$ zip -r9v ${OUT_FILE} . --exclude \*.pyc
$ sha1sum ${OUT_FILE}
3157f010853fee1769a1149afbed15383bf2be96  /home/ec2-user/ami-383c1956-python2.7-tensorflow0.7.1-20160320.zip
```

### 3.2. AWS Lambdaのデプロイパッケージを準備

今回は以下のコードを用いました。「1 + 2」を計算するだけのとてもシンプルなコードです。

```main.py
import tensorflow as tf

def lambda_handler(event, context):
    a = tf.constant(1)
    b = tf.constant(2)
    with tf.Session() as sess:
        return str(sess.run(a + b))
```

`ami-383c1956-python2.7-tensorflow0.7.1-20160320.zip`をコピーし、`main.py`を追加することで、デプロイパッケージを作成しました。

```plain
$ cd /project/path/tensorflow
$ cp ami-383c1956-python2.7-tensorflow0.7.1-20160320.zip test.zip

$ cd /project/path/tensorflow/lambda
$ vi main.py
$ zip -r9v ../test.zip . --exclude \*.pyc
```

### 3.3. AWS Lambdaのデプロイパッケージをアップロード

今回はWebコンソールからLambda関数を作成し、`test.zip`をアップロードしました。
メモリサイズはデフォルトの128MBのまま。タイムアウト値は10秒に延長しました。

### 3.4. AWS Lambdaの実行

Webコンソールから「Test」ボタンを押下し、Lambda関数を実行すると、正しく「3」という結果を得ることができました。
少なくとも2回目以降は100ms以下の実行時間、最大メモリ使用量は33MBでした。

## 4. 参考文献

以下、参考にしたページです。

- [python - Using moviepy, scipy and numpy in amazon lambda - Stack Overflow](http://stackoverflow.com/questions/34749806/using-moviepy-scipy-and-numpy-in-amazon-lambda)
- [AWS Lambda Python版でgcloudパッケージを利用しようとするとImportError - Qiita](http://qiita.com/runtakun/items/06b41dbff1cc683e48d8)