今回の内容
ノンプログラミングで機械学習サービスが作りたい! テキスト分類編の第2弾です。機械学習の分類結果をWebAPIから利用できるようにします。
この段階になるとさすがにノンプログラミングというわけにはいかず、早くもタイトル詐欺くさくなってきましたが、60行ちょっとのコードですので読み解くのは難しくないと思います。
ソースはhttps://github.com/shuukei-imas-cg/imas_cg_words で公開しています。
使用するフレームワーク、ソフトウェアについて
Falcon
Falconはバックエンド用途の非常に高速でミニマルなWebフレームワークです。公式サイトに掲載されているベンチマークによれば、Python用webフレームワークとして定番のFlask(0.11.1)に対して9倍のパフォーマンスを発揮するとあります。
今回はせっかくなのでcythonizeを行い、より高速に動作するようにセットアップします。
Gunicorn
GunicornはFalconでも推奨されているシンプルで高速なWSGI Webサーバです。
WSGIはWeb Server Gateway Interfaceの略で、WebサーバとWebフレームワークの標準化されたインタフェース定義です。これに従っていれば、好きなWebサーバとWebアプリケーション(フレームワーク)の組み合わせで利用可能です。
サンプル実行手順
cd imas_cg_words/ (前回記事でcloneしたディレクトリ)
git pull
# Gunicorn, cythonをインストールする
pip install cython gunicorn
# Cコンパイラでfalconをコンパイルしつつインストール
pip install --no-binary :all: falcon
# localhostでwebapiサーバを起動
cd webapi/
python server.py &
# クエリ
curl http://localhost:8080/imas_cg-words/v1/predict/妄想
[
{
"score": 1.2635555267333984,
"name:": "喜多日菜子"
},
{
"score": -0.9001807570457458,
"name:": "棟方愛海"
},
{
"score": -1.0048713684082031,
"name:": "浅利七海"
}
]
curlでクエリを投げて上記のように表示されれば正常に動作しています。
任意のテキストをHTTP GETメソッドで受け取り、その分類結果をJSON形式で返します。
外部から利用可能なWebAPIとして公開する場合
外部からもアクセス可能なWebAPIとして公開する場合、simple_serverでは力不足ですので、以下のようにGunicornを用います。
Gunicornから起動する場合、config.py内で設定したIPアドレスとポート番号は無視され、コマンドラインオプションで指定した値が優先されることに注意します。
gunicorn -b (IPアドレス):(ポート番号) server:api &
# ワーカ数やログファイルを指定する場合
gunicorn -w 4 -b (IPアドレス):(ポート番号) --access-logfile log/access.log --error-logfile log/error.log server:api &
IPアドレスには外部から参照可能なIPアドレスを指定してください。
解説
webapi/server.pyの内容を解説していきます。
まずFalconのインスタンスを生成し、URIのパスにクラスPredictSerifを割り当てるルーティングの設定を行います。{words}の部分は任意の値を取り、その内容は変数としてクラスや関数に渡されます。
# Add route
api = falcon.API()
api.add_route('/imas_cg-words/v1/predict/{words}', PredictSerif())
PredictSerifではHTTP GETメソッド時の挙動を定義します。関数predictの中身は前回作成したものとほぼ同様です。
その返り値をJSON形式に変換し、WebAPIの出力として表示させています。
_add_headersは幾つかのHTTPヘッダを追加しています。次回の記事で、JavaScriptを用いたSPAからこのWebAPIにアクセスするため、とりあえずCORSを許可する設定を行っています。
class PredictSerif(object):
def on_get(self, req, resp, words):
result = predict(words)
json_out = json.dumps(result, indent=4, ensure_ascii=False)
_add_headers(resp)
resp.body = json_out
resp.status = falcon.HTTP_200
logging.info("predict {0} {1}".format(req.remote_addr, words.decode('utf-8')))
json.dumpsのindent=4は可読性のために設定してあります。本番では削除しても良いでしょう。
次回
これで機械学習の分類機能をWebAPIとして利用できるようになりました。次回は、このWebAPIを利用するフロントエンドをVue.jsで作成します。
最後に(重要)
もしこの記事を気に入っていただけたら、あなたが「いい」と思った分だけ、アイドルマスターシンデレラガールズで2018年4月頃に開催されると思われる「第7回シンデレラガール総選挙」で喜多日菜子に投票してください。