iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
AI & Data

我不太懂 AI,可是我會一點 Python 和 Azure系列 第 24

Day 24 Azure machine learning: deploy service and inference- 模型訓練完就是要拿來用啊

Azure machine learning: deploy service and inference- 模型訓練完就是要拿來用啊

搞了半天,終於有了一個堪用的模型,現在我們要來部署了。一開始部署,我也是吃足了苦頭,原因是沒有考慮清楚環境的設定,也沒有考慮清楚要怎麼跟服務互動,後來搞清楚狀況後,就顯得相當簡單了。最先該做的事情,就是直接使用原本準備好的環境,就87%沒有問題了。

部署服務與使用服務

  • 部署服務時,一樣需要兩份 py 檔

    1. 一個在workspace利用運算群組執行predict_currency.py
    2. 另一個是deploy_currency_prediction.py,在本機執行,將預測的服務部署在workspace
  • 使用服務,也就是標題上所寫的 inference,這個詞直接查字典的話,意思是推論或推斷,可以想做,我們利用過去蒐集到的資料做成一個模型之後,利用此模型推論未來的情境。白話一點,其實就是把做好的模型拿來使用。服務部署完成後,會產生該服務的 API ,便可以透過 API 使用預測服務了。

示範程式

  • 用來執行預測服務的程式碼結構基本上是固定的,必須定義兩個 function:
    • init:讀取模型。
    • run:當使用者呼叫 API 時,執行預測,並回傳結果。

predict_currency.py

import os
from datetime import datetime, timedelta
import pickle
from keras.models import load_model
import investpy


def init():
    """
    Load the model
    """
    global model
    global scaler
    
    # 模型的預設路徑就是 /var/azureml-app/azureml-models/,從中找到相對應的模型
    for root, _, files in os.walk("/var/azureml-app/azureml-models/", topdown=False):
        for name in files:
            if name.split(".")[-1] == "h5":
                model_path = os.path.join(root, name)
            elif name.split(".")[-1] == "pickle":
                scaler_path = os.path.join(root, name)
    model = load_model(model_path)
    with open(scaler_path, "rb") as f_h:
        scaler = pickle.load(f_h)
    f_h.close()

# 這邊的 raw_data 並沒有被使用到,因為資料可以直接透過 investpy 取得。
# 但因為直接省略 raw_data ,是無法部署的,所以只好保留。
def run(raw_data):
    """
    Prediction
    """
    
    today = datetime.now()
    data = investpy.get_currency_cross_historical_data(
        "USD/TWD",
        from_date=(today - timedelta(weeks=105)).strftime("%d/%m/%Y"),
        to_date=today.strftime("%d/%m/%Y"),
    )
    data.reset_index(inplace=True)
    data = data.tail(240).Close.values.reshape(-1, 1)
    data = scaler.transform(data)
    data = data.reshape((1, 240, 1))
    ans = model.predict(data)
    ans = scaler.inverse_transform(ans)
    # 要注意回傳的數值必須要是 JSON 支援的資料格式
    return float(ans[0][0])
  • 部署服務時,需要考慮執行環境,如果沒有事先準備好現成的環境,服務部屬的時間會非常久,因為會從環境準備開始。
  • 需要指定模型,包含版本和名稱,這樣predict_currency.py才找得到相對應的模型。
    deploy_currency_prediction.py
import os
import numpy as np
from azureml.core import Model, Workspace
from azureml.core import Run
from azureml.core.model import InferenceConfig
from azureml.core.webservice import AciWebservice
from azureml.core.authentication import InteractiveLoginAuthentication


def main():
    """
    Deploy model to your service
    """
    # 為了之後 pipeline 的使用,所以使用兩種方式取得 workspace。
    run = Run.get_context()
    try:
        work_space = run.experiment.workspace
    except AttributeError:
        interactive_auth = InteractiveLoginAuthentication(
            tenant_id=os.getenv("TENANT_ID")
        )
        work_space = Workspace.from_config(auth=interactive_auth)
    # 選擇之前已經建立好的環境
    environment = work_space.environments["train_lstm"]
    
    # 選擇模型,如果不挑選版本,則會直接挑選最新模型
    model = Model(work_space, "currency")
    
    # scaler 也是會用到
    scaler = Model(work_space, name="scaler", version=1)
    # 設定部署服務的 config
    service_name = "currency-service"
    inference_config = InferenceConfig(
        entry_script="predict_currency.py", environment=environment
    )
    # 設定執行服務的資源
    aci_config = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1)
    
    # 部署服務
    service = Model.deploy(
        workspace=work_space,
        name=service_name,
        models=[model, scaler],
        inference_config=inference_config,
        deployment_config=aci_config,
        overwrite=True,
    )
    service.wait_for_deployment(show_output=True)
    print(service.get_logs())
    # 印出服務連結,之後就是利用這個連結提供服務
    print(service.scoring_uri)


if __name__ == "__main__":
    main()
  • 服務部署完成之後,可以到workspace的端點,檢視服務的相關資訊。

  • 點進去剛剛產生的服務,可以看到 REST 端點,這其實就是服務連結,可以透過POST使用。

  • 接著,便可嘗試呼叫剛剛取得的服務連結來使用服務

predict_currency_azml.py


import argparse
import json
import requests


def parse_args():
    """
    Parse arguments
    """
    parser = argparse.ArgumentParser()
    # endpoint url 就是 API 的連結
    parser.add_argument("-e", "--endpoint_url", type=str, help="Endpoint url")
    args = parser.parse_args()
    return args


def main():
    """
    Predict mnist data with Azure machine learning
    """
    args = parse_args()
    data = {"data": ""}
    # 將資料轉換成 JSON 
    input_data = json.dumps(data)
    # Set the content type
    headers = {"Content-Type": "application/json"}

    # 使用 POST 呼叫 API
    resp = requests.post(args.endpoint_url, input_data, headers=headers)

    print("The answer is {}".format(resp.text))


if __name__ == "__main__":
    main()
  • 直接在 terminal 執行 python3.7 predict_currency_azml.py -e 你的 API 連結,就會得到預測結果了。

做到這一步,算是完整的走一遍,利用 Azure machine learning 訓練模型與部屬服務的流程了,但實際應用上,可能還要考慮日後更新資料和模型的問題,這就會需要用到pipelinesechedule的概念。下一篇,先從pipeline開始。


上一篇
Day 23 Azure machine learning: training experiment and register model- 以 LSTM 模型為例
下一篇
Day 25 Azure machine learning: Pipeline for data- 建立工作流程來收集資料
系列文
我不太懂 AI,可是我會一點 Python 和 Azure30

尚未有邦友留言

立即登入留言