Cross Validationクロス検証
8061 ワード
トレーニングセットvs.テストセット
パターン認識(pattern recognition)と機械学習(machine learning)に関する研究では、データセット(dataset)を訓練セット(training set)とテストセット(testing set)の2つのサブセットに分けることがよくあり、前者はモデル(model)を構築するために用いられ、後者は未知のサンプルを予測する際の精度を評価するために用いられ、正規の説では汎化能力(generalization ability)である.完全なデータセットをトレーニングセットとテストセットに分けるには、次のポイントを遵守する必要があります.
最後の点は特に重要であり、均一サンプリングの目的は、トレーニングセット/テストセットと完全なセットとの間のばらつき(bias)を低減することであるが、容易ではない.一般的なやり方はランダムサンプリングであり、サンプル数が十分であれば均一サンプリングの効果が得られるが、ランダムもこのやり方の盲点であり、データ上で手足を作ることができる場所でもある.例えば、認識率が理想的でない場合、テストセットの認識率が満足するまで、トレーニングセット/テストセットのセットを再サンプリングするが、厳密にはカンニングである.クロス検証(Cross Validation)
クロス検証(Cross Validation)は分類器の性能を検証するための統計分析方法であり、基本思想はある意味で元のデータ(dataset)をグループ化し、一部を訓練セット(training set)、もう一部を検証セット(validation set)とし、まず訓練セットで分類器を訓練し、検証セットを利用して訓練で得られたモデル(model)をテストし、これを評価分類器の性能指標とする.一般的なクロス検証方法は次のとおりです.
Hold-Out Method
元のデータをランダムに2つのグループに分け、1つのグループを訓練セットとし、1つのグループを検証セットとし、訓練セットを利用して分類器を訓練し、その後、検証セットを利用してモデルを検証し、最後の分類精度をこの分類器の性能指標として記録する.この方法の利点の処理は簡単で,ランダムに元のデータを2つのグループに分けるだけでよいが,厳密にはHold-Out MethodはCVとは言えない.この方法は交差の思想に達していないため,ランダムに元のデータをグループ化するので,最終検証セットの分類精度の高低は元のデータのグループ化と大きく関係しているため,この方法で得られた結果は説得性がない.
Double Cross Validation(2-fold Cross Validation、2-CVと記す)
データセットを2つの等しいサイズのサブセットに分けて,2ラウンドの分類器訓練を行う.第1ラウンドでは、1つのサブセットがtraining setとなり、もう1つはtesting setとなる.第2ラウンドではtraining setとtesting setを交換した後、再び分類器を訓練したが、その中で私たちが関心を持っているのは2回のtesting setsの認識率だ.しかし、実務的には2-CVはあまり使われていない.主な原因はtraining setサンプル数が少なすぎて、通常母体サンプルの分布を代表するのに十分ではなく、testing段階の認識率に明らかな落差が現れやすいためである.また,2‐CVでは分子集合の変異度が大きく,「実験過程は複製されなければならない」という要求に達しないことが多い.
K-fold Cross Validation(K-折り交差検証、K-CVと記す)
元のデータをKグループ(一般的には均等)に分け、各サブセットデータをそれぞれ1回検証セットとし、残りのK-1グループのサブセットデータをトレーニングセットとすることで、K個のモデルが得られ、このK-CV下の分類器の性能指標として、このK個のモデルの最終的な検証セットの分類精度の平均数が用いられる.Kは一般に2以上であり,実際の操作では3から取り始め,元のデータセットのデータ量が小さい場合にのみ2を取ることを試みる.K-CVは過学習や欠学習状態の発生を効果的に回避でき,最終的に得られた結果も比較的説得性がある.
K-fold cross-validation(k-CV)はdouble cross-validationの延長であり、datasetをk個の大きさの等しいsubsetsに切断し、各subsetをそれぞれ1回のtest setとし、残りのサンプルをtraining setとするため、1回のk-CVの実験ではk個のmodelsを構築し、k回のtest setsの平均認識率を計算する必要がある.実作では、各ラウンドのtraining setサンプル数を十分に大きくするには、k=10が十分であるのが一般的である.
Leave-One-Out Cross Validation(LOO-CVと記す)
元のデータにN個のサンプルがあるとすると、LOO-CVはN-CV、すなわち各サンプルが単独で検証セットとなり、残りのN-1個のサンプルがトレーニングセットとなるので、LOO-CVはN個のモデルを得、このN個のモデルの最終的な検証セットの分類精度の平均数をこの下のLOO-CV分類器の性能指標とする.LOO−CVには、前のK−CVと比較して2つの明らかな利点がある.
Cross-Validationでよく犯すエラー
実験室の多くの研究はevolutionary algorithms(EA)とclassifiersに有用であるため、使用されるfitness functionではclassifierの認識率に一般的に有用であるが、cross-validationを誤って使用する例は少なくない.前述したように、モデルの構築に使用できるのはtraining dataのみであるため、fitness functionではtraining dataの認識率のみである.一方,EAは訓練過程でモデルの最適パラメータを調整する方法であるため,EAの進化が終了した後にモデルパラメータが固定されている場合にのみtest dataを使用することができる.EAとcross-validationはどのように組み合わせますか?Cross-validationの本質は、あるclassification methodがdatasetのgeneralization errorのセットに対してclassifierを設計する方法ではないので、cross-validationはEAのfitness functionでは使用できません.fitness functionに関するサンプルはtraining setに属しているので、どのサンプルがtest setなのかを聞いてみましょう.あるfitness functionでcross−validationのtrainingまたはtest判別率が使用されている場合、このような実験方法はcross−validationとは言えない.
EAとk-CVの正しい組み合わせは、datasetをk等分のsubsetsに分割した後、毎回1部のsubsetをtest setとし、残りのk-1部をtraining setとし、このグループのtraining setをEAのfitness function計算に適用する(このtraining setがどのようにさらに利用されるかについては制限はない).したがって,正しいk−CVは,共にk回のEA進化を行い,k個のclassifiersを確立する.一方、k−CVのtest判別率は、k群test setsがEA訓練で得られたk個のclassifiers判別率に対応する平均値である.
例 import numpy as np
from sklearn import cross_validation
from sklearn import datasets
from sklearn import svm
iris = datasets.load_iris()
iris.data.shape, iris.target.shape
((150, 4), (150,))
We can now quickly sample a training set while holding out 40% of the data for testing (evaluating) our classifier: X_train, X_test, y_train, y_test = cross_validation.train_test_split(
... iris.data, iris.target, test_size=0.4, random_state=0)
X_train.shape, y_train.shape
((90, 4), (90,)) X_test.shape, y_test.shape
((60, 4), (60,)) clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
clf.score(X_test, y_test)
0.96666666666666667
Computing cross-validated metrics
The simplest way to use cross-validation is to call the cross_val_score helper function on the estimator and the dataset.The following example demonstrates how to estimate the accuracy of a linear kernel support vector machine on the iris dataset by splitting the data, fitting a model and computing the score 5 consecutive times (with different splits each time): clf = svm.SVC(kernel='linear', C=1)
# iris linear kernel SVM 5
scores = cross_validation.cross_val_score(clf, iris.data, iris.target, cv=5)
scores
array([ 0.96666667, 1. , 0.96666667, 0.96666667, 1. ])The mean score and the 95% confidence interval of the score estimate are hence given by: print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.98 (+/- 0.03)By default, the score computed at each CV iteration is the score method of the estimator. It is possible to change this by using the scoring parameter:See The scoring parameter: defining model evaluation rules for details. In the case of the Iris dataset, the samples are balanced across target classes hence the accuracy and the F1-score are almost equal.When the cv argument is an integer, cross_val_score uses the KFold or StratifiedKFold strategies by default, the latter being used if the estimator derives from ClassifierMixin. # f1 score
from sklearn import metrics
scores = cross_validation.cross_val_score(clf, iris.data, iris.target,cv=5, scoring='f1_weighted')
scores
array([ 0.96658312, 1. , 0.96658312, 0.96658312, 1. ])
CrossvalidationでGird Searchを作る >>> from sklearn import svm, datasets
>>> from sklearn.model_selection import GridSearchCV
>>> iris = datasets.load_iris()
>>> parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
>>> svr = svm.SVC()
>>> clf = GridSearchCV(svr, parameters,cv=5,scoring='f1_weighted')
>>> clf.fit(iris.data, iris.target)
GridSearchCV(cv=5, error_score='raise',
estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False),
fit_params={}, iid=True, n_jobs=1,
param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')},
pre_dispatch='2*n_jobs', refit=True, return_train_score=True,
scoring='f1_weighted', verbose=0)
# View the accuracy score
print('Best score for data:', clf.best_score_)
# View the best parameters for the model found using grid search
print('Best C:',clf.best_estimator_.C)
print('Best Kernel:',clf.best_estimator_.kernel)
print('Best Gamma:',clf.best_estimator_.gamma)
Best score for data: 0.979949874687
Best C: 1
Best Kernel: linear
Best Gamma: auto
import numpy as np
from sklearn import cross_validation
from sklearn import datasets
from sklearn import svm
iris = datasets.load_iris()
iris.data.shape, iris.target.shape
((150, 4), (150,))
We can now quickly sample a training set while holding out 40% of the data for testing (evaluating) our classifier:
X_train, X_test, y_train, y_test = cross_validation.train_test_split(
... iris.data, iris.target, test_size=0.4, random_state=0)
X_train.shape, y_train.shape
((90, 4), (90,))
X_test.shape, y_test.shape
((60, 4), (60,))
clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
clf.score(X_test, y_test)
0.96666666666666667
Computing cross-validated metrics
The simplest way to use cross-validation is to call the cross_val_score helper function on the estimator and the dataset.The following example demonstrates how to estimate the accuracy of a linear kernel support vector machine on the iris dataset by splitting the data, fitting a model and computing the score 5 consecutive times (with different splits each time):
clf = svm.SVC(kernel='linear', C=1)
# iris linear kernel SVM 5
scores = cross_validation.cross_val_score(clf, iris.data, iris.target, cv=5)
scores
array([ 0.96666667, 1. , 0.96666667, 0.96666667, 1. ])The mean score and the 95% confidence interval of the score estimate are hence given by:
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.98 (+/- 0.03)By default, the score computed at each CV iteration is the score method of the estimator. It is possible to change this by using the scoring parameter:See The scoring parameter: defining model evaluation rules for details. In the case of the Iris dataset, the samples are balanced across target classes hence the accuracy and the F1-score are almost equal.When the cv argument is an integer, cross_val_score uses the KFold or StratifiedKFold strategies by default, the latter being used if the estimator derives from ClassifierMixin.
# f1 score
from sklearn import metrics
scores = cross_validation.cross_val_score(clf, iris.data, iris.target,cv=5, scoring='f1_weighted')
scores
array([ 0.96658312, 1. , 0.96658312, 0.96658312, 1. ])
CrossvalidationでGird Searchを作る >>> from sklearn import svm, datasets
>>> from sklearn.model_selection import GridSearchCV
>>> iris = datasets.load_iris()
>>> parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
>>> svr = svm.SVC()
>>> clf = GridSearchCV(svr, parameters,cv=5,scoring='f1_weighted')
>>> clf.fit(iris.data, iris.target)
GridSearchCV(cv=5, error_score='raise',
estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False),
fit_params={}, iid=True, n_jobs=1,
param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')},
pre_dispatch='2*n_jobs', refit=True, return_train_score=True,
scoring='f1_weighted', verbose=0)
# View the accuracy score
print('Best score for data:', clf.best_score_)
# View the best parameters for the model found using grid search
print('Best C:',clf.best_estimator_.C)
print('Best Kernel:',clf.best_estimator_.kernel)
print('Best Gamma:',clf.best_estimator_.gamma)
Best score for data: 0.979949874687
Best C: 1
Best Kernel: linear
Best Gamma: auto
>>> from sklearn import svm, datasets
>>> from sklearn.model_selection import GridSearchCV
>>> iris = datasets.load_iris()
>>> parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
>>> svr = svm.SVC()
>>> clf = GridSearchCV(svr, parameters,cv=5,scoring='f1_weighted')
>>> clf.fit(iris.data, iris.target)
GridSearchCV(cv=5, error_score='raise',
estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False),
fit_params={}, iid=True, n_jobs=1,
param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')},
pre_dispatch='2*n_jobs', refit=True, return_train_score=True,
scoring='f1_weighted', verbose=0)
# View the accuracy score
print('Best score for data:', clf.best_score_)
# View the best parameters for the model found using grid search
print('Best C:',clf.best_estimator_.C)
print('Best Kernel:',clf.best_estimator_.kernel)
print('Best Gamma:',clf.best_estimator_.gamma)
Best score for data: 0.979949874687
Best C: 1
Best Kernel: linear
Best Gamma: auto