###前置き###
scikit-learn
にはハイパーパラメータ探索用のGridSearchCV
があって、Pythonのディクショナリでパラメータの探索リストを渡すと全部試してスコアを返してくれる便利なヤツだ。
今回はDeepLearningではないけど、使い方が分からないという声を聞くので、このGridSearchCV
の使い方をまとめておこうと思います。
ちなみにKeras
だとscikit-learn
のAPIもあるので、Keras
で作ったモデルをこのGridSearchCV
でパラメータ探索できる。
(やったことないけど・・・)
####GridSearchCV####
###ソースコード全文###
今回は最初にコード全文を載せておく。説明は後程。
データはirisデータセットでサポートベクターマシンを使って分類する。
### ライブラリのインポート
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import confusion_matrix
### 探索するパラメータ空間
def param():
ret = {
'C':[1, 10, 100],
'kernel':['rbf', 'linear', 'poly'],
'degree':np.arange(1, 6, 1),
'gamma':np.linspace(0.01, 1.0, 50)
}
return ret
if __name__ == '__main__':
# データの準備
x = load_iris().data
y = load_iris().target
# 25%分のデータを除けておく
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# GridSearchCVのインスタンスを作成&学習&スコア記録
gscv = GridSearchCV(SVC(), param(), cv=4, verbose=2)
gscv.fit(x_train, y_train)
# スコアの一覧を取得
gs_result = pd.DataFrame.from_dict(gscv.cv_results_)
gs_result.to_csv('gs_result.csv')
# 最高性能のモデルを取得し、テストデータを分類
best = gscv.best_estimator_
pred = best.predict(x_test)
# 混同行列を出力
print(confusion_matrix(y_test, pred))
####解説####
#####ライブラリインポート#####
### ライブラリのインポート
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import confusion_matrix
探索パラメータが数値の時にndarrayでやると楽なのでnumpy、スコア一覧をDataFrameにしてしまえばCSVなどで吐き出すのが楽なのでpandas。
irisデータセットと分類用のサポートベクターマシン(SVC
)、データをランダムに分割するtrain_test_split
、最後の評価用の混同行列を出力するconfusion_matrix
をインポートします。
#####探索するパラメータ空間#####
### 探索するパラメータ空間
def param():
ret = {
'C':[1, 10, 100],
'kernel':['rbf', 'linear', 'poly'],
'degree':np.arange(1, 6, 1),
'gamma':np.linspace(0.01, 1.0, 50)
}
return ret
メインのソースが綺麗になるので、パラメータ空間は関数で作る。
ディクショナリで渡す必要がある。
キーがサポートベクターマシンのパラメータ名で値が探索する値のリスト
(というか多分iterator
なら何でもOKなんだと思う)
値の最大・最小を指定しておけばいいわけではないので、ここではnumpyが活躍する。
色々あるけど、arange
とlinspace
を覚えておけば大体OKと思う。
どちらも始点と終点を入れ替えると昇順・降順が入れ替わる。
######Tips######
# 1以上6未満で1刻みのarrayを作る
a = np.arange(1, 6, 1)
>> [1 2 3 4 5]
# 0.0以上1.0以下を10分割したarrayを作る
a = np.linspace(0.0, 1.0, 10)
>> [0. 0.11111111 0.22222222 0.33333333 0.44444444 0.55555556 0.66666667 0.77777778 0.88888889 1. ]
#####データの準備#####
# データの準備
x = load_iris().data
y = load_iris().target
# 25%分のデータを除けておく
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
説明変数となるx、目的変数となるyを75%と25%にランダムに分ける。
ここでの25%は最後の評価用で、75%を使ってGridSearchCV
によるパラメータ探索を行う。
#####GridSearchCVのインスタンスを作成&学習&スコア記録#####
# GridSearchCVのインスタンスを作成&学習&スコア記録
gscv = GridSearchCV(SVC(), param(), cv=4, verbose=2)
gscv.fit(x_train, y_train)
GridSearchCV
の第1引数には推定器のインスタンスを渡す。
探索せずに固定したいパラメータがあれば、ここで指定しておけば常にそのパラメータが使われる。
第2引数にはパラメータの探索空間(ディクショナリ)を渡す。ここでは先ほどの関数を渡す。
ここでのパラメータcv
は交差検証の手法を指定する。
この例のようにIntで指定するとK-Fold法のn分割のnを指定することになる。 ※省略すると3になる。
Int型以外ではscikit-learn
のデータ分割(ShuffleSplit
等)を指定することもできる。
verbose
は進捗を見たい場合は1や2を指定しておくと標準出力で進捗が見れるけど、プログレスバーみたいな上等な物は出ない。
fit
にデータを放り込むと探索が始まる。設定した探索空間次第だが、長くなる。が、自動である。
#####スコアの一覧を取得#####
# スコアの一覧を取得
gs_result = pd.DataFrame.from_dict(gscv.cv_results_)
gs_result.to_csv('gs_result.csv')
ディクショナリで返ってくるので、そのままpandasのDataFrameに入れてCSV出力する。
・・・というのも大抵の場合、大きすぎてEXCELなどじゃないと見れたものじゃないからだ。
キーは全部英語だけど、意味が分からない物はほとんどないと思うが、一番分かりやすいのはrank_test_score
。
この列をキーに昇順に並べ替えた時、一番上に来るものが未学習データのスコアが一番良かったパラメータの適用例。
#####最高性能のモデルを取得し、テストデータを分類#####
# 最高性能のモデルを取得し、テストデータを分類
best = gscv.best_estimator_
pred = best.predict(x_test)
# 混同行列を出力
print(confusion_matrix(y_test, pred))
GridSearchCV
のインスタンスからbest_estimator_
にアクセスすると最高性能だったパラメータを適用した学習済みのインスタンスを取り出せる。
このまま、最初に除けておいた25%のデータを分類させ、混同行列を出力すると・・・・
[[14 0 0]
[ 0 12 1]
[ 0 0 11]]
1つだけ間違ってしまうようだが、上々の性能だ。
###最後に###
GridSearchCV
の必要最小限の使い方を解説しました。
カスタマイズ性が高いので、これ以上は色々試されると良いと思います。
例えば、評価方法はscikit-learn
の場合、回帰問題だと決定係数$R^2$、分類問題だと正解率が適用されて、いずれも高い方が良いように扱われますが、回帰問題で正負反転した平均二乗誤差などを使うこともできます。