web-dev-qa-db-de.com

Kreuzvalidierung in Keras

Ich implementiere ein Multilayer-Perzeptron in Keras und benutze scikit-learn, um die Kreuzvalidierung durchzuführen. Dafür hat mich der Code in der Ausgabe Cross Validation in Keras inspiriert.

from sklearn.cross_validation import StratifiedKFold

def load_data():
    # load your data using this function

def create model():
    # create your model using this function

def train_and_evaluate__model(model, data[train], labels[train], data[test], labels[test)):
    # fit and evaluate here.

if __== "__main__":
    X, Y = load_model()
    kFold = StratifiedKFold(n_splits=10)
    for train, test in kFold.split(X, Y):
        model = None
        model = create_model()
        train_evaluate(model, X[train], Y[train], X[test], Y[test])

In meinen Studien zu neuronalen Netzwerken habe ich gelernt, dass die Wissensrepräsentation des neuronalen Netzwerks in den synaptischen Gewichtungen und während des Netzwerkverfolgungsprozesses den Gewichtungen entspricht, die aktualisiert werden, um dadurch die Netzwerkfehlerrate zu reduzieren und ihre Leistung zu verbessern. (In meinem Fall verwende ich Supervised Learning)

Um die Leistung des neuronalen Netzwerks besser zu trainieren und zu bewerten, wird häufig eine Kreuzvalidierung verwendet, bei der Partitionen des Datensatzes für das Training und die Bewertung des Modells zurückgegeben werden.

Mein Zweifel ist ...

In diesem Codeausschnitt:

for train, test in kFold.split(X, Y):
    model = None
    model = create_model()
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

Wir definieren, trainieren und bewerten ein neues neuronales Netz für jede der erzeugten Partitionen?

Wenn es mein Ziel ist, das Netzwerk für die gesamte Datenmenge zu optimieren, warum ist es dann nicht korrekt, ein einzelnes neuronales Netzwerk zu definieren und es mit den generierten Partitionen zu trainieren?

Warum ist dieses Stück Code so?

for train, test in kFold.split(X, Y):
    model = None
    model = create_model()
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

und nicht so?

model = None
model = create_model()
for train, test in kFold.split(X, Y):
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

Ist mein Verständnis, wie der Code funktioniert, falsch? Oder meine Theorie?

Vielen Dank!

7
Alisson Hayasi

Wenn es mein Ziel ist, das Netzwerk für den gesamten Datensatz zu optimieren

Es ist nicht klar, was Sie unter "Feinabstimmung" verstehen oder was genau Ihr Zweck für die Durchführung der Kreuzvalidierung (Lebenslauf) ist. CV dient im Allgemeinen einem der folgenden Zwecke:

  • Modellauswahl (Wählen Sie die Werte für die Hyperparameter)
  • Modellbewertung

Da Sie in Ihrem Code kein Suchraster für die Auswahl von Hyperparametern definieren, scheint es, als würden Sie CV verwenden, um die erwartete Leistung Ihres Modells (Fehler, Genauigkeit usw.) zu erhalten.

Wie auch immer, aus welchem ​​Grund auch immer Sie Ihren Lebenslauf verwenden, ist der erste Ausschnitt der richtige. dein zweiter Ausschnitt

model = None
model = create_model()
for train, test in kFold.split(X, Y):
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

