Pierdere NaN la antrenarea rețelei de regresie (Programare, Python, Keras, Rețea Neuronală, Theano, Funcție De Pierdere)

Anomalia a intrebat.

Am o matrice de date în „one-hot encoding” (toți unu și zero) cu 260 000 de rânduri și 35 de coloane. Folosesc Keras pentru a antrena o rețea neuronală simplă pentru a prezice o variabilă continuă. Codul pentru a realiza rețeaua este următorul:

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

Cu toate acestea, în timpul procesului de instruire, văd că pierderea scade frumos, dar la mijlocul celei de-a doua epoci, aceasta se duce la 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

Am încercat să folosesc RMSProp în loc de SGD, am încercat tanh în loc de relu, am încercat cu și fără dropout, toate fără rezultat. Am încercat cu un model mai mic, adică cu un singur strat ascuns, și aceeași problemă (devine nan la un alt punct). Cu toate acestea, funcționează cu mai puține caracteristici, adică dacă există doar 5 coloane, și oferă predicții destul de bune. Se pare că există un fel de depășire, dar nu-mi pot imagina de ce – pierderea nu este deloc nerezonabil de mare.

Python versiunea 2.7.11, rulează pe o mașină linux, doar CPU. L-am testat cu cea mai recentă versiune de Theano și, de asemenea, primesc Nans, așa că am încercat să trec la Theano 0.8.2 și am aceeași problemă. Cu cea mai recentă versiune de Keras are aceeași problemă, și cu versiunea 0.3.2 de asemenea.

Comentarii

  • Încercați loss=’mean_squared_error’, optimizer=’adam’ cu un singur strat ascuns – tot nans? –  > Por 1”.
  • @1”’ Când folosesc modelul de mai sus cu optimizatorul Adam, obțin nans. Cu un singur strat, nu dă nans în timpul celor trei epoci de antrenament. –  > Por The_Anomaly.
  • pentru viitorii cititori, iată un thread relevant pentru keras. github.com/keras-team/keras/keras/issues/2134 Am un oarecare succes combinând toate sugestiile menționate aici. de exemplu, adăugarea batchnorm, variația ratei de învățare, optimizatorul, adăugarea clip_by_value, clip_by_global_norm, în cele din urmă, pieptănarea codului de mai multe ori pentru bug-uri ajută, de asemenea, de exemplu, lipsește stratul batch norm după un strat de conv. 🙂 –  > Por pangyuteng.
19 răspunsuri
1”

Regresia cu rețele neuronale este greu de făcut să funcționeze, deoarece ieșirea este nelimitată, deci sunteți în mod special predispus la problema gradienților explozivi (cauza probabilă a nansurilor).

Din punct de vedere istoric, o soluție cheie pentru gradienții explozivi a fost reducerea ratei de învățare, dar odată cu apariția algoritmilor cu rată de învățare adaptivă per parametru, cum ar fi Adam, nu mai este nevoie să setați o rată de învățare pentru a obține performanțe bune. Există foarte puține motive pentru a mai folosi SGD cu impulsuri, cu excepția cazului în care sunteți un împătimit al rețelelor neuronale și știți cum să reglați programul de învățare.

Iată câteva lucruri pe care le puteți încerca:

  1. Normalizați ieșirile cu normalizarea cuantică sau scorul z. Pentru a fi riguroși, calculați această transformare pe datele de instruire, nu pe întregul set de date. De exemplu, cu normalizarea cuantilor, dacă un exemplu se află în a 60-a percentila a setului de instruire, acesta primește o valoare de 0,6. (Puteți, de asemenea, să deplasați valorile normalizate prin cuantile în jos cu 0,5, astfel încât percentila 0 să fie -0,5 și percentila 100 să fie +0,5).

  2. Adăugați regularizarea, fie prin creșterea ratei de abandon, fie prin adăugarea de penalizări L1 și L2 la ponderi. Regularizarea L1 este analogă cu selecția caracteristicilor și, din moment ce ați spus că reducerea numărului de caracteristici la 5 oferă performanțe bune, este posibil să fie și L1.

  3. Dacă acestea tot nu vă ajută, reduceți dimensiunea rețelei. Aceasta nu este întotdeauna cea mai bună idee, deoarece poate dăuna performanței, dar în cazul dvs. aveți un număr mare de neuroni din primul strat (1024) în raport cu caracteristicile de intrare (35), astfel încât ar putea fi de ajutor.

  4. Creșteți dimensiunea lotului de la 32 la 128. 128 este o valoare destul de standard și ar putea crește stabilitatea optimizării.

