web-dev-qa-db-fra.com

Perte de NaN lors de l'entraînement sur un réseau de régression

J'ai une matrice de données en «codage à chaud» (toutes les unités et zéros) avec 260 000 lignes et 35 colonnes. J'utilise Keras pour former un réseau de neurones simple permettant de prédire une variable continue. Le code pour créer le réseau est le suivant:

model = Sequential()
model.add(Dense(1024, input_shape=(n_train,)))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(1))

sgd = SGD(lr=0.01, nesterov=True);
#rms = RMSprop()
#model.compile(loss='categorical_crossentropy', optimizer=rms, metrics=['accuracy'])
model.compile(loss='mean_absolute_error', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_Epoch=3, verbose=1, validation_data=(X_test,Y_test), callbacks=[EarlyStopping(monitor='val_loss', patience=4)] )

Cependant, au cours du processus d’entraînement, la perte a bien diminué, mais au milieu de la deuxième époque, elle est passée à nan:

Train on 260000 samples, validate on 64905 samples
Epoch 1/3
260000/260000 [==============================] - 254s - loss: 16.2775 - val_loss:
 13.4925
Epoch 2/3
 88448/260000 [=========>....................] - ETA: 161s - loss: nan

J'ai essayé d'utiliser RMSProp au lieu de SGD, j'ai essayé tanh au lieu de relu, j'ai essayé avec et sans abandon, le tout en vain. J’ai essayé avec un modèle plus petit, c’est-à-dire avec un seul calque caché, et le même problème (il devient nan à un point différent). Cependant, cela fonctionne avec moins de fonctionnalités, c’est-à-dire s’il n’ya que 5 colonnes, et donne de très bonnes prédictions. Il semble y avoir une sorte de débordement, mais je ne peux pas imaginer pourquoi - la perte n’est pas démesurée du tout. 

Python version 2.7.11, fonctionnant sur une machine Linux, CPU uniquement. Je l'ai testé avec la dernière version de Theano, et j'ai aussi Nans, alors j'ai essayé d'aller à Theano 0.8.2 et j'ai le même problème. Avec la dernière version de Keras a le même problème, et aussi avec la version 0.3.2. 

32
The_Anomaly

La régression avec des réseaux de neurones est difficile à mettre en oeuvre car la sortie est illimitée, vous êtes donc particulièrement exposé au problème des gradients explosifs (cause probable des nans). 

Historiquement, une solution clé pour exploser les gradients consistait à réduire le taux d'apprentissage. Toutefois, avec l'avènement des algorithmes de taux d'apprentissage adaptatifs par paramètre comme Adam, il n'est plus nécessaire de définir un taux d'apprentissage pour obtenir de bonnes performances. Il y a très peu de raisons d'utiliser SGD avec élan, à moins que vous ne soyez un fan de réseau neuronal et que vous sachiez ajuster le calendrier d'apprentissage.

Voici certaines choses que vous pourriez potentiellement essayer:

  1. Normalisez vos sorties en quantile normalisant ou z en marquant . Pour être rigoureux, calculez cette transformation sur les données d'apprentissage, et non sur l'ensemble de données. Par exemple, avec la normalisation de quantiles, si un exemple se situe dans le 60e centile de l'ensemble de formation, il obtient une valeur de 0,6. (Vous pouvez également réduire les valeurs normalisées du quantile de 0,5 pour que le 0e centile soit égal à -0,5 et le 100e centile à +0,5).

  2. Ajoutez une régularisation, soit en augmentant le taux d'abandon scolaire, soit en ajoutant des pénalités L1 et L2 aux poids. La régularisation de L1 est analogue à la sélection des fonctionnalités, et puisque vous avez dit que réduire le nombre de fonctionnalités à 5 donne de bonnes performances, L1 peut également.

  3. Si cela ne vous aide toujours pas, réduisez la taille de votre réseau. Ce n'est pas toujours la meilleure idée car cela peut nuire aux performances, mais dans votre cas, vous avez un grand nombre de neurones de première couche (1024) par rapport aux entités en entrée (35), donc cela peut aider.

  4. Augmentez la taille du lot de 32 à 128. 128 est assez standard et pourrait potentiellement augmenter la stabilité de l'optimisation.

51
1''

La réponse par 1 "est tout à fait bonne. Cependant, tous les correctifs semblent résoudre le problème de manière indirecte plutôt que directement. Je recommanderais d'utiliser l'écrêtage en dégradé, qui coupera simplement les dégradés dépassant une certaine valeur.

