iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
AI & Data

全民瘋AI系列2.0系列 第 28

[Day 28] 儲存訓練好的模型

  • 分享至 

  • xImage
  •  

儲存訓練好的模型

今日學習目標

  • 使用 pickle + gzip 儲存模型
    • 將訓練好的模型打包並儲存
  • 載入儲存的模型
    • 讀取打包好的模型並預測

前言

今天的教學內容要教各位如何將訓練好的模型儲存,並提供下一次載入模型和預測。在本系列的教學中介紹了許多 Sklearn 的模型演算法。當模型訓練好了,可以將訓練結果儲存起來,並建立一個 API 接口提供模型預測。

https://ithelp.ithome.com.tw/upload/images/20211010/20107247gGHs2Ux4t0.png

模型儲存方法

常見的儲存模型的套件有 picklejoblib。其中在 [Day 20] 機器學習金手指 - Auto-sklearn 最後有使用 joblib 來儲存模型,操作方法也非常簡單。然而在今天的教學中則使用另一種方法 pickle 來儲存模型。由於 pickle 儲存模型後容量可能會有好幾百 MB 因此建議可以透過 gzip 來壓縮模型並儲存。另外在 Python 官方文件中有警告絕對不要利用 pickle 來 unpickle 來路不明的檔案。因為透過 pickle 打包模型會有安全性疑慮,包括 arbitrary code execution 的問題,詳細內容可以參考這篇文章。如果要追求執行速度與安全性,建議可以採用 JSON 格式來存取模型的參數與設定。

後記:這幾年ONNX模型通用格式也非常流行,除了神經網路之外也支援sklearn的模型儲存。大家不妨也可以試試看!

1) 載入資料集

今日的範例還是拿鳶尾花朵資料集進行示範。首先我們先載入資料集並進行資料的切割。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris

iris = load_iris()
df_data = pd.DataFrame(data= np.c_[iris['data'], iris['target']],
                     columns= ['SepalLengthCm','SepalWidthCm','PetalLengthCm','PetalWidthCm','Species'])
df_data

2) 切割訓練集與測試集

from sklearn.model_selection import train_test_split
X = df_data.drop(labels=['Species'],axis=1).values # 移除Species並取得剩下欄位資料
y = df_data['Species'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)

print('train shape:', X_train.shape)
print('test shape:', X_test.shape)

訓練模型 - XGBoost

XGBoost 模型是目前最熱門的演算法模型之一,詳細的內容可以參考 [Day 15] 機器學習常勝軍 - XGBoost。裡面會有介紹詳細的模型說明與手把手實作。當然大家也可以試著用其他 Sklearn 的模型訓練看看,一樣可以透過 pickle 來儲存訓練好的模型。

from xgboost import XGBClassifier

# 建立 XGBClassifier 模型
xgboostModel = XGBClassifier(n_estimators=100, learning_rate= 0.3)
# 使用訓練資料訓練模型
xgboostModel.fit(X_train, y_train)
# 使用訓練資料預測分類
predicted = xgboostModel.predict(X_train)

儲存 XGboost 模型

大家可以觀察 .pickle.gzip 兩種不同副檔名儲存結果檔案大小有何差別?

1. 使用 pickle 儲存模型

import pickle
with open('./model/xgboost-iris.pickle', 'wb') as f:
    pickle.dump(xgboostModel, f)

2. 使用 pickle 儲存模型並利用 gzip 壓縮

import pickle
import gzip
with gzip.GzipFile('./model/xgboost-iris.pgz', 'w') as f:
    pickle.dump(xgboostModel, f)

https://ithelp.ithome.com.tw/upload/images/20211010/20107247cXrS6Ls7IA.png

載入 XGboost 模型

試著載入兩種不同格式的模型,並預測一筆資料。注意模型預測輸入必須為 numpy 型態,且須為二維陣列格式。

1. 載入 gzip 格式模型

import pickle
import gzip

#讀取Model
with gzip.open('./model/xgboost-iris.pgz', 'r') as f:
    xgboostModel = pickle.load(f)
    pred=xgboostModel.predict(np.array([[5.5, 2.4, 3.7, 1. ]]))
    print(pred)

2. 載入 pickle 格式模型

#讀取Model
with open('./model/xgboost-iris.pickle', 'rb') as f:
    xgboostModel = pickle.load(f)
    pred=xgboostModel.predict(np.array([[5.5, 2.4, 3.7, 1. ]]))
    print(pred)

雙十1010連假愉快/images/emoticon/emoticon42.gif

Reference

本系列教學內容及範例程式都可以從我的 GitHub 取得!


上一篇
[Day 27] 機器學習常犯錯的十件事
下一篇
[Day 29] 使用 Python Flask 架設 API 吧!
系列文
全民瘋AI系列2.031
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Rick
iT邦新手 5 級 ‧ 2023-02-25 11:01:23

10程式中 你好, 看了您一系列的文章下來到這個階段, 有個想請教, 如果訓練跟測試模型時都是使用這個function去執行(這datafram有多個season),
https://ithelp.ithome.com.tw/upload/images/20230225/20135894RxV7GGr6Uc.png

那將訓練好的模型存下來以後要使用, 但是輸入要測試的datafram的column數 必須要相同於train時用的feature 數量, 若手邊有的測試數據 沒辦法吻合 測試時用的features, 請問是該更改測試數據 還是訓練數據?

非常感激您有空可以幫我解答, 謝謝

10程式中 iT邦研究生 4 級 ‧ 2023-02-25 21:19:16 檢舉

Hi Rick

  1. 模型訓練完以後,實際新的資料要推論時,要跟當時訓練集的特徵數量與排序相同。此外若有進行資料前處理(例如正規化),也必須走一次相同的流程。
  2. 手邊的測試數據(特徵數)沒辦法符合訓練時的情況,這樣就無法拿訓練好的模型對這些測試數據進行推論了。只能再另行搜集更多資料重新建模。

我要留言

立即登入留言