Comentarii

  • În ceea ce privește 1. De ce nu normalizați întregul set de ieșire? De asemenea, pot folosi în schimb scalarea? –  > Por Eran.
  • @Eran Dacă utilizați întregul set de date (instruire + test) atunci când decideți cum să normalizați, încorporați indirect informații despre setul de testare în setul de instruire, ceea ce reprezintă o formă de contaminare instruire-test. Cu toate acestea, atâta timp cât folosiți doar setul de instruire atunci când decideți cum să normalizați, puteți folosi scalarea sau orice alt tip de normalizare care oferă performanțe bune. –  > Por 1”.
  • Verificând mărimea lotului și constatând că este prea mică (16), creșterea mărimii lotului la 128 funcționează! –  > Por allenyllee.
  • Reducerea ratei de învățare pe Adam a funcționat! –  > Por curios95.
  • Regula mea de bază în ceea ce privește dimensiunea lotului este că ar trebui să fie atât de mare cât permite memoria, dar cel mult 1% din numărul de observații. Cu 1% veți obține 100 de loturi aleatorii, ceea ce înseamnă că aveți încă partea stocastică a coborârii stocastice a gradientului. –  > Por grofte.
pir

Răspunsul de 1″ este destul de bun. Cu toate acestea, toate soluțiile par să rezolve problema indirect, mai degrabă decât direct. V-aș recomanda să folosiți gradient clipping, care va tăia orice gradient care este peste o anumită valoare.