Dans Keras, vous pouvez utiliser clipnorm=1 (voir https://keras.io/optimizers/ ) pour couper simplement tous les dégradés avec une norme supérieure à 1.

20
pir

J'ai fait face au même problème avant. Je cherche et trouve cette question et ses réponses. Toutes les astuces mentionnées ci-dessus sont importantes pour la formation d'un réseau de neurones profonds. Je les ai tous essayés, mais j'ai quand même eu NAN. 

Je trouve aussi cette question ici. https://github.com/fchollet/keras/issues/2134 . J'ai cité le résumé de l'auteur comme suit: ““ Je tenais à le signaler afin qu'il soit archivé pour les autres personnes susceptibles de rencontrer ce problème à l'avenir. Je courais dans ma fonction de perte, revenant soudainement à un nan après avoir passé si loin dans le processus de formation. J'ai vérifié le relus, l'optimiseur, la fonction de perte, mon abandon conformément au relus, la taille de mon réseau et la forme du réseau. J'avais encore des pertes qui se sont transformées en nan et je devenais assez frustré.

Ensuite, j'ai compris. Je peux avoir une mauvaise entrée. Il s'avère que l'une des images que je transmettais à mon CNN (et faisant la normalisation moyenne) n'était rien d'autre que des 0. Je ne cherchais pas ce cas lorsque j'ai soustrait la moyenne et normalisé par la déviation standard et que je me suis donc retrouvé avec une matrice exemplaire qui n'était que nan. Une fois ma fonction de normalisation corrigée, mon réseau s’entraîne parfaitement. »

Je suis d'accord avec le point de vue ci-dessus: l'entrée est sensible pour votre réseau. Dans mon cas, J'utilise la valeur de journal de l'estimation de la densité comme entrée. La valeur absolue peut être très énorme, ce qui peut entraîner NaN après plusieurs étapes de gradients. Je pense que la vérification d'entrée est nécessaire. Tout d’abord, vous devez vous assurer que l’entrée ne fait pas include -inf ou inf, ou des nombres extrêmement importants en valeur absolue. 

15
HenryZhao

J'ai été confronté à un problème très similaire, et voici comment je l'ai fait fonctionner. 

La première chose que vous pouvez essayer est de changer votre activation en LeakyReLU au lieu d’utiliser Relu ou Tanh. La raison en est que souvent, de nombreux nœuds au sein de vos couches ont une activation égale à zéro, et que backpropogation ne met pas à jour les pondérations de ces nœuds, car leur gradient est également nul. Ceci est aussi appelé le problème 'mourant de ReLU' (vous pouvez en lire plus ici: https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in-neural -réseaux ). 

Pour ce faire, vous pouvez importer l'activation de LeakyReLU en utilisant:

from keras.layers.advanced_activations import LeakyReLU

et l'intégrer dans vos couches comme ceci:

model.add(Dense(800,input_shape=(num_inputs,)))
model.add(LeakyReLU(alpha=0.1))

De plus, il est possible que la fonction de sortie (la variable continue que vous essayez de prédire) soit un ensemble de données déséquilibré et comporte trop de 0. Un moyen de résoudre ce problème consiste à utiliser le lissage. Vous pouvez le faire en ajoutant 1 au numérateur de toutes vos valeurs dans cette colonne et en divisant chacune des valeurs de cette colonne par 1/(moyenne de toutes les valeurs de cette colonne).

Cela déplace essentiellement toutes les valeurs de 0 à une valeur supérieure à 0 (qui peut encore être très petite). Cela empêche la courbe de prédire les 0 et de minimiser la perte (ce qui la rend finalement NaN). Les valeurs plus petites ont plus d'impact que les valeurs plus grandes, mais dans l'ensemble, la moyenne de l'ensemble de données reste la même. 

5
Arnav

Je commençais à perdre tout mon poids dès la première époque, dès le début de la formation. Une solution aussi simple que de supprimer le nas des données d'entrée a fonctionné pour moi (df.dropna ())

J'espère que cela aide quelqu'un qui rencontre un problème similaire

2
Krithi07

J'ai essayé toutes les suggestions sur cette page et beaucoup d'autres en vain. Nous importions des fichiers csv avec des pandas, puis utilisions keras Tokenizer avec saisie de texte pour créer des vocabulaires et des matrices vectorielles Word. Après avoir remarqué que certains fichiers CSV conduisaient à nan alors que d'autres fonctionnaient, nous avons soudainement examiné l'encodage des fichiers et nous nous sommes rendu compte que les fichiers ascii ne fonctionnaient PAS avec keras, entraînant une perte de nan et une précision de 0.0000e+00; Cependant, les fichiers utf-8 et utf-16 étaient fonctionnaient! Percée.

Si vous effectuez une analyse textuelle et obtenez une perte de nan après avoir essayé ces suggestions, utilisez file -i {input} (linux) ou file -I {input} (osx) pour découvrir votre type de fichier. Si vous avez ISO-8859-1 ou us-ascii, essayez de convertir en utf-8 ou utf-16le. Je n'ai pas essayé le dernier mais j'imagine que cela fonctionnerait aussi. Espérons que cela aide quelqu'un de très très frustré!

0
Clay Coleman