iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0

前言

在學校寫作業或是研究所做研究,可能會較專注於模型的建構,但在業界,通常會將這些 AI 模型商品化,讓使用者可以更方便使用它們,例如透過 API 服務,讓使用者上傳影像,即時得到影像推論的結果。今天開始要來介紹 API 開發和部署模型的一些方法,總共會使用到 2 個網頁框架,以及 1 個 UI 介面,會分 3 天來介紹。

Flask

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!」囉!
https://ithelp.ithome.com.tw/upload/images/20241001/20166645C2BVcxWkXb.png

補充

  1. if __name__ == '__main__'::在有些 Python 程式碼會看到這個語法,可以用來判斷該支程式是否為主程式,若此程式被當作模組匯入其他程式中使用,就不會執行它底下的內容。
  2. 裝飾函數(Decorator):在不修改函數定義去讓該函數表達更多功能。
    借助 ChatGPT 解釋:
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 提取上傳的檔案。

補充

  • GET 和 POST:兩者都是伺服器請求的一種方法,GET 為從伺服器取得數據,POST 為將數據發送到伺服器,例如上述程式碼,可以理解成根目錄頁面從伺服器獲得「Welcome!」字串,在 /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 服務,並於本機測試,部署的部分可以使用 HEROKUGlitch 等平臺,讓模型上線供他人使用。

參考資料


上一篇
[Day 23] 推論結果可視化:混淆矩陣
下一篇
[Day 25] 部署模型的方法 (2):FastAPI
系列文
輕鬆上手AI專案-影像分類到部署模型27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言