FlaskRESTAPIを使用したPython機械学習予測
公開: 2022-03-11この記事では、Flask REST APIを使用して、リアルタイム予測を行うための機械学習または人工知能(AI)システムのコンテキストでPythonを使用する方法について説明します。 ここで公開されているアーキテクチャは、概念実証(PoC)から機械学習アプリケーションの最小実行可能製品(MVP)に移行する方法と見なすことができます。
Pythonは、リアルタイムソリューションを設計するときに考えることができる最初の選択肢ではありません。 ただし、TensorflowとScikit-Learnは、Pythonでサポートされている最も使用されている機械学習ライブラリの一部であるため、多くのJupyterNotebookPoCで便利に使用されています。
このソリューションを実行可能にするのは、予測に比べてトレーニングに多くの時間がかかるという事実です。 トレーニングを映画を見て、それに関する質問への回答を予測するプロセスと考える場合、新しい質問のたびに映画を再視聴する必要がないのは非常に効率的です。
トレーニングはその「映画」の一種の圧縮されたビューであり、予測は圧縮されたビューから情報を取得することです。 映画が複雑であろうと長かろうと、それは本当に速いはずです。
Pythonで簡単な[Flask]の例を使ってそれを実装しましょう!
一般的な機械学習アーキテクチャ
一般的なトレーニングと予測アーキテクチャのフローの概要から始めましょう。
まず、目的関数に従って過去のデータについて学習するためのトレーニングパイプラインが作成されます。
これにより、2つの重要な要素が出力されます。
- 特徴工学関数:トレーニング時に使用された変換は、予測時に再利用する必要があります。
- モデルパラメータ:最終的に選択されたアルゴリズムとハイパーパラメータを保存して、予測時に再利用できるようにする必要があります
トレーニング中に行われた特徴エンジニアリングは、予測に適用できるように慎重に保存する必要があることに注意してください。 途中で発生する可能性のある他の多くの問題の1つは、多くのアルゴリズムに必要な機能のスケーリングです。
特徴X1が値1から1000にスケーリングされ、関数f(x) = x/max(X1)
で[0,1]範囲に再スケーリングされた場合、予測セットの値が2000の場合はどうなりますか?
マッピング関数が予測時に正しく計算される一貫した出力を返すように、事前にいくつかの注意深い調整を検討する必要があります。
機械学習トレーニングと予測
ここで取り組むべき主要な質問があります。 そもそもなぜトレーニングと予測を分離するのですか?
すべてのデータ(予測されるデータを含む)が事前にわかっている機械学習の例とコースのコンテキストでは、予測子を構築する非常に簡単な方法は、トレーニングと予測データ(通常はテストセット)。
次に、結果を得るために「トレーニングセット」でトレーニングし、「テストセット」で予測すると同時に、トレーニングデータとテストデータの両方で特徴エンジニアリングを行い、同じ独自のパイプラインでトレーニングと予測を行う必要があります。 。
ただし、実際のシステムでは、通常、トレーニングデータがあり、予測されるデータは、処理されているときに入力されます。 言い換えれば、あなたは一度に映画を見て、後でそれについていくつかの質問があります。つまり、答えは簡単で速いはずです。
さらに、トレーニングには時間がかかり(一部の画像セットでは数週間かかる場合があります)、時間の経過とともに十分に安定している必要があるため、通常、新しいデータが着信するたびにモデル全体を再トレーニングする必要はありません。
そのため、トレーニングと予測は多くのシステムで明確に分離できる、または分離する必要があります。これは、インテリジェントシステム(人工または非人工)がどのように学習するかをよりよく反映しています。
過剰適合との関係
トレーニングと予測を分離することも、過剰適合の問題に対処するための良い方法です。
統計では、過剰適合とは、「特定のデータセットに非常に密接に、または正確に対応する分析の生成であり、したがって、追加のデータを適合させたり、将来の観測を確実に予測したりできない可能性があります」。
過剰適合は、多くの機能を備えたデータセット、またはトレーニングデータが限られたデータセットで特に見られます。 どちらの場合も、データには予測変数で検証できる情報と比較して情報が多すぎ、一部のデータは予測変数にリンクされていない可能性があります。 この場合、ノイズ自体が信号として解釈される可能性があります。
過剰適合を制御する良い方法は、データの一部をトレーニングし、グラウンドトゥルースがある別の部分を予測することです。 したがって、新しいデータで予想されるエラーは、トレーニングするデータがシステムの現実とその将来の状態を表す場合、そのデータセットで測定されたエラーとほぼ同じです。
したがって、データの正しい分割とともに適切なトレーニングと予測のパイプラインを設計すれば、過剰適合の問題に対処するだけでなく、そのアーキテクチャを再利用して新しいデータを予測することもできます。
最後のステップは、新しいデータのエラーが予想と同じになるように制御することです。 常にシフトがあり(実際のエラーは常に予想されるエラーを下回っています)、許容できるシフトを決定する必要がありますが、それはこの記事のトピックではありません。
予測のためのRESTAPI
そこで、トレーニングと予測を明確に分離することが役立ちます。 特徴エンジニアリングメソッドとモデルパラメーターを保存すると、これらの要素を使用して単純なRESTAPIを構築できます。
ここで重要なのは、APIの起動時にモデルとパラメーターをロードすることです。 起動されてメモリに保存されると、各API呼び出しは、MLアルゴリズムの特徴エンジニアリング計算と「予測」メソッドをトリガーします。 どちらも通常、リアルタイムの応答を保証するのに十分な速度です。
APIは、予測される固有の例、またはいくつかの異なる例(バッチ予測)を受け入れるように設計できます。
JSON入力とJSON出力(質問入力、回答出力)を使用して、この原則を実装する最小限のPython/Flaskコードを次に示します。
app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call No need to re-load the model """ # reads the received json jsonfile = request.get_json() res = dict() for key in jsonfile.keys(): # calculates and predicts res[key] = model.predict(doTheCalculation(key)) # returns a json file return jsonify(res) if __name__ == '__main__': # Model is loaded when the API is launched model = pickle.load(open('modelfile', 'rb')) app.run(debug=True)
APIは新しいデータからの予測に使用できますが、モデルのトレーニングに使用することはお勧めしません。 使用することもできますが、これによりモデルトレーニングコードが複雑になり、メモリリソースの点でより要求が厳しくなる可能性があります。

実装例-自転車共有
例として、Kaggleデータセット、自転車共有を取り上げましょう。 私たちが自転車のメンテナンス、ロジスティクス、その他のビジネスの側面をより適切に管理するために、毎日の自転車レンタルの数を予測したいと考えている自転車共有会社であるとします。
賃貸料は主に気象条件に依存するため、天気予報を使えば、賃貸料がピークになる時期をより正確に把握し、これらの日のメンテナンスを回避することができます。
まず、モデルをトレーニングして、Jupyterノートブックに表示されるピクルスオブジェクトとして保存します。
モデルのトレーニングとパフォーマンスはここでは扱いません。これは、プロセス全体を理解するための単なる例です。
次に、各API呼び出しで実行されるデータ変換を記述します。
import numpy as np import pandas as pd from datetime import date def doTheCalculation(data): data['dayofyear']=(data['dteday']- data['dteday'].apply(lambda x: date(x.year,1,1)) .astype('datetime64[ns]')).apply(lambda x: x.days) X = np.array(data[['instant','season','yr','holiday','weekday','workingday', 'weathersit','temp','atemp','hum','windspeed','dayofyear']]) return X
これは、月と正確な日の両方を含む変数(年の日)の計算にすぎません。 列の選択と、保持するそれぞれの順序もあります。
次に、Flaskを使用してRESTAPIを作成する必要があります。
from flask import Flask, request, redirect, url_for, flash, jsonify from features_calculation import doTheCalculation import json, pickle import pandas as pd import numpy as np app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call """ jsonfile = request.get_json() data = pd.read_json(json.dumps(jsonfile),orient='index',convert_dates=['dteday']) print(data) res = dict() ypred = model.predict(doTheCalculation(data)) for i in range(len(ypred)): res[i] = ypred[i] return jsonify(res) if __name__ == '__main__': modelfile = 'modelfile.pickle' model = pickle.load(open(modelfile, 'rb')) print("loaded OK") app.run(debug=True)
このプログラムを実行すると、デフォルトでポート5000でAPIが提供されます。
リクエストをローカルでテストする場合、Pythonを使用します。
import requests, json url = '[http://127.0.0.1:5000/api/makecalc/](http://127.0.0.1:5000/api/makecalc/)' text = json.dumps({"0":{"instant":1,"dteday":"2011-01-01T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":6,"workingday":0,"weathersit":2,"temp":0.344167,"atemp":0.363625,"hum":0.805833,"windspeed":0.160446}, "1":{"instant":2,"dteday":"2011-01-02T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":3,"workingday":0,"weathersit":2,"temp":0.363478,"atemp":0.353739,"hum":0.696087,"windspeed":0.248539}, "2":{"instant":3,"dteday":"2011-01-03T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":1,"workingday":1,"weathersit":1,"temp":0.196364,"atemp":0.189405,"hum":0.437273,"windspeed":0.248309}})
リクエストには、モデルに提供されたすべての情報が含まれています。 したがって、私たちのモデルは、指定された日付の自転車レンタルの予測で応答します(ここでは3つあります)。
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} r = requests.post(url, data=text, headers=headers) print(r,r.text) <Response [200]> { "0": 1063, "1": 1028, "2": 1399 }
それでおしまい! このサービスは、メンテナンス計画のため、またはユーザーが自転車の交通量、需要、およびレンタサイクルの可用性を認識するために、どの企業のアプリケーションでも簡単に使用できます。
すべてを一緒に入れて
多くの機械学習システム、特にPoCの主な欠点は、トレーニングと予測を組み合わせることにあります。
それらを注意深く分離すると、MVPのリアルタイム予測を非常に簡単に実行できます。特に、多くのPoCで、最初にScikit-learn、Tensorflow、または他のPython機械学習ライブラリ。
ただし、これはすべてのアプリケーション、特に特徴エンジニアリングが重いアプリケーション、または各呼び出しで最新のデータを利用できるようにする必要がある最も近い一致を取得するアプリケーションでは実行できない場合があります。
いずれにせよ、あなたはそれらについての質問に答えるために何度も映画を見る必要がありますか? 同じルールが機械学習にも当てはまります。