nikkie-ftnextの日記

イベントレポートや読書メモを発信

イベントレポート | Pythonもくもく自習室 #13 あやめの分類器をAPIに組み込み、Dockerイメージ作成 #rettypy

はじめに

いつも心は虹色に! nikkieです。
rettypyにお邪魔してstapyのDockerトーク準備を進めてきました。
9/12に話します:みんなのPython勉強会#38 - connpass

勉強会の概要

Pythonもくもく自習室 #13 @ Rettyオフィス - connpass

週末の昼下がりに、Pythonに関するやりたいことを各自持ち寄り、ゆるゆると「自習」を進めていく会です。
本を読む
PythonDjangoなどのチュートリアルをすすめる
コミュニティの作業や執筆etc...
他の参加者と情報交換をしたり学んだり
おいしいご飯と共に楽しむ(?)
など、Python使いおよびエンジニアライフのオアシス&知見を身につける「自習室」としてゆるくご活用いただければと思います。

今回はPyCon準備枠が設けられ、皆さま粛々と登壇準備されていました。
主催のshinyorkeさんがまとめてくださいました。

私はトークの題材を転換することにし、以下に取り組みました。

  • 機械学習のモデルを作る
  • モデルをFlaskでAPIにする
  • FlaskアプリケーションをDockerコンテナにする

トークの題材の転換

1週間前のトークの構成: DockerでのPythonの環境構築について
イベントレポート | 第31回 Pythonもくもく会 〜Dockerトーク準備〜 #mokupy - nikkie-ftnextの日記

  • docker run の使い方がメイン
  • メッセージ: 機械学習の環境とWeb開発の環境、どちらもDockerで省力化して構築できます

この1週間、stapy参加者で環境構築の話を聞きたい人っている?と自問を繰り返した1ところ、
あまりいないのではないかということに気づく。

  • 機械学習の環境: そもそも数モジュールならpipで入る。Anacondaで入れている人には魅力がなさそう
  • Webの環境: stapy参加者のメインは、エンジニアでないがPythonを始めた or 他の言語もやっているがPythonも始めた方(あくまで私の印象です)
    • Pythonをはじめる大きな理由は機械学習という印象。-> Webの話は興味をもたれづらいか。。

そこで、デプロイの面を語ることで立て直しを測る。

  • 機械学習: モデルをAPIにする際にデプロイが発生。ここでFlaskを使うことが多い
  • Web: デプロイというトピックには興味もっていただけそう

機械学習のモデルを作る

機械学習については入門レベルなので、本を参考に。
Python機械学習プログラミング2の3章でscikit-learnであやめの分類器を作るのをなぞりました。
python-machine-learning-book/ch03.ipynb at master · rasbt/python-machine-learning-book · GitHub

iris = datasets.load_iris()
# Petal(花びら)のlengthとwidthから品種を分類する
X = iris.data[:, [2, 3]]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0)
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
ppn = Perceptron(max_iter=40, eta0=0.1, random_state=0, shuffle=True)
ppn.fit(X_train_std, y_train)
  • scikit-learnとnumpyの他にscipyを入れる必要があった(datasetsのimportで落ちて判明)
  • DeprecationWarningへの対応: from sklearn.model_selection import train_test_split
  • DeprecationWarningへの対応: Perceptronにはn_iterに代えてmax_iterとtolを使う3

モデルをFlaskでAPIにする

Flaskのアプリケーション側でロードするために、モデルとScalerを掃き出しておきます。4

from sklearn.externals import joblib
joblib.dump(ppn, 'ppn_iris.pkl')
joblib.dump(sc, 'sc_iris_petal.pkl')
  • 作ったモデルはPetal(花びら)のlengthとwidthから品種を分類
  • APIにはPetal(花びら)のlengthとwidthからなるJSONがPOSTされると想定

  • 受け取ったlengthとwidthはそれぞれStandardScalerで標準化する

  • 標準化した値を分類器に与える
  • 分類器の返した値をAPIの返り値とする
@app.route('/predict', methods=['POST'])
def predict():
    input_ = request.get_json()
    length = float(input_['length'])
    width = float(input_['width'])
    input_std = sc.transform(np.array([[length, width]]))
    prediction = ppn.predict(input_std)
    response = jsonify({'prediction': int(prediction[0])})
    response.status_code = 200
    return response

FlaskアプリケーションをDockerコンテナにする

過去にAzureで動かせたアプリケーションをベースに作成。
(今後デプロイして確認します→9/2 Azure WebAppsでは動かず、復旧及び原因調査中)
参考:chhantyal/flask-docker

FROM python:3.6
RUN apt update && apt install python-dev -y
COPY . /home
RUN cd /home && pip install -r requirements.txt
EXPOSE 5000
WORKDIR /home/app
ENTRYPOINT ["gunicorn", "-b", "0.0.0.0:5000", "--access-logfile", "-", "--error-logfile", "-"]
CMD ["app:app"]

残り時間はここまでをスライドに移植していました。

成果発表から

PyConが近く非常に濃い時間でした。触ってみたいものをピックアップ

  • NuxtUI:きれいに動いていて一目惚れ
  • TranscriptPythonJavascriptに変換。知っているPythonでフロントエンドがどの程度作れるのか触っておきたい
  • tsumiki:Jupyterのスライドでセルを横に並べる配置を可能に!GitPitchから乗り換えるまでありますね

終わりに

成果発表の時間が濃くてめちゃくちゃモチベーション上がりました。
Dockerトーク、用語の説明が課題ですが、ご指摘いただいた観点を取り込みつつ、
自分の理解を言葉にして説明してみようと思います。

参加者の皆さま、1日ありがとうございました。お疲れ様でした。
PyConで発表聞きに行くの楽しみです。


  1. 勤務先でペルソナを考えるようになった影響だと思います

  2. ちょうど手元にあった旧版を参照しました。増補した第2版が発売しています

  3. tolは設定しなくても本と同じ結果になりました。時間があれば今後調べます。

  4. 参考:A Flask API for serving scikit-learn models