洋食の日記

「だ・である」調ではなく「です・ます」調で書きはじめれば良かったなと後悔してる人のブログです

TheanoなKerasをデプロイするときはNginx+uWSGI+Flaskが良さそう

Kerasで作った画像認識プログラムを、Webサービスの形にしてみようと思い色々ためした。 画像認識処理をAPIの形で立ち上げ、フロントから叩くことにした。 複雑で大規模な構造のAPIにはならないので、フレームワークにはFlaskを選択した。 はじめ、Apache2+mod_wsgiを考えたが、設定ファイルがなんだか面倒なのと、 APIを叩くたびに「Using Theano backend.」とかimportから始まるのでツラい(これも設定ファイルでなんとかなるのかもだけど掘り下げてない)。 KerasなのにTensorFlowじゃないのは、Kerasが出たての頃から使ってて~/.keras/keras.jsonがそんな設定になってるからで、こだわりではない。 そんなわけで、まずは、TheanoなKerasのFlaskアプリを用意する。ちなみに、OSはDebian GNU/Linuxです。

# -*- coding: utf-8 -*-

# 学習するわけではないのでCPUモードで起動する。
# 環境変数をプログラム中で変えることでKerasとTheanoを設定する。
import os
os.environ['KERAS_BACKEND'] = 'theano'
os.environ['THEANO_FLAGS'] = 'mode=FAST_RUN,device=cpu,floatX=float32'
# Kerasがらみ
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
from keras.models import Model
from keras.models import model_from_json
# Flaskがらみ
from flask import Flask

# 省略...(学習したモデルを読み込んだりとか)

app = Flask(__name__)
@app.route('/')
def index():

# 省略...(認識した結果をJSONで返したりとか)

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

Nginxの設定ファイルを書く。sites-available以下に書いて、sites-enabledからシンボリックリンクを張るのが、DebianなNginxのマナー。 5000番ポートをlistenしてるのは、Flask単体でrunしたとき、localhost:5000でサーバーが動くので、その名残り。意味はない。location内のほうが大事で、適当なsocket(/hoge/uwsgi.sock)を用意して、これを介してuwsgiにつなぐ。設定の楽さに感動。

$ sudo vim /etc/nginx/sites-available/uwsgi
server {
  listen 5000;
  listen [::]:5000;

  location / {
    include uwsgi_params;
    uwsgi_pass unix:/hoge/uwsgi.sock;
  }
}
$ cd /etc/nginx/sites-enabled
$ sudo ln -sn /etc/nginx/sites-available/uwsgi

そして、uwsgiでFlaskアプリを動かす。uwsgiの設定ファイルを用意すると、オプションの指定が楽になるんだろうけど、とりあえず試したいだけなので、コマンドで実行する。

# Flaskアプリのファイルはhoge.pyだとして...
$ /usr/local/bin/uwsgi -s /hoge/uwsgi.sock --wsgi hoge:app --chmod-socket=666
*** Starting uWSGI 2.0.14 (64bit) on [Sun Mar 12 15:20:11 2017] ***

...

*** Operational MODE: single process ***
Using Theano backend.
WSGI app 0 (mountpoint='') ready in 7 seconds on interpreter 0x1a2e1e0 pid: 10892 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 10892, cores: 1)

この状態で、APIをいくら叩いても「Using Theano backend.」とかならなかったので、とても良い。 Kerasでは~/.keras以下に設定ファイルや学習済みCNNモデルなどを置くので、デプロイするためのユーザーを用意したほうが良いかもしれない。 ちなみに、Apache2+mod_wsgiAPIを立ち上げたときは、/var/www/.kerasや/var/www/.theanoが作られた。