0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

turicreateを使ったモデルからデータを返却するAPIを作成する

Last updated at Posted at 2020-03-21

概要

turicreateという Apple製の機械学習のライブラリがある。(machine learning modelsってことなのでそれで良いはず)

こいつを使ったモデルをGCP上で扱う構成を作ったときのメモ
参考: https://cloud.google.com/blog/products/ai-machine-learning/how-to-serve-deep-learning-models-using-tensorflow-2-0-with-cloud-functions

構成

*CloudRunって書いてある部分はアイコンがなかったのでGAEのアイコンで代用しています

Untitled (1).png

ユーザはGAEに対してアクセスし、その後ろでCloud Runがstorageからmodelをdownloadしてきて動く。
もちろん毎回storageから持ってくると意味がないのでロードしたモデルはメモリ上にキャッシュする。

困ったこと+解消方法

参考の構成では、TensorflowのmodelをCloud FunctionsでloadしてAPIとして、返しているがTuricreateの場合、おそらく依存関係の解消をしようとしている際にbuildができずにエラーになってしまう。(GAEでやっても同じ、Cloud Buildの設定をいじれれば良いのかもしれないがGAEやCloud Functionsからそれが触れるのかがわからなかった)

そのため、自分で実行imageを作ってdeployし動かすことができる、Cloud Runを使うことにした

実装

実装自体は何ということのないもの、ほぼほぼpython+CloudRunの構成に沿っている

main.py
import turicreate
import os
from flask import Flask, request, jsonify
from google.cloud import storage
import zipfile

model = None

app = Flask(__name__)


def download_model(bucket_name, source_blob_name, dest_blob_name):
    storage_client = storage.Client()
    bucket = storage_client.get_bucket(bucket_name)
    blob = bucket.blob(source_blob_name)

    blob.download_to_filename(dest_blob_name)
    with zipfile.ZipFile(dest_blob_name) as modelZip:
        modelZip.extractall('.')


@app.route('/')
def root():
    global model
    request_json = request.get_json()

    if request.args and 'userId' in request.args:
        userId = request.args.get('userId')
    else:
        return jsonify({'message': 'userId is not found'}), 400
    if 'limit' in request.args:
        limit = int(request.args.get('limit'))
    else:
        limit = 10

    if model is None:
        load_model()

    result = model.recommend(users=[userId], k=limit)

    random.shuffle(result)
    return jsonify({'result': result})

def load_model():
    global model

    os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './credential.json'
    download_model("learning-data", "model.zip", "./model.zip")
    model = turicreate.load_model('./model')
    

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=int(
        os.environ.get('PORT', 8080)), debug=False)
FROM python:3.7

ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . .

RUN pip install -r requirements.txt

CMD [ "python", "main.py" ]
requirements.txt
turicreate==6.1
flask==1.1.1
gunicorn==20.0.4
google-cloud-storage==1.26.0

GAEの方は出来上がったserviceにアクセスしていればOK

課題

  • 上記の場合instanceが残り続けた場合どうなるのか、modelの更新のタイミングをみて動くようにしたい
  • instanceが増えた場合どうやって更新するか

→ 一旦考えているのは、メモリにあるデータは key: 時間、 value: model のようにすることで別途タイミングで先にモデルデータを非同期で読み込むようにしておく方法

このあたりが参考になるかも
https://cloud.google.com/run/docs/tips?hl=ja

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?