web-dev-qa-db-fra.com

Validation croisée à Keras

J'implémente un Perceptron multicouche dans Keras et utilise scikit-learn pour effectuer une validation croisée. Pour cela, je me suis inspiré du code contenu dans le numéro Cross Validation in Keras

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

Lors de mes études sur les réseaux de neurones, j’ai appris que la représentation des connaissances du réseau de neurones se situe dans les poids synaptiques et lors du processus de traçage de réseau, les poids sont mis à jour pour réduire ainsi le taux d’erreur du réseau et améliorer ses performances. (Dans mon cas, j'utilise l'apprentissage supervisé)

Pour améliorer la formation et l'évaluation des performances du réseau neuronal, une méthode courante est la validation croisée, qui renvoie des partitions de l'ensemble de données pour la formation et l'évaluation du modèle.

Mon doute est ...

Dans cet extrait de code:

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

Nous définissons, formons et évaluons un nouveau réseau de neurones pour chacune des partitions générées?

Si mon objectif est d’ajuster le réseau pour l’ensemble du jeu de données, pourquoi n’est-il pas correct de définir un seul réseau de neurones et de l’entraîner avec les partitions générées?

Pourquoi ce code est-il comme ça?

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

et pas si?

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

Est-ce que je comprends mal comment le code fonctionne? Ou ma théorie?

Merci!

7
Alisson Hayasi

Si mon objectif est d’ajuster le réseau pour l’ensemble du jeu de données

Vous ne comprenez pas ce que vous entendez par "peaufiner", ni même quel est exactement votre but pour effectuer une validation croisée (CV); en général, CV sert à l'une des fins suivantes:

  • Sélection du modèle (choisissez les valeurs des hyperparamètres)
  • Évaluation du modèle

Puisque vous ne définissez aucune grille de recherche pour la sélection d'hyperparamètre dans votre code, il semblerait que vous utilisiez CV pour obtenir les performances attendues de votre modèle (erreur, précision, etc.).

Quoi qu'il en soit, quelle que soit la raison pour laquelle vous utilisez CV, le premier extrait est le bon; votre deuxième extrait

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

formera votre modèle séquentiellement sur les différentes partitions (à savoir, entraînement sur la partition n ° 1, puis poursuite de la formation sur la partition n ° 2, etc.), qui consiste essentiellement en une formation sur l'ensemble de votre ensemble de données, et ce n'est certainement pas une validation croisée ...

Cela dit, une dernière étape après le CV qui est souvent seulement implicite (et que les débutants oublient souvent) est que, une fois que vous êtes satisfait des hyperparamètres choisis et/ou des performances du modèle telles que données par votre procédure de CV, retournez et entraînez à nouveau votre modèle, cette fois avec les données disponibles tout.

4
desertnaut

L'idée principale de tester les performances de votre modèle consiste à effectuer les étapes suivantes:

  1. Former un modèle sur un ensemble de formation. 
  2. Evaluez votre modèle sur des données non utilisées pendant le processus de formation afin de simuler une nouvelle arrivée de données.

Donc, fondamentalement, les données que vous devriez enfin tester votre modèle devraient imiter la première partie de données que vous obtiendrez de votre client/application pour appliquer votre modèle.

C'est pourquoi la validation croisée est si puissante: elle permet d'utiliser chaque point de données de votre ensemble de données comme une simulation de nouvelles données.

Et maintenant, pour répondre à votre question, chaque validation croisée devrait suivre le schéma suivant:

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

car après tout, vous allez d'abord entraîner votre modèle, puis l'utiliser sur de nouvelles données. Dans votre seconde approche, vous ne pouvez pas le traiter comme une imitation d’un processus de formation, car par exemple. dans un deuxième temps, votre modèle conserverait les informations du premier, ce qui n’équivaut pas à votre procédure d’entraînement.

Bien sûr, vous pouvez appliquer une procédure d’entraînement qui utilise 10 séances d’entraînement consécutives pour affiner le réseau. Mais il ne s’agit pas d’une validation croisée à ce stade - vous devrez évaluer cette procédure à l’aide d’un schéma quelconque ci-dessus.

1
Marcin Możejko

Les fonctions commentées rendent cela un peu moins évident, mais l’idée est de garder une trace de la performance de votre modèle lorsque vous parcourez vos plis et de fournir à la fin ces métriques de performance de niveau inférieur ou une performance globale moyenne. Par exemple:

La fonction train_evaluate devrait idéalement générer un score de précision pour chaque division, qui pourrait être combiné à la fin.

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

Donc, oui, vous voulez créer un nouveau modèle pour chaque pli, le but de cet exercice étant de déterminer les performances de votre modèle tel qu'il est conçu sur tous les segments de données, et pas uniquement sur un segment particulier autorisant ou interdisant le modèle. bien performer.

Ce type d'approche devient particulièrement puissant lorsqu'il est appliqué avec une recherche sur une grille sur des hyperparamètres. Dans cette approche, vous entraînez un modèle avec différents hyperparamètres en utilisant les divisions de validation croisée et gardez une trace de la performance sur les divisions et dans son ensemble. Au final, vous pourrez avoir une bien meilleure idée des hyperparamètres permettant au modèle de fonctionner au mieux. Pour une explication beaucoup plus détaillée, voir Choix du modèle sklearn et prêtez une attention particulière aux sections Validation croisée et Recherche de grille. 

1
Grr