În Keras puteți utiliza clipnorm=1 (a se vedea https://keras.io/optimizers/) pentru a tăia pur și simplu toate gradienții cu o normă mai mare de 1.

Comentarii

    15

  • Corect! Aceasta este o strategie absolut legitimă, care este adesea utilizată în cazul rețelelor neuronale recurente, de exemplu. Cu toate acestea, înainte de a recurge la această metodă, este întotdeauna bine să verificați dacă nu s-a greșit ceva simplu în optimizare. –  > Por 1”.
  • Aceasta va fi marcată ca fiind soluția corectă, deoarece rezolvă de fapt problema specifică și nu oferă sfaturi pe teme mai largi. –  > Por HAL9000.
  • Același link keras sugerează că decuparea gradientului nu mai este suportată. Există o soluție analogă? –  > Por NeStack.
  • Funcționează acest lucru pentru toate optimizatoarele? Și este întotdeauna o idee bună să setați la 1.0? –  > Por CMCDragonkai.
  • Da, ar trebui să funcționeze pentru toate optimizatoarele. Dacă problema dvs. de optimizare este suficient de simplă/stabilă, atunci acest lucru nu este necesar și poate încetini puțin antrenamentul fără a aduce vreun beneficiu. –  > Por pir.
HenryZhao

M-am confruntat cu aceeași problemă înainte. Caut și găsesc această întrebare și răspunsuri. Toate aceste trucuri menționate mai sus sunt importante pentru instruirea unei rețele neuronale profunde. Le-am încercat pe toate, dar tot am obținut NAN.

Am găsit și această întrebare aici. https://github.com/fchollet/keras/issues/2134. Am citat rezumatul autorului după cum urmează:

Am vrut să semnalez acest lucru, astfel încât să fie arhivat pentru alții care ar putea întâmpina această problemă în viitor. Mă confruntam cu funcția mea de pierdere care returna brusc un nan după ce merge atât de departe în procesul de instruire. Am verificat relus, optimizatorul, funcția de pierdere, abandonul meu în conformitate cu relus, dimensiunea rețelei mele și forma rețelei. Tot primeam pierderi care în cele din urmă se transformau într-un nan și deveneam destul de frustrat.

Apoi mi-am dat seama. S-ar putea să am o intrare proastă. Se pare că una dintre imaginile pe care le dădeam CNN-ului meu (și pe care făceam normalizarea mediei) nu conținea decât 0-uri. Nu am verificat acest caz atunci când am sustras media și am normalizat cu abaterea standard și astfel am ajuns la o matrice de exemplare care nu conținea nimic altceva decât niște nan. După ce am reparat funcția de normalizare, rețeaua mea se antrenează acum perfect.

Sunt de acord cu punctul de vedere de mai sus: intrarea este sensibilă pentru rețeaua dumneavoastră. În cazul meu, folosesc valoarea logaritmică a estimării densității ca intrare. Valoarea absolută ar putea fi foarte mare, ceea ce poate duce la NaN după mai multe etape de gradienți. Cred că verificarea intrării este necesară. În primul rând, trebuie să vă asigurați că intrarea nu nu include -inf sau inf, sau unele numere extrem de mari în valoare absolută.

Comentarii

  • Am avut aceeași problemă ca și dumneavoastră. În timp ce îmi verificam datele, am găsit mai multe locuri cu puncte de date inf. Eliminarea acestora a rezolvat problema. –  > Por troymyname00.
  • Acest lucru a rezolvat problema pentru mine, aveam mai multe NaN-uri în matricea mea de încorporare 🙂 Mulțumesc. –  > Por Aldo Canepa.
  • Am scalat imaginile de intrare (png) de la 0-255 (uint8) la 0.-1.(float32), niciodată nu m-aș fi gândit că intrarea este vinovată…. adăugarea unui tf.clip_by_value înainte de a trece intrarea în rețea pentru instruire pare să fi rezolvat călătoria mea de depanare de 9 luni… – –  > Por pangyuteng.
  • De asemenea, rețineți că np.isnan(np.inf) == False. Pentru a vă asigura că niciunul dintre exemplele dvs. nu conține NaNs sau Infs, puteți face ceva de genul assert np.all(np.isfinite(X)). (Acest lucru m-a surprins de mai multe ori: Credeam că datele mele sunt în regulă pentru că verificam dacă există NaN-uri. Dar am uitat că np.isnan nu observă Infs!) – –  > Por Jack Kelly.
Arnav

M-am confruntat cu o problemă foarte asemănătoare și iată cum am reușit să o fac să funcționeze.

Primul lucru pe care îl puteți încerca este să vă schimbați activarea în LeakyReLU în loc să folosiți Relu sau Tanh. Motivul este că, de multe ori, multe dintre nodurile din cadrul straturilor tale au o activare de zero, iar backpropogation nu actualizează ponderile pentru aceste noduri deoarece gradientul lor este, de asemenea, zero. Acest lucru se mai numește și problema „ReLU muribund” (puteți citi mai multe despre aceasta aici: https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in-neural-networks).

Pentru a face acest lucru, puteți importa activarea LeakyReLU folosind:

from keras.layers.advanced_activations import LeakyReLU

și să o încorporați în straturile dvs. astfel:

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

În plus, este posibil ca caracteristica de ieșire (variabila continuă pe care încercați să o preziceți) să fie un set de date dezechilibrat și să aibă prea multe 0-uri. O modalitate de a remedia această problemă este utilizarea netezimii. Puteți face acest lucru adăugând 1 la numărătorul tuturor valorilor din această coloană și împărțind fiecare dintre valorile din această coloană cu 1/(media tuturor valorilor din această coloană).

În esență, acest lucru deplasează toate valorile de la 0 la o valoare mai mare decât 0 (care poate fi încă foarte mică). Acest lucru împiedică curba să prezică 0-uri și să minimizeze pierderea (în cele din urmă făcând-o NaN). Valorile mai mici sunt afectate mai mult decât cele mai mari, dar, în ansamblu, media setului de date rămâne aceeași.

javac

M-am confruntat cu aceeași problemă cu utilizarea LSTM, problema este că datele mele au unele valori nan după standardizare, prin urmare, ar trebui să verificăm datele modelului de intrare după standarizare dacă vedeți că veți avea valoare nan:

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

puteți rezolva această problemă adăugând o valoare mică (0.000001) la Std, astfel,

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

Othmane

Pentru a rezuma diferitele soluții menționate aici și de aici github discuție, care ar depinde, desigur, de situația dvs. particulară:

  • Adăugați regularizare pentru a adăuga penalizări l1 sau l2 la ponderi. În caz contrar, încercați o regularizare l2 mai mică, de exemplu l2(0,001), sau eliminați-o dacă există deja.
  • Încercați o rată de abandon mai mică.
  • Tăiați gradienții pentru a preveni explozia lor. De exemplu, în Keras puteți utiliza clipnorm=1. sau clipvalue=1. ca parametri pentru optimizatorul dvs.
  • Verificați validitatea intrărilor (fără NaN-uri sau uneori 0-uri), de exemplu df.isnull().any().
  • Înlocuiți optimizatorul cu Adam, care este mai ușor de gestionat. Uneori, ar fi de ajutor și înlocuirea sgd cu rmsprop.
  • Utilizați RMSProp cu regularizare puternică pentru a preveni explozia gradientului.
  • Încercați să vă normalizați datele sau inspectați procesul de normalizare pentru a vedea dacă au fost introduse valori proaste.
  • Verificați dacă utilizați funcția de activare corectă (de exemplu, utilizați o softmax în loc de sigmoid pentru clasificarea claselor multiple).
  • Încercați să măriți dimensiunea lotului (de exemplu, de la 32 la 64 sau 128) pentru a crește stabilitatea optimizării dumneavoastră.
  • Încercați să micșorați rata de învățare.
  • Verificați dimensiunea ultimului lot, care poate fi diferită de dimensiunea lotului.

Krithi07

Primeam pierderea ca nan chiar în prima epocă, imediat ce începea antrenamentul. Soluția simplă de a elimina nas din datele de intrare a funcționat pentru mine (df.dropna())

Sper că acest lucru ajută pe cineva care se confruntă cu o problemă similară

Comentarii

  • Cum ați eliminat nani din prima epocă? Eu am nans înainte de a începe antrenamentul…  > Por Supamee.
Rorschach

Am avut aceeași problemă cu RNN-ul meu cu straturi keras LSTM, așa că am încercat fiecare soluție de mai sus. Îmi scalasem deja datele (cu sklearn.preprocessing.MinMaxScaler), nu existau NaN valori în datele mele după scalare. Soluții precum utilizarea LeakyRelU sau schimbarea ratei de învățare nu au ajutat.

Așa că am decis să schimb scalatorul de la MinMaxScaler la StandardScaler, chiar dacă nu aveam nici un NaN valori și mi s-a părut ciudat, dar a funcționat!

Dmitri Senkovici

În cazul meu, problema a fost că am copiat munca mea anterioară pentru clasificarea binară și am folosit sigmoid activare pe stratul de ieșire în loc de softmax (noua rețea era despre clasificarea multiclasă).

Keng Chan

Încercați să verificați datele dvs. dacă există valori NAN. Îndepărtarea valorilor NAN a rezolvat problema pentru mine.

Clay Coleman

Am încercat toate sugestiile de pe această pagină și multe altele, fără niciun rezultat. Am importat fișiere csv cu pandas, apoi am folosit keras Tokenizer cu intrare de text pentru a crea vocabulare și matrici de vectori de cuvinte. După ce am observat că unele fișiere CSV au dus la nan în timp ce altele au funcționat, ne-am uitat brusc la codificarea fișierelor și am realizat că ascii NU funcționau cu keras, ceea ce a dus la nan pierderea și a acurateței 0.0000e+00; totuși, fișierele utf-8 și utf-16 au fost funcționau! Descoperire.

Dacă efectuați o analiză textuală și obțineți nan pierderi după ce ați încercat aceste sugestii, utilizați file -i {input} (linux) sau file -I {input} (osx) pentru a descoperi tipul de fișier. Dacă aveți ISO-8859-1 sau us-ascii, încercați să convertiți în utf-8 sau utf-16le. Nu l-am încercat pe acesta din urmă, dar îmi imaginez că ar funcționa la fel de bine. Sperăm că acest lucru ajută pe cineva foarte foarte frustrat!

Nu_Dave

Am avut o problemă similară cu logloss-ul meu, MAE și altele fiind toate NA. M-am uitat în date și am găsit, am avut câteva caracteristici cu NA-uri în ele. Am imputat NA-urile cu valori aproximative și am reușit să rezolv problema.

Kushagra Bhatia

Am avut aceeași problemă, am folosit Keras pentru o problemă de regresie multivariată. Ceea ce mi-am dat seama mai târziu a fost că unele valori din setul meu de date erau nan și asta a dus la o pierdere nan. am folosit comanda:

df=df.dropna()

Și mi-a rezolvat problema.

Mcomic

Am avut o problemă similară folosind Keras. Pierderea s-a transformat în NAN după ce a fost introdus al doilea lot.

Am încercat să:

  1. Utilizați softmax ca activare a stratului dens de ieșire
  2. Să scot nan în intrare
  3. Să normalizez intrarea

Cu toate acestea, nu a funcționat. Așa că am încercat să:

  1. Să micșorez rata de învățare

Problema s-a rezolvat.

din_mars

Am avut aceeași problemă cu CNN-ul meu keras, ca și alții, am încercat toate soluțiile de mai sus: scăderea ratei de învățare, eliminarea nulității din datele de antrenament, normalizarea datelor, adăugarea unui strat de abandon și …dar nu am putut rezolva problema nan, am încercat să schimb funcția de activare în stratul de clasificare (ultimul) din sigmoid în softmax. A funcționat!Încercați să schimbați funcția de activare a ultimului strat la softmax!

Talha Chafekar

Am obținut același lucru când am încercat să creez un regresor bounding box. Rețeaua mea neuronală avea un strat mai mare decât al tău. Am mărit valoarea de abandonare și am obținut rezultate adecvate.

Fateh Singh

A fost obtinerea NaN pentru rețeaua mea de clasificare.Răspund aici, deoarece ar putea ajuta pe cineva.

Am făcut o gafă…

Numărul de clase în etichetele de instruire a fost 5. adică de la 0 la 4.

În ultimul strat dens de clasificare a avut 4 noduri, ceea ce înseamnă 4 clase, ceea ce reprezintă problema.

Schimbând numărul de noduri din ultimul strat al rețelei la 5, am rezolvat problema.

Max

Am avut o problemă similară și am încercat să schimb activările de la Sigmoid la Softmax și de la RelU la LeakyRelU și problema a fost rezolvată. Așadar, cred că, atâta timp cât nu există NaN în datele de intrare și ați încercat să reduceți rata de învățare, soluția viabilă este să vă jucați cu activările!

wutzebaer

Am avut această problemă atunci când una dintre intrările mele de date de instruire conținea un nan