クロス検証を使用して混乱しているscikitlearnで構築された回帰モデルを評価したい。2つの関数cross_val_score
とcross_val_predict
のどちらを使用すべきか1つのオプションは次のとおりです。
cvs = DecisionTreeRegressor(max_depth = depth)
scores = cross_val_score(cvs, predictors, target, cv=cvfolds, scoring='r2')
print("R2-Score: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
もう1つは、標準のr2_score
でcv-predictionsを使用します。
cvp = DecisionTreeRegressor(max_depth = depth)
predictions = cross_val_predict(cvp, predictors, target, cv=cvfolds)
print ("CV R^2-Score: {}".format(r2_score(df[target], predictions_cv)))
どちらの方法も有効であり、同様の結果が得られると思います。しかし、それは小さなkフォールドの場合のみです。 r ^ 2は10-fold-cvでほぼ同じですが、「cross_vall_score」を使用する最初のバージョンの場合、k値が高くなるとますます低くなります。 2番目のバージョンは、フォールドの数を変更してもほとんど影響を受けません。
この動作は予想されるものですか、SKLearnのCVに関する理解が不足していますか?
_cross_val_score
_はテストフォールドのスコアを返し、_cross_val_predict
_はテストフォールドの予測y値を返します。
cross_val_score()
には、出力の平均を使用します。これは、フォールドの数に影響されます。フォールドにはエラーが大きくなる可能性があるためです(正しく適合しない)。
一方、cross_val_predict()
は、入力の各要素について、その要素がテストセットにあったときに取得された予測を返します。 [すべての要素をテストセットに1回だけ割り当てるクロス検証戦略のみを使用できることに注意してください]。したがって、折り畳みの数を増やしても、テスト要素のトレーニングデータが増えるだけであるため、結果はそれほど影響を受けない可能性があります。
お役に立てれば。ご不明な点はお気軽にお問い合わせください。
編集:コメントで質問に答える
_cross_val_predict
_の仕組みについては、次の回答をご覧ください。
_cross_val_predict
_はオーバーフォールになると思います。なぜなら、折り畳みが増えると、トレーニング用のデータが増え、テスト用のデータが少なくなるからです。したがって、結果のラベルはトレーニングデータにより依存します。また、上記で既に述べたように、1つのサンプルの予測は1回だけ行われるため、データの分割がより影響を受けやすい可能性があります。そのため、ほとんどの場所やチュートリアルでは、分析に_cross_val_score
_の使用を推奨しています。
その違いは、彼らのアウトプットを調べることで明らかになると思います。このスニペットを検討してください。
# Last column is the label
print(X.shape) # (7040, 133)
clf = MLPClassifier()
scores = cross_val_score(clf, X[:,:-1], X[:,-1], cv=5)
print(scores.shape) # (5,)
y_pred = cross_val_predict(clf, X[:,:-1], X[:,-1], cv=5)
print(y_pred.shape) # (7040,)
形状に注意してください。なぜそうなのでしょうか? scores.shape
は、5倍以上の交差検定で計算されたスコアであるため、長さが5です(引数cv=5
)。したがって、単一の実数値が各フォールドに対して計算されます。その値は、分類子のスコアです。
真のラベルと予測されたラベルが与えられた場合、特定のフォールドで予測子が正しかった答えの数は?
この場合、入力で指定されたyラベルは2回使用されます。データから学習し、分類器のパフォーマンスを評価するためです。
一方、 y_pred.shape
の長さは7040です。これはデータセットの形状です。これは、入力データセットの長さです。これは、各値が複数の値で計算されたスコアではなく、単一の値である分類器の予測であることを意味します。
入力データとそのラベルが与えられた場合、特定のフォールドのテストセットにあった特定の例の分類器の予測はどうなりますか?
どのフォールドが使用されたのかわからないことに注意してください。各出力は特定のフォールドのテストデータで計算されましたが、どの出力かはわかりません(少なくともこの出力から)。
この場合、ラベルは一度だけ使用されます:分類器を訓練するために。これらの出力を真の出力と比較してスコアを計算するのはあなたの仕事です。あなたがやったようにそれらを平均するだけなら、出力はスコアではなく、単なる平均予測です。
したがって、この質問も私を悩ませ、他の人は良い点を示しましたが、OPの質問のすべての側面に答えませんでした。
本当の答えは次のとおりです。kの増加に対するスコアの相違は、選択されたメトリックR2(決定係数)によるものです。例えばMSE、MSLE、またはMAE cross_val_score
またはcross_val_predict
を使用しても違いはありません。
R2の定義 を参照してください:
R ^ 2 = 1-(MSE(グラウンドトゥルース、予測)/ MSE(グラウンドトゥルース、mean(グラウンドトゥルース) ))
太字の部分は、kを増やすとスコアが異なるようになる理由を説明しています。分割数が多いほど、テストフォールドのサンプル数が少なくなり、テストフォールドの平均の分散が大きくなります。逆に、kが小さい場合、サンプルサイズは分散が小さいほど大きいため、テストフォールドの平均は完全なグラウンドトゥルースの平均と大きく異なりません。
証明:
import numpy as np
from sklearn.metrics import mean_absolute_error as mae
from sklearn.metrics import mean_squared_log_error as msle, r2_score
predictions = np.random.Rand(1000)*100
groundtruth = np.random.Rand(1000)*20
def scores_for_increasing_k(score_func):
skewed_score = score_func(groundtruth, predictions)
print(f'skewed score (from cross_val_predict): {skewed_score}')
for k in (2,4,5,10,20,50,100,200,250):
fold_preds = np.split(predictions, k)
fold_gtruth = np.split(groundtruth, k)
correct_score = np.mean([score_func(g, p) for g,p in Zip(fold_gtruth, fold_preds)])
print(f'correct CV for k={k}: {correct_score}')
for name, score in [('MAE', mae), ('MSLE', msle), ('R2', r2_score)]:
print(name)
scores_for_increasing_k(score)
print()
出力は次のようになります。
MAE
skewed score (from cross_val_predict): 42.25333901481263
correct CV for k=2: 42.25333901481264
correct CV for k=4: 42.25333901481264
correct CV for k=5: 42.25333901481264
correct CV for k=10: 42.25333901481264
correct CV for k=20: 42.25333901481264
correct CV for k=50: 42.25333901481264
correct CV for k=100: 42.25333901481264
correct CV for k=200: 42.25333901481264
correct CV for k=250: 42.25333901481264
MSLE
skewed score (from cross_val_predict): 3.5252449697327175
correct CV for k=2: 3.525244969732718
correct CV for k=4: 3.525244969732718
correct CV for k=5: 3.525244969732718
correct CV for k=10: 3.525244969732718
correct CV for k=20: 3.525244969732718
correct CV for k=50: 3.5252449697327175
correct CV for k=100: 3.5252449697327175
correct CV for k=200: 3.5252449697327175
correct CV for k=250: 3.5252449697327175
R2
skewed score (from cross_val_predict): -74.5910282783694
correct CV for k=2: -74.63582817089443
correct CV for k=4: -74.73848598638291
correct CV for k=5: -75.06145142821893
correct CV for k=10: -75.38967601572112
correct CV for k=20: -77.20560102267272
correct CV for k=50: -81.28604960074824
correct CV for k=100: -95.1061197684949
correct CV for k=200: -144.90258384605787
correct CV for k=250: -210.13375041871123
もちろん、ここには示されていない別の効果があります。 kが増加すると、より多くのサンプルでトレーニングされ、より少ないサンプルで検証されるモデルが多くなり、最終スコアに影響しますが、これはcross_val_score
とcross_val_predict
の選択によって引き起こされません。