つまりなにしたの?
データ分析をやったら、Cross Validation(交差検定)などをやって分析手法が妥当か調べることが多い。
そこでscikit-learnのcross_validateを使ってCross Validationをやってみる
やりたいこと
- Cross Validationとはなにか
- データセットを用意する
- 分割の仕方
- cross_validateを使ったCross Validation
環境
% python Python 3.6.4 (default, Mar 2 2018, 00:45:54) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import numpy >>> import pandas >>> import sklearn >>> numpy.__version__ '1.15.3' >>> pandas.__version__ '0.23.4' >>> sklearn.__version__ '0.20.0'
Cross Validationとはなにか
ここでは一般的なCross Validationの一つであるk-Fold Cross Validationについて紹介する。
Cross Validationの目的は、主に解析の目標が予測であり、予測モデルが実際にどの程度正確に実行されるかを推定することにある。
これは、学習データへの過学習(オーバーフィッティング)を避けることである。
その方法はいくつかあるが、k-Fold Cross Validationでは使える学習データをk個に分割して、
k-1つのデータで学習、別の1つのデータで検証を行うことで実現する。
こんなイメージ。
事前にシャッフルしたり、各クラスごとに比率をあわせたりするテクニックが併せて使われる
データセットを用意する
よく使うWineのデータを使うことにしてみた。
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn import datasets wine_data = datasets.load_wine() wine_df = pd.DataFrame(wine_data.data, columns=wine_data.feature_names) wine_df.head() wine_df_tgt = pd.DataFrame(wine_data.target, columns=['target']) wine_df_tgt.head()
分割の仕方
K-foldでの分割とShuffleSplitでの分割を試してみた。
from sklearn.model_selection import KFold # 4つのデータセットをつくる。 kf = KFold(n_splits=4) for learn,test in kf.split([i for i in range(16)]): print(learn, test) [ 4 5 6 7 8 9 10 11 12 13 14 15] [0 1 2 3] [ 0 1 2 3 8 9 10 11 12 13 14 15] [4 5 6 7] [ 0 1 2 3 4 5 6 7 12 13 14 15] [ 8 9 10 11] [ 0 1 2 3 4 5 6 7 8 9 10 11] [12 13 14 15]
from sklearn.model_selection import ShuffleSplit # 4つのデータセットをテストサイズ20%でつくる。乱数を固定するためにrandom_state=0とした ss = ShuffleSplit(n_splits=4, test_size=0.2, random_state=0) for learn,test in ss.split([i for i in range(16)]): print(learn, test) [13 4 2 14 10 7 15 11 3 0 5 12] [1 6 8 9] [ 0 3 4 10 11 5 15 8 13 7 6 1] [ 2 14 12 9] [10 14 6 11 9 12 1 8 3 2 0 15] [ 5 13 7 4] [ 6 13 9 15 14 12 2 3 7 4 10 0] [11 8 1 5]
Wineのデータのようにラベルが綺麗に整列していると普通に分割した時に、
0と1のクラスで学習して2のクラスを予測するみたいな話になるのでシャッフルとかが必要になる。
cross_validateを使ったCross Validation
実際にcross_validateを使ってPrecisionとRecallを出してみることにする。
from sklearn.model_selection import cross_validate from sklearn.metrics import recall_score scoring = ['precision_macro', 'recall_macro'] clf = svm.SVC(kernel='linear', C=1, random_state=0) # 分割の仕方 cv = ShuffleSplit(n_splits=4, test_size=0.2, random_state=0) # Cross Validation scores = cross_validate(clf, wine_df, np.array(wine_df_tgt['target']), scoring=scoring, cv=cv, return_train_score=False) # 表示 print(sorted(scores.keys())) print(scores['test_recall_macro']) print(scores['test_precision_macro']) #結果 ['fit_time', 'score_time', 'test_precision_macro', 'test_recall_macro'] [1. 0.91666667 0.8962963 0.93333333] [1. 0.96666667 0.8962963 0.91666667]
Fitにかかる時間やスコアを出す時間とともにテストのPrecision、Recallが出せている。