Читать книгу Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow - Aurélien Géron - Страница 95
Implementierung der Kreuzvalidierung
ОглавлениеBisweilen benötigen Sie eine genauere Kontrolle über den Prozess der Kreuzvalidierung, als sie von Scikit-Learn angeboten wird. In diesen Fällen können Sie die Kreuzvalidierung selbst implementieren. Das folgende Codebeispiel tut in etwa das Gleiche wie die Scikit-Learn-Funktion cross_val_score() und liefert das gleiche Ergebnis:
from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone
skfolds = StratifiedKFold(n_splits=3, random_state=42)
for train_index, test_index in skfolds.split(X_train, y_train_5):
clone_clf = clone(sgd_clf)
X_train_folds = X_train[train_index]
y_train_folds = y_train_5[train_index]
X_test_fold = X_train[test_index]
y_test_fold = y_train_5[test_index]
clone_clf.fit(X_train_folds, y_train_folds)
y_pred = clone_clf.predict(X_test_fold)
n_correct = sum(y_pred == y_test_fold)
print(n_correct / len(y_pred)) # gibt 0.9502, 0.96565 und 0.96495 aus
Die Klasse StratifiedKFold bildet eine stratifizierte Stichprobe (wie in Kapitel 2 erklärt), um Folds mit einer repräsentativen Anzahl Punkte aus jeder Kategorie zu ermitteln. Bei jeder Iteration erstellt der Code einen Klon des Klassifikators, trainiert diesen auf den zum Trainieren abgestellten Folds und führt eine Vorhersage für den Fold zum Testen durch. Anschließend ermittelt er die Anzahl korrekter Vorhersagen und gibt deren Anteil aus.
Wir verwenden die Funktion cross_val_score(), um unser SGDClassifier-Modell mit k-facher Kreuzvalidierung und drei Folds auszuwerten. Bei der k-fachen Kreuzvalidierung wird der Trainingsdatensatz bekanntlich in k Folds aufgeteilt (drei in diesem Fall), anschließend werden auf jedem Fold Vorhersagen getroffen und ausgewertet, wobei das Modell mit den jeweils restlichen Folds trainiert wird (siehe Kapitel 2):
>>> from sklearn.model_selection import cross_val_score
>>> cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy")
array([0.96355, 0.93795, 0.95615])
Wow! Eine Genauigkeit über 93% (Anteil korrekter Vorhersagen) auf sämtlichen Folds der Kreuzvalidierung? Das sieht fantastisch aus, nicht wahr? Bevor Sie sich aber vom Ergebnis mitreißen lassen, betrachten wir zum Vergleich einen sehr primitiven Klassifikator, der einfach jedes Bild der Kategorie »nicht-5« zuordnet:
from sklearn.base import BaseEstimator
class Never5Classifier(BaseEstimator):
def fit(self, X, y=None):
pass
def predict(self, X):
return np.zeros((len(X), 1), dtype=bool)
Können Sie die Genauigkeit dieses Modells erraten? Finden wir es heraus:
>>> never_5_clf = Never5Classifier()
>>> cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring="accuracy")
array([0.91125, 0.90855, 0.90915])
Richtig, es hat eine Genauigkeit von über 90%! Dies liegt einfach daran, dass nur etwa 10% der Bilder 5en sind. Wenn Sie also jedes Mal darauf tippen, dass ein Bild keine 5 enthält, werden Sie in 90% der Fälle richtig liegen. Damit schlagen Sie sogar Nostradamus.
Dies zeigt, warum die Genauigkeit bei Klassifikatoren für gewöhnlich nicht das Qualitätsmaß der Wahl ist, besonders wenn Sie es mit unbalancierten Datensätzen zu tun haben (also solchen, bei denen einige Kategorien viel häufiger als andere auftreten).