GAE スタンダード環境で scikit-learn を使う

Hayato Yoshikawa
google-cloud-jp
Published in
6 min readOct 8, 2018

Google Cloud Next ’18 in San Francisco にて、Google App Engine スタンダード環境の Python 3.7 対応がアナウンスされました。Pythonista の方々には朗報ですが、実はそれ以外にも大きな変更がありました。

C で書かれたライブラリの使用が可能に

今までの GAE スタンダード環境 Python ランタイムでは、ライブラリはホワイトリスト化された特定のビルトインのものか、Pure Python のものという制限がありました。これは従来のランタイムで使用されていたアイソレーション環境では、システムの安全性を保証できなかったからです。一方、今回Python 3.7 が動作する第2世代ランタイムでは、gVisor をベースとしたアイソレーション環境により安全性が担保できるため、内部的にCで書かれた Pythonライブラリもロードして使用することができます。これは長年のGAEファンには待望の機能拡張ではないでしょうか?
このおかげで、従来は使えなかった scikit-learn¹ なども使うことができます。

gVisor は様々な GCP プロダクトですでに使われている

scikit-learn を GAE スタンダード環境で使う準備

GAE スタンダード環境でこれらCで書かれたライブラリをロードするには、まずはapp.yaml でPython 3.7 を使う事を定義します。

runtime: python37

その後requirements.txt にライブラリ名を記載をするだけです。

scikit-learn==0.20.0

これだけです!簡単ですね。 pip install -t lib -r requirements.txt なども実行する必要はありません(ローカル環境でテストしたい場合を除く)。

scikit-learn のモデルを Serving する

scikit-learn で学習したモデルは、 joblib を使ってファイルにしておくことができます。ここでは簡単に、あらかじめローカル環境にて Iris のデータを SVM で学習しておいたモデルを、GAE 環境で Serving してみましょう。
ローカルで学習するには、次のコードを実行します。

from sklearn import svm
from sklearn import datasets
clf = svm.SVC(gamma='scale')
iris = datasets.load_iris()
X, y = iris.data, iris.target
# 学習
clf.fit(X, y)
# ファイルにする
from sklearn.externals import joblib
joblib.dump(clf, 'iris.joblib')

実行すると、 iris.joblib というファイルが生成されます。このファイルをデプロイするファイルに含めれば、GAE環境でも学習済みモデルをロードすることができます。

GAE にデプロイするファイルを準備

GAE スタンダード環境で必要なファイルはごく少数です。ここでは次のようなファイル構成を用意します。

gae-sklearn
|-- app.yaml
|-- requirements.txt
|-- main.py
|-- iris.joblib

これだけです。 app.yamliris.joblib は先に記載した通りですが、 requirements.txt は Webフロントエンドフレームワークとして Flask を使いたいので、次のように書きます²。

Flask==1.0.2
scikit-learn==0.20.0

次は推論のデータリクエストに対し、学習済みモデルで推論した結果を返すハンドラを main.py に記載します。推論したい特徴ベクトルを JSON で受け取り、scikit-learn の学習済みモデルで推論し、その結果を JSON で返す簡単なコードです。

from flask import Flask, request, jsonify
from sklearn.externals import joblib
clf = joblib.load('iris.joblib')
app = Flask(__name__)
@app.route('/predict', methods=['GET', 'POST'])
def predict():
dat = request.json
pred = clf.predict(dat['data'])
return jsonify({"predicted_class": pred.tolist()})
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)

これでコーディングは完了です。GAE 環境にデプロイしましょう。デプロイは今まで通り、 gcloud app deploy で行えます。

$ cd gae-sklearn
$ gcloud app deploy .

デプロイが完了したら、リクエストを投げてみましょう。 今回は JSON でデータを受け付ける構成にしたので、次のように application/json ヘッダをつけてリクエストします。[project_id] の部分は自分のプロジェクトIDに書き換えてください。

$ curl -H "Content-Type: application/json" \
--data '{"data":[[0,0,0,0]]}' \
https://[project_id].appspot.com/predict

リクエストに成功すると、次のように推論結果が返ってきます。 2 のラベルのようですね。

{"predicted_class":[2]}

このように、 Cで書かれたライブラリを簡単に使う事ができるようになりました。今まで GAE スタンダード環境に魅力を感じたものの、使いたいライブラリが実行できないため泣く泣く別の環境を選択した方も、もう一度GAE を検討してみてはいかがでしょうか?

[1] ライブラリが Python 3.7 に対応している必要があります。TensorFlowは本記事執筆時点では Python 3.7 に未対応であるため、requrements.txt に記載してもインストールできません。

[2] 今回の構成だと、デフォルトのインスタンスタイプではメモリ不足になる場合があります。その際は app.yamlinstance_class: F2 などを追記し、よりメモリの多いタイプを使うと解決します。

--

--

Hayato Yoshikawa
google-cloud-jp

Customer Engineer, Google Cloud @Google. Views are my own.