webentwicklung-frage-antwort-db.com.de

Unterschied zwischen cross_val_score und cross_val_predict

Ich möchte ein mit Scikitlearn erstelltes Regressionsmodell unter Verwendung der Kreuzvalidierung auswerten und verwirrt werden, welche der beiden Funktionen cross_val_score und cross_val_predict ich verwenden sollte .

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))

Eine andere, um die cv-Vorhersagen mit dem Standard r2_score zu verwenden:

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)))

Ich würde davon ausgehen, dass beide Methoden gültig sind und ähnliche Ergebnisse liefern. Das ist aber nur bei kleinen k-Faltungen der Fall. Während r ^ 2 für 10-fache cv ungefähr gleich ist, wird es bei höheren k-Werten bei der ersten Version mit "cross_vall_score" immer niedriger. Die zweite Version ist von der Änderung der Falzanzahl meist nicht betroffen.

Ist dieses Verhalten zu erwarten und habe ich kein Verständnis für den Lebenslauf in SKLearn? 

7
Bobipuegi

cross_val_score gibt den Wert der Testfalte zurück, wobei cross_val_predict vorhergesagte y-Werte für die Testfalte zurückgibt.

Für cross_val_score() verwenden Sie den Durchschnittswert der Ausgabe, der von der Anzahl der Falzungen beeinflusst wird, da er einige Falze haben kann, die einen hohen Fehler aufweisen können (nicht richtig passen).

Während cross_val_predict() für jedes Element in der Eingabe die Vorhersage zurückgibt, die für dieses Element erhalten wurde, als es sich im Testset befand. [Beachten Sie, dass nur Kreuzvalidierungsstrategien verwendet werden können, die alle Elemente genau einmal einem Test-Set zuordnen.] Wenn also die Anzahl der Falten erhöht wird, werden nur die Trainingsdaten für das Testelement erhöht, und das Ergebnis kann daher nicht wesentlich beeinflusst werden.

Hoffe das hilft. Fühlen Sie sich frei, um Zweifel zu fragen.

Bearbeiten: Beantworten der Frage in Kommentar

Sehen Sie sich die folgende Antwort an, wie cross_val_predict funktioniert:

Ich denke, dass cross_val_predict übertrieben sein wird, da mit zunehmender Falte mehr Daten für den Zug und weniger für den Test zur Verfügung stehen. Daher ist das resultierende Label mehr von den Trainingsdaten abhängig. Wie oben bereits gesagt, wird die Vorhersage für eine Probe nur einmal durchgeführt, sodass sie möglicherweise mehr an der Datenaufteilung beteiligt ist. Deshalb empfehlen die meisten Orte oder Tutorials die Verwendung des cross_val_score zur Analyse.

10
Vivek Kumar

Ich denke, der Unterschied kann deutlich gemacht werden, wenn man ihre Ergebnisse betrachtet. Betrachten Sie diesen Ausschnitt:

# 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,)

Beachten Sie die Formen: Warum sind diese so? scores.shape hat Länge 5, da es sich um eine Bewertung handelt, die mit Kreuzvalidierung über 5-fach berechnet wird (siehe Argument cv=5). Daher wird für jede Faltung ein einzelner reeller Wert berechnet. Dieser Wert ist die Bewertung des Klassifizierers:

wie viele Antworten hatte der Prädiktor in einer bestimmten Falte richtig?

In diesem Fall werden die eingegebenen y-Labels zweimal verwendet: um aus Daten zu lernen und die Leistungen des Klassifikators zu bewerten.

Auf der anderen Seite hat y_pred.shape die Länge 7040, die Form des Datensatzes. Das ist die Länge des Eingabedatensatzes. Dies bedeutet, dass es sich bei jedem Wert nicht um eine Bewertung handelt, die anhand mehrerer Werte berechnet wird, sondern um einen einzigen Wert: die Vorhersage des Klassifizierers:

wie lautet die Vorhersage des Klassifizierers an einem bestimmten Beispiel, das sich in einem Testsatz einer bestimmten Falte befand, angesichts der Eingabedaten und ihrer Bezeichnungen?

Beachten Sie, dass Sie nicht wissen, welche Falte verwendet wurde: Jede Ausgabe wurde anhand der Testdaten einer bestimmten Falte berechnet, aber Sie können nicht sagen, welche (mindestens diese Ausgabe).

In diesem Fall werden die Labels nur einmal verwendet: um den Klassifikator zu trainieren. Es ist Ihre Aufgabe, diese Ausgaben mit den wahren Ausgaben zu vergleichen, um die Bewertung zu berechnen. Wenn Sie die Durchschnittswerte genau wie Sie berechnen, handelt es sich bei der Ausgabe nicht um eine Bewertung, sondern nur um die durchschnittliche Vorhersage.

Diese Frage hat mich also auch gestört, und obwohl die anderen gute Punkte gemacht haben, haben sie nicht alle Aspekte der Frage von OP beantwortet.

Die wahre Antwort lautet: Die Divergenz der Bewertungen für die Erhöhung von k ist auf die gewählte Metrik R2 (Bestimmungskoeffizient) zurückzuführen. Für z.B. MSE, MSLE oder MAE es gibt keinen Unterschied bei der Verwendung von cross_val_score oder cross_val_predict.

Siehe Definition von R2 :

R ^ 2 = 1 - (MSE (Grundwahrheit, Vorhersage)/MSE (Grundwahrheit, Mittelwert (Grundwahrheit) ))

Der fett gedruckte Teil erklärt, warum sich die Punktzahl mit zunehmendem k zu unterscheiden beginnt: Je mehr Splits wir haben, desto weniger Stichproben befinden sich in der Testfalte und desto höher ist die Varianz im Mittel der Testfalte. Umgekehrt weicht der Mittelwert der Testfalte für kleine k nicht wesentlich vom Mittelwert der vollständigen Grundwahrheit ab, da die Stichprobengröße immer noch groß genug ist, um eine geringe Varianz aufzuweisen.

Beweis:

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()

Die Ausgabe wird sein:

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

Natürlich gibt es hier noch einen anderen Effekt, der von anderen erwähnt wurde. Mit zunehmendem k werden mehr Modelle an mehr Stichproben trainiert und an weniger Stichproben validiert, was sich auf die endgültigen Ergebnisse auswirkt. Dies wird jedoch nicht durch die Wahl zwischen cross_val_score und cross_val_predict.

0
Kirgsn