概要
前編で作ったアプリケーションをGCP上で動かします。Flaskを使って実装しており、アーキテクチャと処理は以下の図のようにしています。App EngineとCloud Storageを用いています。GCP上でモデルの学習させたいとか、モデルの呼び出しをAPIとして切り離したい場合は、Cloud ML Engineを使う方がいいと思います。
(1) 画像をアップロード
(2) 画像をCloud Storageバケットに保存
(3) アッップロードされた画像と予め保存しておいた機械学習モデルを読み込み
(4) 判定し、結果を返す
GCPについては、過去にもいくつか記事を書いていますので、よければご覧ください。
動作環境
App Engineは、スタンダード環境(Python 3.7)を使います。
Cloud Storageについては、簡単のために公開バケットを使います。サービスアカウントとこ、IAMは今回は考えません。また、予め学習させたCNNのモデル(.h5)を、このバケットにアップロードしておきます。
実装内容
App Engineにデプロイするコードは、以下のような構成です。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ tree . . ├── app.yaml ├── main.py ├── requirements.txt ├── static │ └── style.css └── templates ├── base.html ├── predict.html └── result.html |
これらを、gcloud app deploy app.yaml --project [project-id]
でデプロイできます。HTML
やCSS
ファイルは前編から変わっていません。その他、追加変更したところを見ていきます。
requirements.txt
アプリケーションをビルドするのに必要なパッケージは以下の通りです。一応新しい仮想環境で開発しましたが、精査していないので無駄なものも入れてしまっていたらごめんなさい。
app.yaml
APP Engineを利用するための設定ファイルです。ランタイムや、利用するインスタンスクラス、インスタンスのスケーリングなどを設定しています。App Enginet特有のものは、実質これだけです。
main.py
前編ではpredict.py
としていたファイルです。相変わらず、メインとなる処理を書いています。
ここでは、main.py
で主に変更した点について書いていきます。
まず、アップロードされた画像やCNNのモデルを保存するためにストレージが必要です。前編ではローカルPC上での動作だったので、ローカルストレージに保存できていました。一方、App EngineはPaaSですから、データを保存したいときは基本的に以下のようなGCPのストレージサービスを使います。今回はもっとも扱いやすそうなGoogle Cloud Storage(オブジェクトストレージサービス、AWSのS3)を用いました。
Cloud Storageの操作は、google-cloud-storage
というライブラリが用意されています。
1 2 |
from google.cloud import storage |
Cloud Storageバケットと、予め保存しておくCNNのモデル名を以下の変数に設定します。アップロードされてきた画像も、このバケットに保存します。
1 2 3 4 5 6 7 |
################################# # TODO: # # Set GCS_BUCKET and MODEL_NAME # ################################# GCS_BUCKET = '' MODEL_NAME = '' |
そして、pedict()
の真ん中あたりで、以下の処理をしています。
- 画像をCloud Storageへアップロード
- アップロードした画像の公開URLを取得
- 公開URLから画像を読み込み、予測結果を返す
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
def predict(): if request.method == 'POST': if 'file' not in request.files: flash('No file.') return redirect(url_for('predict')) file = request.files.get('file') if file.filename == '': flash('No file.') return redirect(url_for('predict')) if file and is_allowed_file(file.filename): gcs = storage.Client() bucket = gcs.get_bucket(GCS_BUCKET) blob = bucket.blob(file.filename) blob.upload_from_string( file.read(), content_type=file.content_type ) file_url = blob.public_url img = Image.open(io.BytesIO(requests.get(file_url).content)).convert('RGB') img = img.resize((150, 150)) x = np.array(img, dtype=np.float32) x = x / 255. x = x.reshape((1,) + x.shape) global graph with graph.as_default(): pred = model.predict(x, batch_size=1, verbose=0) score = pred[0][0] if(score >= 0.5): person = 'Smalling' else: person = 'Obama' score = 1 - score resultmsg = '[{}] {:.4%} Sure.'.format(person, score) return render_template('result.html', resultmsg=resultmsg, filepath=file_url) return render_template('predict.html') |
画像アップロードと予測の関数を分けた方がいいと思いますが、今回はやっていません。また公開URLも、DBで管理するなどすれば、使い道が広がりそうです。
動作例
App Engineにデプロイ後は、GCPのプロジェクトIDに応じてエンドポイントが割り当てられます。そこにアクセスすれば、以下と同様に動作します。
お盆休みなのでflaskで遊んでる pic.twitter.com/eVHuBMx8ZZ
— nishipy (@iamnishipy) August 14, 2019
参考にしたサイト
有益な情報ありがとうございます。というか、ほとんど内容かぶっててごめんなさい🙇
- GoogleAppEngine(GAE)フレキシブル環境でディープラーニングの予測タスクを動かしてみた(CNN,画像分類,keras/TensorFlow)
- flaskでGAEからGSCにファイルをアップロードするまで
さいごに
App Engine久々に使ったけど、やっぱり便利でした。今回のコードも、GitHubにあげました。
以上.
コメント