前提
以下の環境で実装、動作確認済み
要素 | バージョン |
---|---|
debian | 8.6 |
python | 3.6.2 |
scikit-learnによる機械学習シリーズ
機械学習も数学もPythonもよくわからなくても機械学習はデキるシリーズ
- 1: 足し算を学習させる
- 2: 足し算学習モデルを評価する
- 3: 自動車の情報から価格を予測する
- 4: 学習が完了したモデルを永続化する ← イマココ
概要
前回、自動車の情報から価格を予測する学習モデルを構築し、それを評価した。
しかし、予測を行おうとスクリプトを実行するたびに学習モデルを構築しているのは無駄でしかないので、一度作成した学習モデルをシリアライズし、使いまわせるようにする。以降では、シリアライズされた学習モデルをデシリアライズして予測を行うことで、学習作業を省略することができる。
シリアライズ
今回は、scikit-learnのjoblibを用いてシリアライズする。以下のimport文が必要
from sklearn.externals import joblib
学習が完了したモデル(clf)を、cars.plkのファイル名で保存する場合は以下のようにする
joblib.dump(clf, 'cars.pkl')
実行するとcars.plkが生成される。可読性のあるものではないので中身は気にしなくて良い
$ file cars.pkl cars.pkl: 8086 relocatable (Microsoft)
デシリアライズ
シリアライズされた学習モデルは、load関数でデシリアライズすることができる。以降ではclfを用いれば従来通りpredictメソッドを使って予測を行うことができる
clf = joblib.load('cars.pkl');
ソースコード
自動車の情報と価格をランダムフォレストで学習し、シリアライズするスクリプト
import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn import preprocessing from sklearn.externals import joblib # CSVファイルを読み込む df = pd.read_csv('cars.csv') # 学習に不要な行、列を削除 del df['normalized-losses'] for col in ['num-of-doors', 'price', 'bore', 'stroke', 'horsepower', 'peak-rpm']: df = df[df[col] != '?'] # 説明変数列と目的変数列に分割 label = df['price'] data = df.drop('price', axis=1) # 文字列データを数値化 le = preprocessing.LabelEncoder() for col in ['make', 'fuel-type', 'aspiration', 'num-of-doors', 'body-style', 'drive-wheels', 'engine-location', 'engine-type', 'num-of-cylinders', 'fuel-system']: data[col] = le.fit_transform(data[col]) # 学習する clf = RandomForestClassifier() clf.fit(data, label) # 学習結果をシリアライズ joblib.dump(clf, 'cars.pkl')
シリアライズされた学習モデルをデシリアライズし、予測、評価するスクリプト
import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn import preprocessing from sklearn.externals import joblib # CSVファイルを読み込む df = pd.read_csv('cars.csv') # 学習に不要な行、列を削除 del df['normalized-losses'] for col in ['num-of-doors', 'price', 'bore', 'stroke', 'horsepower', 'peak-rpm']: df = df[df[col] != '?'] # 説明変数列と目的変数列に分割 label = df['price'] data = df.drop('price', axis=1) # 文字列データを数値化 le = preprocessing.LabelEncoder() for col in ['make', 'fuel-type', 'aspiration', 'num-of-doors', 'body-style', 'drive-wheels', 'engine-location', 'engine-type', 'num-of-cylinders', 'fuel-system']: data[col] = le.fit_transform(data[col]) # 学習モデルをデシリアライズ clf = joblib.load('cars.pkl'); # 評価する predict = clf.predict(data) rate_sum = 0 for i in range(len(label)): t = int(label.iloc[i]) p = int(predict[i]) rate_sum += int(min(t, p) / max(t, p) * 100) print(rate_sum / len(label))