scikit-learnモデルを使ったFlask APIをHerokuにデプロイする

公開資料のページにscikit-learnで作った回帰分析のモデルをFlask API化する方法を書いてあります。

そのFlaskアプリをHerokuにデプロイする方法をまとめておきます。
Flaskアプリをデプロイする先って意外と面倒で、ロリポップのようなレンタルサーバでも出来ないことはなさそうなのですが、なかなか面倒であることは間違いないし、VPSとかAmazon EC2の環境を使って自分でLinuxサーバーを立ち上げれば良いのですが、それもちょっと試す程度のことには面倒(お仕事としてはやりますけどね・・・)。

ちょっと試す程度なら、ローカル(PC)で動かしてngrokで外部に公開するというのも最近やっているのですが、それは本当にPCを立ち上げている時しか試せないので、そこはやっぱり公開されている状態にしておきたい。

というわけで、Herokuを使ってみようと思う次第。今回使用するモデルはAnscombeをデータとして使ったもので、極めて小さなモデル。なので、Herokuの無料版でも充分動作するわけです。(さすがにAnscombeじゃなくて、もう少しちゃんとしたモデルでも大丈夫じゃないかとは思いますけどね。)

Herokuの環境準備

Herokuを使うには、まずユーザー登録が必要です。
ユーザー登録が終わったら、Heroku CLIをインストールしておきましょう。何かと便利です。

APIサーバの開発

プロジェクトディレクトリにapp.pyファイルを作成し、下記のようにします。詳細は最初にリンクした公開資料の方を参照ください。

from flask import Flask, request, Response
import pickle
import json

app = Flask(__name__)


@app.route('/predict', methods=['POST'])
def predict():
    json_data = request.get_json()

    with open('model.pickle', mode='rb') as fp:
        model = pickle.load(fp)
    pred = model.predict([[json_data['value']]])

    result = {
        "result": pred[0][0]
    }

    return Response(json.dumps(result), content_type='application/json')


if __name__ == '__main__':
    app.run()

公開資料の方のコードと違うのは、最後の2行だけです。

プロジェクトディレクトリにrequirements.txtを作成します。必要なライブラリはこんな感じ。

Flask
gunicorn
sklearn

ローカルPCでの動作確認

ローカルPCでの動作確認は下記のようにします。

まず、必要なライブラリをインストールして・・・

pip install -r requirements.txt

app.pyを起動します。mainのコードを書いてあるので、この方法でFlaskアプリが起動します。

python app.py

Herokuのデプロイ準備

プロジェクトディレクトリに、Procfileを作りましょう。

web: gunicorn app:app --log-file=-

HerokuへのデプロイのためにGitを使用するので、.gitignoreも作っておくと良いでしょう。
.gitignoreファイルの作成には、gitignore.ioがオススメです。

Herokuでアプリ作成

アプリはHeroku CLIでも作れるのですが、ここはWebサイトで作ります。

ここではアプリの名前を指定するくらいです。リージョンは米国かヨーロッパなので、米国を選択しました。

アプリを作成すると、デプロイの方法が表示されます。
基本的にはGitリポジトリにPushすると、Herokuへのデプロイが始まりますので、使用するGitリポジトリを選択します。
今回は、Heroku Gitを使用することにしました。

あとは、このとおりに進めていけばOKです。

Herokuにデプロイ

先ほどの画面どおりに進めます。

heroku login

このコマンドを実行した後、表示されるメッセージに従って何かキーを押下すると、Webブラウザが開いてHerokuへのログインを求められます。

Webブラウザでのログインが完了すると、コマンドプロンプトに戻ります。

まず、ローカルPC上でのGitリポジトリの作成とコミットを行います。ここは、Herokuの画面での説明どおりでも良いですし、普段使っているGitクライアント(私はもっぱらVS Codeばかりですが)を使っても構いません。

Heroku Gitを使うようにしたので、herokuというリモート名でHeroku Gitにプッシュされるように設定します。

heroku git:remote -a <アプリ名>

Heroku Gitにプッシュします。GitコマンドでやるとHerokuへのデプロイの様子が確認できます。GitクライアントでもGit出力が見えれば確認できるでしょう。

git push heroku master

こんなメッセージが表示されます。

Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 12 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 2.42 KiB | 309.00 KiB/s, done.
Total 7 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Python app detected
remote: -----> No Python version was specified. Using the buildpack default: python-3.9.9
remote:        To use a different version, see: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> Installing python-3.9.9
remote: -----> Installing pip 21.3.1, setuptools 57.5.0 and wheel 0.37.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting Flask
remote:          Downloading Flask-2.0.2-py3-none-any.whl (95 kB)
(中略)
remote:        Installing collected packages: numpy, threadpoolctl, scipy, MarkupSafe, joblib, Werkzeug, scikit-learn, Jinja2, itsdangerous, click, sklearn, gunicorn, Flask                                          remote:        Successfully installed Flask-2.0.2 Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 gunicorn-20.1.0 itsdangerous-2.0.1 joblib-1.1.0 numpy-1.21.4 scikit-learn-1.0.1 scipy-1.7.2 sklearn-0.0 threadpoolctl-3.0.0
remote: -----> Discovering process types
remote:
remote: -----> Compressing...
remote:        Done: 141.5M
remote: -----> Launching...
remote:        Released v3
remote:        https://<アプリ名>.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/<アプリ名>.git
 * [new branch]      master -> master

こんな感じで、requirements.txtファイルを用いたPythonライブラリのインストールなども自動的に行われます。

動作確認

デプロイが完了したら、動作確認しましょう。
私はもっぱらVS CodeのREST Clientという拡張機能を使っています。

POST https://<アプリ名>.herokuapp.com/predict
Content-Type: application/json

{
    "value": 30
}

レスポンスはこのようなものでした。

HTTP/1.1 200 OK
Connection: close
Server: gunicorn
Date: Fri, 19 Nov 2021 11:19:45 GMT
Content-Type: application/json
Content-Length: 30
Via: 1.1 vegur

{
  "result": 18.002818181818185
}

Herokuでscikit-learnモデルが問題なく動作することが確認できました。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。画像認識モデルを活用したアプリや、生成AIを業務に組み込むためのサービス「Gen2Go」の開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。