it-swarm.com.de

NaN-Verlust beim Training des Regressionsnetzwerks

Ich habe eine Datenmatrix in "One-Hot-Codierung" (alle Einsen und Nullen) mit 260.000 Zeilen und 35 Spalten. Ich benutze Keras, um ein einfaches neuronales Netzwerk zu trainieren, um eine kontinuierliche Variable vorherzusagen. Der Code für das Netzwerk ist folgender:

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

Während des Trainingsprozesses sehe ich jedoch, dass der Verlust gut abnimmt, aber in der Mitte der zweiten Epoche geht es um 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

Ich habe versucht, RMSProp anstelle von SGD zu verwenden, ich versuchte tanh anstelle von relu, ich versuchte es mit und ohne Aussetzer, alles ohne Erfolg. Ich habe es mit einem kleineren Modell versucht, d. H. Mit nur einer verborgenen Schicht und demselben Problem (es wird an einem anderen Punkt nan). Es funktioniert jedoch mit weniger Features, d. H. Wenn es nur 5 Spalten gibt, und liefert ziemlich gute Vorhersagen. Es scheint, dass es eine Art Überlauf gibt, aber ich kann mir nicht vorstellen, warum - der Verlust ist nicht unangemessen groß. 

Python Version 2.7.11, läuft auf einem Linux-Rechner, nur CPU. Ich habe es mit der neuesten Version von Theano getestet, und ich bekomme auch Nans, also habe ich versucht, zu Theano 0.8.2 zu gehen, und habe das gleiche Problem. Mit der neuesten Version von Keras hat das gleiche Problem und auch mit der Version 0.3.2. 

32
The_Anomaly

Die Regression mit neuronalen Netzwerken ist schwer zu bekommen, da die Ausgabe unbegrenzt ist. Daher sind Sie besonders anfällig für das explodierende Gradientenproblem (die wahrscheinliche Ursache der Nans). 

In der Vergangenheit war eine der wichtigsten Lösungen für das Explodieren von Gradienten die Verringerung der Lernrate. Mit dem Aufkommen von Algorithmen für adaptive Lernraten pro Parameter wie Adam müssen Sie jedoch keine Lernrate mehr festlegen, um eine gute Leistung zu erzielen. Es gibt kaum einen Grund, SGD mit Momentum zu verwenden, es sei denn, Sie sind ein Neuralnetzwerkfreund und wissen, wie Sie den Lernzeitplan anpassen.

Hier sind einige Dinge, die Sie möglicherweise ausprobieren könnten:

  1. Normalisieren Sie Ihre Ausgaben durch Quantil-Normalisierung oder Z-Bewertung . Um streng zu sein, berechnen Sie diese Transformation anhand der Trainingsdaten und nicht des gesamten Datensatzes. Bei der Quantil-Normalisierung erhält ein Beispiel beispielsweise, wenn es sich im 60. Perzentil des Trainingssatzes befindet, den Wert 0,6. (Sie können die normalisierten Werte des Quantils auch um 0,5 nach unten verschieben, sodass das 0-Perzentil -0,5 und das 100-Perzentil +0,5 beträgt).

  2. Fügen Sie die Regularisierung hinzu, indem Sie entweder die Dropout-Rate erhöhen oder L1- und L2-Strafen zu den Gewichtungen hinzufügen. L1-Regularisierung ist analog zur Merkmalsauswahl, und da Sie sagten, dass die Reduzierung der Anzahl der Merkmale auf 5 eine gute Leistung bringt, kann L1 auch.

  3. Wenn diese immer noch nicht helfen, reduzieren Sie die Größe Ihres Netzwerks. Dies ist nicht immer die beste Idee, da dies die Leistung beeinträchtigen kann. In Ihrem Fall haben Sie jedoch eine große Anzahl an Neuronen der ersten Schicht (1024) im Verhältnis zu den Eingabemerkmalen (35), sodass dies hilfreich sein kann.

  4. Erhöhen Sie die Stapelgröße von 32 auf 128. 128 ist ein Standard und könnte die Stabilität der Optimierung möglicherweise erhöhen.

51
1''

Die Antwort von 1 "ist ziemlich gut. Allerdings scheinen alle Fixes das Problem eher indirekt als direkt zu beheben. Ich würde die Verwendung von Verlaufsausschnitten empfehlen, bei dem alle Gradienten, die über einem bestimmten Wert liegen, einfach abgeschnitten werden.

