LoginSignup
14
12

More than 5 years have passed since last update.

GoogleAppEngine(GAE)スタンダード環境でscikit-learnを動かしてみた(機械学習、予測)

Last updated at Posted at 2018-10-20

はじめに

以下の記事で、GoogleAppEngineスタンダード環境で、scikit-learnを利用することができるようになったとのことで、動作させてみました。
学習したモデルはGCSへ保存したり、モデルを読み込んで予測タスクも実行しています。

Python 3.7 が動作する第2世代ランタイムでは、gVisor をベースとしたアイソレーション環境により安全性が担保できるため、内部的にCで書かれた Pythonライブラリもロードして使用することができます。

とのこと。

環境

  • GoogleAppEngine StandardEnvironment (Python3.7(ベータ版))
  • GoogleCloudStorage
  • scikit-learn 0.20.0
  • Pickle

簡易構成図と流れは、以下です。

  1. 事前準備(学習データ読み込みと、モデル保存用に、GCSバケット準備)
  2. GAEがGCSから学習データを取得
  3. 機械学習実行
  4. 学習モデルはGCSへ保存
  5. 学習モデルを読み込み、予測

構成図

説明

1. 事前準備(GAE設定、学習データ読み込みと、モデル保存用に、GCSバケット準備)

GCS上に学習データを配置しておきます。GAEはそれを読み込んで学習することとします。

そして、GAE実行に、必要なライブラリを読み込んだり、環境準備をしておきます。

requirements.txt
Flask==1.0.2
google-cloud-storage== 1.7.0
gunicorn==19.8.1
WTForms-Appengine==0.1
pandas==0.23.4
scikit-learn==0.20.0
numpy==1.15.2

runtimeでpython37を指定します。また、学習タスクで負荷が高く、デフォルトのF1だとServerError504が発生したので、F2を指定しました。

app.yaml
runtime: python37
instance_class: F2

2. GAEがGCSから学習データを取得

GAEがGCSから学習データを取得します。取得したデータはsource_dataに格納します。
(今回、source_filenameはPOST request内のFORMデータに格納するようにしています。)

main.py(抜粋)
def download_blob(source_blob_name):
    """Downloads a blob from the bucket."""

    storage_client = storage.Client(project=PROJECT_ID)
    bucket = storage_client.get_bucket(CLOUD_STORAGE_BUCKET)
    blob = bucket.blob(source_blob_name)
    file = blob.download_as_string()
    # <class 'bytes'>
    return file

def multi_ml():
    source_filename = request.form['source_file']
    ## source_filename : alldata.csv
    source_data = download_blob(source_filename)

3. 機械学習実行

まず、取得したデータは、最後の要素が目的変数で、それ以外が説明変数である形式であることを前提とします。

説明変数1 説明変数2 目的変数
10 10 100
20 20 200
30 30 300

上記のデータを学習用。テスト用のデータフレームへ分けます。パラメータはデフォルト。

main.py
    import sklearn.model_selection
    df = pd.read_csv(BytesIO(source_data))
    X = df.drop(df.columns.values[len(df.columns)-1], axis=1)
    Y = df.iloc[:, [len(df.columns)-1]]
    X_train, X_test, Y_train, Y_test = sklearn.model_selection.train_test_split(X,Y)

今回テストとして、scikit-learnでランダムフォレストアルゴリズムを使います。パラメータはデフォルト。

main.py(抜粋)
    from sklearn.ensemble import RandomForestRegressor
    rf_reg = RandomForestRegressor()
    rf_reg.fit(X_train, Y_train)

4. 学習モデルはGCSへ保存

上記で学習したモデルを、Pickleでdumpして、名前を指定してGCSへアップロードしておきます。予測で利用します。

main.py(抜粋)
    model = pickle.dumps(rf_reg)
    url = upload_file(model, 'RandomForestModel.pkl', 'application/octet-stream')
main.py(upload_file機能
def upload_file(file_stream, filename, content_type):
    storage_client = _get_storage_client()
    bucket = storage_client.bucket(CLOUD_STORAGE_BUCKET)
    blob = bucket.blob(filename)

    blob.upload_from_string(
        file_stream,
        content_type=content_type)

    url = 'gs://{}/{}'.format(CLOUD_STORAGE_BUCKET, filename)

    return url

学習フェーズはここまで。予測フェーズは以下。

5. 予測のために、GCSから学習モデルを読み込み

GAEがGCSからモデルを取得し、Pickleでモデルをloadします。
(今回、モデルが格納されているURI(gs://)はPOST request内のFORMデータに格納するようにしています。)

main.py
    model_uri = request.form['model']
    ## gs://<uploadurl>/Model.pkl

    model_data = download_blob(model_uri)
    model = pickle.loads(model_data)

予測するための入力データもPOST requestで取得できる前提とします。カンマ区切り。
※この辺りは、学習したデータに合わせてください。

input_data
40,40,40

今回テストで、stringデータを入力した関係もあり、str~list~np.arrayへ変換しています。
このあたりは、入力データに合わせて適宜作り替えてください。

main.py
    input_data = request.form['input']
    input_list = input_data.split(',')
    input_array = np.array([input_list]).astype(np.float64)

6. 予測を実行

あとは、読み込んだモデルを利用して、predictをするだけです。

main.py
    predict_kekka = model.predict(input_array)

結果は適宜利用しましょう。テスト実装では、結果をユーザに返しています。

main.py
    return render_template('predict_kekka.html', predict_kekka=predict_kekka, message=message)

参考

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

おわりに

基本的には機械学習のアーキテクチャではMachineLearningEngine(MLE)を使うものですし、GAEはinstance_classとして、GPUは選択できないので、学習タスクを行うことはあまり適していないと思われます。
ただ、予測タスク(5,6項)を行う分には、GAEは価格も安いので十分に使えるものではないかと思いました。

コードはgithubに公開しました。

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12