如何用 Python 建立 Machine Learning Models Flask-RESTful API?

IT 點技能
8 min readFeb 19, 2023

--

開發環境建立

  1. 開發工具:Visual Studio Code
  2. 安裝 Python
  3. 安裝 Visual Studio Code Jupyter 套件
  4. 安裝會用到的 Python 函式庫
pip install numpy scikit-learn flask-restful requests pandas

建立 Machine Learning Model 並產出 pickle 檔 (參考 Github 上的 Jupyter Notebook

  1. 這個 Jupyter Notebook 模擬一個機器學習演算法產出模型的 pickle 檔,使用機器學習資料集 — Iris dataset 進行資料載入、分群、訓練模型、預測模型,使用混淆矩陣 (confusion matrix) 判斷模型表現的好不好,最後產出模型的 pickle 檔。
  2. Iris dataset 是一個花朵資料集,由英國統計學家 Ronald Fisher 爵士在 1936 年對加斯帕半島上的鳶尾屬花朵所提取的花瓣花萼的長寬數據資料,有以下共150筆資料:
  • 三種花卉:setosa(山鳶尾)、versicolor(變色鳶尾)、virginica(維吉尼亞鳶尾)
  • 四種屬性:Sepal length: 花萼長度 (cm)、Sepal width: 花萼寬度 (cm)、Petal length: 花瓣長度 (cm)、Petal width: 花瓣寬度 (cm)

開發 RESTful API 介接 Machine Learning Model(參考 Github 上的 Python Code

  1. 載入需要的開發模組:
from flask import Flask, jsonify
from flask_restful import Api, Resource, reqparse
import pickle
import numpy as np
import json

2. 建立 Flask app 物件:

app = Flask(__name__)
api = Api(app)

3. 建立 request parser 去解析 request 傳入的參數:

# Create parser for the payload data
parser = reqparse.RequestParser()
parser.add_argument('data')

4. 定義繼承自 flask_restful Resource 的類別,實作 Post Request:

class IrisClassifier(Resource):
def post(self):
args = parser.parse_args()
X = np.array(json.loads(args['data']))
prediction = model.predict(X)
return jsonify(prediction.tolist())

5. 定義 RESTful API URL:

api.add_resource(IrisClassifier, '/iris')

6. 載入模型並啟動 flask app:

if __name__ == '__main__':
# Load model
with open('model.pickle', 'rb') as f:
model = pickle.load(f)

app.run(port=5000 ,debug=True)

7. 執行 RESTful API:

python api.py

8. 啟動結果:

開發測試 RESTful API(參考 Github 上的 Python Code

  1. 載入需要的開發模組:
import numpy as np
import requests
import json

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

2. 載入機器學習資料集 — Iris dataset:

# Load data
iris = load_iris()

3. 進行測試資料分群:

# Split into train and test sets using the same random state
X_train, X_test, y_train, y_test = train_test_split(iris['data'], iris['target'], random_state=12)

4. 設定 request payload:

# Serialize the data into json and send the request to the model
xTest = json.dumps(X_test.tolist());
payload = {'data': xTest}
# Fix the single quote bug
payload = json.dumps(payload)

5. 將資料送到 API:

# Set request's header.
headers = {'Content-type': 'application/json'}
y_predict = requests.post('http://127.0.0.1:5000/iris', headers=headers, data=payload)

6. 印出模型回覆的結果:

# Make array from the list
y_predict = np.array(y_predict.json())
print(y_predict)

7. 執行 Test API:

python test_api.py

8. 測試結果:

測試 API 依序遇到問題與解法

  • 測試 API 依序遇到問題與解法
  1. 錯誤訊息:Did not attempt to load JSON data because the request Content-Type was not ‘application/json’ request header 'Content-type': 'application/json',
  • 將資料送到 API 時,request 沒加 request header ‘Content-type’: ‘application/json’,加了就跳下一個錯誤訊息。

2. 錯誤訊息:Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)

--

--