trainiert Ihr Modell sequentiell über die verschiedenen Partitionen (dh trainieren Sie auf Partition # 1, fahren Sie dann mit Partition # 2 fort usw.), was im Wesentlichen nur das Training Ihres gesamten Datensatzes ist, und es ist keine Kreuzvalidierung ...

Ein letzter Schritt danach der Lebenslauf, der oft nur impliziert ist (und häufig von Anfängern übersehen wird) ist, dass Sie mit den von Ihrem Lebenslauf-Verfahren gewählten Hyperparametern und/oder der Modellleistung zufrieden sind Zurück und trainieren Sie Ihr Modell erneut, diesmal mit den gesamten verfügbaren Daten.

4
desertnaut

Ich denke, viele Ihrer Fragen werden beantwortet, wenn Sie sich mit verschachtelter Kreuzvalidierung befassen. Dies ist ein guter Weg, um die Hyperparameter Ihres Modells zu "verfeinern". Hier gibt es einen Thread:

https://stats.stackexchange.com/questions/65128/nested-cross-validation-for-model-selection

Das größte Problem, dessen Sie sich bewusst sein sollten, ist das "Spähen" oder die zirkuläre Logik. Im Wesentlichen - Sie möchten sicherstellen, dass keine Daten, die zur Beurteilung der Modellgenauigkeit verwendet werden, während des Trainings angezeigt werden.

Ein Beispiel, bei dem dies problematisch sein kann, ist die Ausführung von PCA oder ICA für die Feature-Extraktion. Wenn Sie so etwas tun, müssen Sie sicherstellen, dass PCA auf Ihrem Trainingssatz ausgeführt wird, und dann die Transformationsmatrix vom Trainingssatz auf den Testsatz anwenden.

2
PK Douglas

Beim Testen der Leistung Ihres Modells sollten Sie die folgenden Schritte ausführen:

  1. Trainieren Sie ein Modell auf einem Trainingsset. 
  2. Bewerten Sie Ihr Modell anhand von Daten, die während des Schulungsprozesses nicht verwendet werden, um eine neue Datenankunft zu simulieren.

Grundsätzlich gilt: Die Daten, die Sie abschließend testen sollten, sollten den ersten Datenanteil simulieren, den Sie von Ihrem Client/Ihrer Anwendung erhalten, um Ihr Modell anzuwenden.

Deshalb ist die Kreuzvalidierung so leistungsfähig, dass jeder Datenpunkt in Ihrem gesamten Datensatz als Simulation neuer Daten verwendet wird.

Und jetzt, um Ihre Frage zu beantworten, sollte jede Kreuzvalidierung dem folgenden Muster folgen:

for train, test in kFold.split(X, Y
     model = training_procedure(train, ...)
     score = evaluation_procedure(model, test, ...)

denn Sie trainieren zunächst Ihr Modell und verwenden es dann für neue Daten. In Ihrem zweiten Ansatz - Sie können es nicht als Mimikry eines Trainingsprozesses behandeln, weil z. In der zweiten Falte würde Ihr Modell Informationen aus der ersten Falte behalten - was Ihrem Trainingsverfahren nicht entspricht.

Natürlich - Sie können ein Trainingsverfahren anwenden, bei dem das 10-fache des aufeinanderfolgenden Trainings verwendet wird, um das Netzwerk zu optimieren. Dies ist jedoch keine Kreuzvalidierung - Sie müssen dieses Verfahren anhand eines der obigen Schemata bewerten.

1
Marcin Możejko

Die auskommentierten Funktionen machen dies etwas weniger offensichtlich, aber die Idee besteht darin, die Modellleistung zu verfolgen, während Sie Ihre Falten durchlaufen und am Ende entweder diese Leistungskennzahlen auf niedrigerer Ebene oder eine durchschnittliche globale Leistung bereitstellen. Zum Beispiel:

Die train_evaluate-Funktion würde im Idealfall für jeden Split einen bestimmten Genauigkeitswert ausgeben, der am Ende kombiniert werden könnte.

def train_evaluate(model, x_train, y_train, x_test, y_test):
    model.fit(x_train, y_train)
    return model.score(x_test, y_test)

X, Y = load_model()
kFold = StratifiedKFold(n_splits=10)
scores = np.zeros(10)
idx = 0
for train, test in kFold.split(X, Y):
    model = create_model()
    scores[idx] = train_evaluate(model, X[train], Y[train], X[test], Y[test])
    idx += 1
print(scores)
print(scores.mean())

Sie möchten also ein neues Modell für jede Falzung erstellen, da in dieser Übung festgelegt wird, wie Ihr Modell bei der Konstruktion für alle Segmente der Daten funktioniert, nicht nur für ein bestimmtes Segment, das das Modell zulässt oder nicht gut zu leisten.

Diese Art von Ansatz wird besonders wirksam, wenn sie zusammen mit einer Gittersuche über Hyperparameter angewendet wird. Bei diesem Ansatz trainieren Sie ein Modell mit unterschiedlichen Hyperparametern unter Verwendung der Kreuzvalidierungsaufteilungen und verfolgen die Leistung in Bezug auf Aufteilungen und Gesamtmenge. Am Ende erhalten Sie eine bessere Vorstellung davon, mit welchen Hyperparametern das Modell die beste Leistung erzielt. Eine ausführlichere Erklärung finden Sie unter sklearn Model Selection und beachten Sie insbesondere die Abschnitte Cross Validation und Grid Search. 

1
Grr

Sie können Wrapper der Scikit-Learn-API für Keras-Modelle verwenden.

Bei gegebenen Eingaben x und y ist hier ein Beispiel für die wiederholte 5-fache Kreuzvalidierung:

from sklearn.model_selection import RepeatedKFold, cross_val_score
from tensorflow.keras.models import * 
from tensorflow.keras.layers import * 
from tensorflow.keras.wrappers.scikit_learn import KerasRegressor

def buildmodel():
    model= Sequential([
        Dense(10, activation="relu"),
        Dense(5, activation="relu"),
        Dense(1)
    ])
    model.compile(optimizer='adam', loss='mse', metrics=['mse'])
    return(model)

estimator= KerasRegressor(build_fn=buildmodel, epochs=100, batch_size=10, verbose=0)
kfold= RepeatedKFold(n_splits=5, n_repeats=100)
results= cross_val_score(estimator, x, y, cv=kfold, n_jobs=2)  # 2 cpus
results.mean()  # Mean MSE
0
Megatron