在學校寫作業或是研究所做研究,可能會較專注於模型的建構,但在業界,通常會將這些 AI 模型商品化,讓使用者可以更方便使用它們,例如透過 API 服務,讓使用者上傳影像,即時得到影像推論的結果。今天開始要來介紹 API 開發和部署模型的一些方法,總共會使用到 2 個網頁框架,以及 1 個 UI 介面,會分 3 天來介紹。
Flask 首次發布於 2010 年,為一種輕量的網頁應用框架,使用 Python 撰寫,並以 Werkzeug WSGI 工具箱和 Jinja2 模板引擎為基礎。今天會使用 Flask 框架寫一支程式碼,以 API 形式讓使用者可以透過指令上傳影像,透過訓練好的模型進行推論,並回傳推論結果的類別名稱和信心值。
先介紹 Flask 基本的使用方法。
from flask import Flask
寫一段程式,並在網頁上顯示「Hello, World!」:
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
首先需要使用 Flask(__name__)
創建 Flask 應用,接著定義路由(Route),括號裡的 '/'
表示網頁的根目錄(Root Directory),根目錄頁面要顯示「Hello, World!」,所以定義一個 hello_world()
函數,表示根目錄頁面會出現這個函數的內容,例如定義一個 hello_world()
函數,會回傳「Hello, World!」。最後使用 app.run()
來啟動伺服器,執行後會出現 http://127.0.0.1:5000 ,打開網頁就會看到「Hello, World!」囉!
if __name__ == '__main__':
:在有些 Python 程式碼會看到這個語法,可以用來判斷該支程式是否為主程式,若此程式被當作模組匯入其他程式中使用,就不會執行它底下的內容。def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
my_decorator
是裝飾函數,它在say_hello
函數執行前後添加了額外的印出語句,而不需要改變say_hello
的原始定義。
from flask import Flask, request, jsonify
import io
import numpy as np
from PIL import Image
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
# 設定 Flask 應用
app = Flask(__name__)
# 載入模型
model = load_model('your_model_name.h5')
# 定義推論影像函式
def predict_image(img: Image.Image):
img = img.resize((256, 256))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
prediction = model.predict(img_array)
return prediction
# 定義根目錄
@app.route("/", methods=["GET"])
def home():
return "Welcome!"
# 定義 /predict/ 頁面
@app.route("/predict/", methods=["POST"])
def predict():
file = request.files['file']
img = Image.open(io.BytesIO(file.read()))
prediction = predict_image(img)
confidence = prediction[0]
predicted_index = np.argmax(confidence)
# 定義分類類別名稱和信心值
class_names = ['black', 'grizzly', 'panda', 'polar', 'teddy']
predicted_class = class_names[predicted_index]
confidence = confidence[predicted_index]
# 回傳分類類別名稱和信心值
return jsonify({"predicted_class": predicted_class,
"confidence": round(float(confidence), 3)})
if __name__ == "__main__":
app.run()
透過 request.files
提取上傳的檔案。
/predict/
頁面可以上傳檔案至伺服器獲取結果(回傳值)。到終端機執行下列指令,your_image_path
換成自己的影像路徑:
curl -X POST "http://127.0.0.1:5000/predict/" -F "file=@your_image_path"
即將影像上傳到 http://127.0.0.1:5000/predict/ 這個頁面進行推論。
執行結果範例:
{"confidence":0.999,"predicted_class":"grizzly"}
得到上傳的影像推論結果和信心值啦!
是不是覺得今天的內容和之前不太一樣呢?明天會介紹另一種網頁框架!
註:本系列部署在介紹網頁框架章節的部分,主要著重在開發 API 服務,並於本機測試,部署的部分可以使用 HEROKU 或 Glitch 等平臺,讓模型上線供他人使用。