In Keras können Sie clipnorm=1 (siehe https://keras.io/optimizers/ ) verwenden, um alle Gradienten mit einer Norm über 1 zu schneiden.

20
pir

Ich hatte schon früher das gleiche Problem. Ich suche und finde diese Frage und Antworten. Alle diese Tricks sind für das Training eines tiefen neuronalen Netzwerks wichtig. Ich habe sie alle ausprobiert, aber immer noch NAN bekommen. 

Diese Frage finde ich auch hier. https://github.com/fchollet/keras/issues/2134 . Ich zitierte die Zusammenfassung des Autors wie folgt: __. „Ich wollte darauf hinweisen, damit sie für andere archiviert wird, die dieses Problem in der Zukunft haben könnten. Ich lief in meine Verlustfunktion und kehrte plötzlich ein Nan zurück, nachdem es so weit in den Trainingsprozess eingedrungen war. Ich habe den Relus, den Optimierer, die Verlustfunktion, meinen Aussetzer entsprechend dem Relus, die Größe meines Netzwerks und die Form des Netzwerks überprüft. Ich bekam immer noch Verluste, die sich letztendlich in eine Nanosekunde verwandelten, und ich wurde ziemlich ärgerlich.

Dann dämmerte es mir. Ich habe möglicherweise schlechte Eingaben. Es stellte sich heraus, dass eines der Bilder, die ich meinem CNN übergab (und dabei Normalisierung bedeutet), nichts anderes als Nullen war. Ich habe nicht nach diesem Fall gesucht, als ich den Mittelwert subtrahierte und durch die Standardabweichung normalisierte. So erhielt ich eine Mustermatrix, die nichts anderes als nans war. Sobald ich meine Normalisierungsfunktion repariert habe, trainiert mein Netzwerk jetzt perfekt. “

Ich stimme dem obigen Standpunkt zu: Die Eingabe ist für Ihr Netzwerk empfindlich. In meinem Fall Ich verwende den log-Wert der Dichteschätzung als Eingabe. Der absolute Wert kann sehr groß sein, was nach mehreren Gradienten zu NaN führen kann. Ich denke, die Eingabeprüfung ist notwendig. Zuerst sollten Sie sicherstellen, dass die Eingabe nicht include -inf oder inf oder einige extrem große Zahlen in absoluten Werten enthält. 

15
HenryZhao

Ich war mit einem sehr ähnlichen Problem konfrontiert, und so habe ich es zum Laufen gebracht. 

Als Erstes können Sie versuchen, die Aktivierung in LeakyReLU zu ändern, anstatt Relu oder Tanh zu verwenden. Der Grund ist, dass viele der Knoten in Ihren Layern häufig eine Aktivierung von Null haben und die Backpropogation die Gewichtungen für diese Knoten nicht aktualisiert, da ihr Gradient ebenfalls Null ist. Dies wird auch als "sterbende ReLU" -Problem bezeichnet (mehr darüber können Sie hier lesen: https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in-neural -networks ). 

Dazu können Sie die LeakyReLU-Aktivierung importieren, indem Sie

from keras.layers.advanced_activations import LeakyReLU

und füge es so in deine Ebenen ein:

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

Darüber hinaus ist es möglich, dass die Ausgabefunktion (die fortlaufende Variable, die Sie vorhersagen möchten) ein unausgeglichener Datensatz ist und zu viele Nullen aufweist. Eine Möglichkeit, dieses Problem zu beheben, ist die Glättung. Sie können dies tun, indem Sie dem Zähler aller Ihrer Werte in dieser Spalte den Wert 1 hinzufügen und jeden Wert in dieser Spalte durch 1 teilen. (Durchschnitt aller Werte in dieser Spalte).

Dies verschiebt im Wesentlichen alle Werte von 0 auf einen Wert größer als 0 (der immer noch sehr klein sein kann). Dadurch wird verhindert, dass die Kurve 0s vorhersagt und den Verlust minimiert (was letztendlich zu NaN führt). Kleinere Werte sind stärker betroffen als größere, insgesamt bleibt der Durchschnitt des Datensatzes jedoch gleich. 

5
Arnav

Ich hatte das gleiche Problem mit der Verwendung von LSTM. Das Problem ist, dass meine Daten nach der Standardisierung einen gewissen Nanowert haben. Daher sollten wir die Eingabemodelldaten nach der Standardisierung überprüfen, wenn Sie feststellen, dass Sie einen Nanowert haben:

print(np.any(np.isnan(X_test)))
print(np.any(np.isnan(y_test)))

sie können dies lösen, indem Sie einen kleinen Wert (0,000001) zu Std hinzufügen.

def standardize(train, test):


    mean = np.mean(train, axis=0)
    std = np.std(train, axis=0)+0.000001

    X_train = (train - mean) / std
    X_test = (test - mean) /std
    return X_train, X_test
2
javac

Ich bekam den Verlust als Nan in der allerersten Epoche, sobald das Training beginnt. Lösung so einfach wie das Entfernen der NAS aus den für mich funktionierenden Eingabedaten (df.dropna ())

Ich hoffe, das hilft jemandem, der ein ähnliches Problem hat

2
Krithi07

Ich hatte ein ähnliches Problem mit meinem logloss, MAE und anderen, die alle NAs sind. Ich habe die Daten untersucht und festgestellt, dass ich nur wenige Features mit NAs darin hatte. Ich habe NAs mit ungefähren Werten unterstellt und konnte um das Problem zu lösen.

1
Not_Dave

Ich hatte das gleiche Problem, ich verwendete Keras für ein multivariates Regressionsproblem. Was ich später erkannte, war, dass einige Werte in meinem Datensatz nan waren und dies zu einem Nanoverlust führte. Ich habe den Befehl verwendet:

df=df.dropna()

Und es löste mein Problem.

1
Kushagra Bhatia

Ich habe jeden Vorschlag auf dieser Seite und viele andere ohne Erfolg ausprobiert. Wir importierten csv-Dateien mit Pandas und benutzten dann keras Tokenizer mit Texteingabe, um Vokabulare und Word-Vektor-Matrizen zu erstellen. Nachdem wir bemerkt hatten, dass einige CSV-Dateien zu nan geführt haben, während andere gearbeitet haben, haben wir uns plötzlich die Kodierung der Dateien angesehen und festgestellt, dass ascii -Dateien NICHT mit Keras arbeiten, was zu nan-Verlust und Genauigkeit von 0.0000e+00 führt. utf-8- und utf-16-Dateien funktionierten! Durchbruch.

Wenn Sie nach dem Durchführen dieser Vorschläge eine Textanalyse durchführen und nan verlieren, verwenden Sie file -i {input} (linux) oder file -I {input} (osx), um Ihren Dateityp zu ermitteln. Wenn Sie ISO-8859-1 oder us-ascii haben, versuchen Sie, in utf-8 oder utf-16le zu konvertieren. Ich habe das letztere nicht ausprobiert, aber ich könnte mir vorstellen, dass es auch funktionieren würde. Hoffentlich hilft das jemandem sehr, sehr frustriert!

0
Clay Coleman