公開資料のページに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モデルが問題なく動作することが確認できました。