深層学習..と言っても隠れ層は4層くらいの浅いものなのですが、これを利用して予測するAPIを作ってみて感じ事を書き連ねます。
環境
- ローカル(Mac)
- python2.7
- リモート(もちろんLambdaの事)
- Amazon Linux
- python2.7
- (3.x対応はいつ来るのか)
詰まった事
今回、この環境を作る上で頭を抱えた事を大きく分けると以下の2つになります。
- Lambda用に自分のコードを圧縮するには?
- Macで圧縮したzipをそのままあげても、Lambdaで動かなかった。
- 作成したzipのサイズはLambdaの許容量を超えていた。
Lambda用に自分のコードを圧縮するには?の話
簡単なLambdaのコードだったら、ルートディレクトリに
lambda_function.py
なんてファイルを作って置いておけば、すぐLambdaにアップロードして試せると思います。
しかし、自分のディレクトリ構成は以下のような構成でした。
./src
├── data
│ ├── __init__.py
│ └── data.py
├── __init__.py
├── lambda
│ ├── __init__.py
│ └── lambda_function.py
├── ml
│ ├── hoge_dir
│ ├── __init__.py
│ └── fuga_fir
└── utils
├── __init__.py
└── utils.py
LambdaのHandlerの指定も以下のように指定しなければならないほど、実行したいコードが深くにあります。
src/lambda/lambda_function.lambda_handler
Lambdaで動かすにはimportするサードパーティのライブラリをプロジェクトのルートディレクトリに配置しなければいけません。
この配置を手動でやるとかめんどくさすぎるだろ...
が、どうやらクラスメソッドさんの記事を読んでいるとlambda-uploaderとかいう神ツールを使った記事を見つけて自分のコードをLambda用にzip圧縮するということはすんなり解決しました。
クラスメソッドさんの記事は以下
参照:http://dev.classmethod.jp/cloud/deploy-aws-lambda-python-with-lambda-uploader/
Macで圧縮したzipをそのままあげても、Lambdaで動かなかった話
なぜこんな事が起きたかというと、"当初"はpythonのライブラリとして以下を利用してコードを書いていました。
- numpy
- scipy
- scikit-learn
実際に、LambdaにzipをアップロードしテストRunしてみると以下のメッセージが...
/var/task/numpy/core/multiarray.so: invalid ELF header
これはMacとAmazonLinuxという環境の違いがあったため発生した問題です。
この件は公式に書いてある通り、Lambdaと同じ環境でzip化しなければなりません。(少し面倒ですが)
つまり、EC2を立ち上げてそこに同じような環境を作って、先ほどのlambda-uploaderを使うということになります。
参照:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html
作成したzipのサイズはLambdaの許容量を超えていた話
当初は以下のライブラリをつかっていました。
- numpy
- numpyに関しては行列演算のため
- scipy
- scikit-learnのため(うろ覚え)
- scikit-learn
- データの標準化を行いたかったため
- pandas
- csvデータの扱い
つまりpython上では以下の処理をさせていました。
- Lambdaに入力されたデータを
scikit-learn
で標準化 - S3に置いてある重み、バイアスのcsvデータを
boto3
とpandas
を使って行列に変換 - 手順1, 2のデータを使って予測
これをいざ、Lambdaでrunさせてみると以下の警告が...
Unzipped size must be smaller than 262144000 bytes
AWS Lambdaのデプロイメントの制限に引っかかっていたわけですね。
参照:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html
これは非常に厄介
結論からどういう対応を行ったかというと、
- lambda-uploaderで圧縮される対象を絞った。(ignore設定を行った)
-
scipy
,scikit-learn
を使わない実装にした。- ここを利用しているのはデータの標準化のみです。つまり、
numpy
だけでも同じ処理を実装することができます。
- ここを利用しているのはデータの標準化のみです。つまり、
ただ、これはどの案件にも言える話ではないので、たまたま運が良かっただけですね...
感想
デプロイメントの制限は緩和して欲しいですね。(こういうケースはECSを使って欲しいのかもしれませんが...)