Najczęstsze przyczyny nans podczas treningu


85

Zauważyłem, że pojawia się częste zjawisko podczas treningu NAN.

Często wydaje się, że jest on wprowadzany przez nadmuchiwanie ciężarów w warstwach produktu wewnętrznego / w pełni połączonych lub splotowych.

Czy dzieje się tak, ponieważ obliczenia gradientu wybuchają? A może jest to spowodowane inicjalizacją wagi (jeśli tak, dlaczego inicjalizacja wagi ma taki efekt)? A może jest to prawdopodobnie spowodowane charakterem danych wejściowych?

Nadrzędne pytanie brzmi po prostu: Jaki jest najczęstszy powód występowania sieci NAN podczas treningu? Po drugie, jakie są metody zwalczania tego problemu (i dlaczego działają)?


Czy wywołujesz określone funkcje MATLAB? Czy to wszystko twój własny kod?
Matthew Gunn

2
@MatthewGunn Nie sądzę, aby to pytanie było specyficzne dla MATLABA, ale raczej związane caffe.
Shai

Odpowiedzi:


134

Dobre pytanie.
Z tym zjawiskiem spotkałem się kilkakrotnie. Oto moje spostrzeżenia:


Gradientowy wysadzenie

Powód: duże wzniesienia utrudniają naukę.

Czego powinieneś się spodziewać: Patrząc na dziennik czasu wykonywania, powinieneś spojrzeć na wartości strat na iterację. Zauważysz, że strata zaczyna znacznie rosnąć od iteracji do iteracji, ostatecznie strata będzie zbyt duża, aby była reprezentowana przez zmienną zmiennoprzecinkową i stanie się nan.

Co możesz zrobić: Zmniejsz base_lr(w solver.prototxt) o rząd wielkości (przynajmniej). Jeśli masz kilka warstw strat, powinieneś sprawdzić dziennik, aby zobaczyć, która warstwa jest odpowiedzialna za wysadzenie gradientu i zmniejszyć loss_weight(w train_val.prototxt) dla tej konkretnej warstwy, zamiast ogólnej base_lr.


Zasady i parametry dotyczące nieprawidłowego tempa uczenia się

Powód: caffe nie może obliczyć prawidłowego współczynnika uczenia się i pobiera 'inf'lub 'nan'zamiast tego, ta nieprawidłowa stawka mnoży wszystkie aktualizacje, a tym samym unieważnia wszystkie parametry.

Czego powinieneś się spodziewać: Patrząc na dziennik czasu działania, powinieneś zobaczyć, że sam współczynnik uczenia się zmienia się 'nan'na przykład:

... sgd_solver.cpp:106] Iteration 0, lr = -nan

Co możesz zrobić: naprawić wszystkie parametry wpływające na szybkość uczenia się w 'solver.prototxt'pliku.
Na przykład, jeśli użyjesz lr_policy: "poly"i zapomnisz zdefiniować max_iterparametr, otrzymasz lr = nan...
Więcej informacji o tempie uczenia się w kawie znajdziesz w tym wątku .


Wadliwa funkcja utraty

Przyczyna: czasami obliczenia strat w warstwach strat powodują nanpojawienie się s. Na przykład InfogainLosswarstwa karmienia z nieznormalizowanymi wartościami , używanie niestandardowej warstwy strat z błędami itp.

Czego powinieneś się spodziewać: Patrząc na dziennik działania, prawdopodobnie nie zauważysz niczego niezwykłego: utrata stopniowo maleje i nagle nanpojawia się.

Co możesz zrobić: Sprawdź, czy możesz odtworzyć błąd, dodaj wydruk do warstwy strat i zdebuguj błąd.

Na przykład: Kiedyś zastosowałem stratę, która znormalizowała karę na podstawie częstotliwości występowania etykiety w partii. Tak się złożyło, że jeśli jedna z etykiet uczących w ogóle nie pojawiła się w partii - obliczona strata wyprodukowana nans. W takim przypadku wystarczyła praca z odpowiednio dużymi partiami (biorąc pod uwagę liczbę etykiet w zestawie), aby uniknąć tego błędu.


Wadliwe wejście

Powód: masz w tym wkład nan!

Czego powinieneś się spodziewać: gdy proces uczenia się „trafi” na to błędne dane wejściowe - wyjście staje się nan. Patrząc na dziennik działania, prawdopodobnie nie zauważysz nic niezwykłego: strata stopniowo maleje i nagle nanpojawia się.

Co możesz zrobić: odbuduj swoje wejściowe zbiory danych (lmdb / leveldn / hdf5 ...) upewnij się, że nie masz złych plików graficznych w swoim zestawie treningowym / walidacyjnym. W celu debugowania możesz zbudować prostą sieć, która odczytuje warstwę wejściową, ma na sobie fałszywą stratę i przechodzi przez wszystkie dane wejściowe: jeśli jedno z nich jest wadliwe, ta atrapa sieci również powinna produkować nan.


krok większy niż rozmiar jądra w "Pooling"warstwie

Z jakiegoś powodu wybranie stride> kernel_sizedo łączenia może skutkować nans. Na przykład:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

wyniki z nans in y.


Niestabilności w "BatchNorm"

Zgłoszono, że pod niektórymi ustawieniami "BatchNorm"warstwa może wyprowadzać nans z powodu niestabilności numerycznych.
Ten problem został zgłoszony w bvlc / caffe i PR # 5136 próbuje go naprawić.


Ostatnio zdałem sobie sprawę z debug_infoflagą: ustawienie debug_info: truew 'solver.prototxt'uczyni drukiem caffe zalogowania więcej informacji debugowania (w tym wielkości i wartości gradientu aktywacja) podczas treningu: Ta informacja może pomóc w plamienie wybuchy gradientu i inne problemy w procesie szkolenia .


Dzięki, jak można zinterpretować te liczby? Co to za liczby? pastebin.com/DLYgXK5v dlaczego jest tylko jeden numer wyjściowy na warstwę !? jak powinny wyglądać te liczby, żeby ktoś wiedział, że jest problem lub go nie ma !?
Rika

@Hossein właśnie o tym jest ten post .
Shai

Dzięki za tę odpowiedź. Otrzymuję utratę NAN dla aplikacji do segmentacji obrazu wytrenowanej z utratą DICE (nawet po dodaniu małej stałej epsilon / gładkości). Mój zbiór danych zawiera obrazy, których odpowiadająca im prawda naziemna, która nie zawiera żadnej etykiety pierwszego planu, i kiedy usunąłem te obrazy ze uczenia, utrata została ustabilizowana. Nie wiem, dlaczego tak jest?
samra irshad

@samrairshad Czy próbowałeś zwiększyć epsilon w utracie DICE?
Shai

Tak. Otworzyłem post przy przepełnieniu stosu i wkleiłem ewolucję strat dla niektórych epok. Oto odniesienie: stackoverflow.com/questions/62259112/…
samra irshad

5

W moim przypadku przyczyną było nie ustawienie odchylenia w warstwach splotu / dekonwolucji.

Rozwiązanie: dodaj następujące parametry do parametrów warstwy splotu.

bias_filler {type: "constant" wartość: 0}


jak by to wyglądało w matconvnet? Mam coś w stylu „biases”. Init_bias * ones (1,4, single)
h612

4

Ta odpowiedź nie dotyczy przyczyny nans, ale raczej proponuje sposób jej debugowania. Możesz mieć tę warstwę Pythona:

class checkFiniteLayer(caffe.Layer):
  def setup(self, bottom, top):
    self.prefix = self.param_str
  def reshape(self, bottom, top):
    pass
  def forward(self, bottom, top):
    for i in xrange(len(bottom)):
      isbad = np.sum(1-np.isfinite(bottom[i].data[...]))
      if isbad>0:
        raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" %
                        (self.prefix,i,100*float(isbad)/bottom[i].count))
  def backward(self, top, propagate_down, bottom):
    for i in xrange(len(top)):
      if not propagate_down[i]:
        continue
      isf = np.sum(1-np.isfinite(top[i].diff[...]))
        if isf>0:
          raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" %
                          (self.prefix,i,100*float(isf)/top[i].count))

Dodanie tej warstwy do twojego train_val.prototxtw pewnych punktach, które podejrzewasz, może spowodować problemy:

layer {
  type: "Python"
  name: "check_loss"
  bottom: "fc2"
  top: "fc2"  # "in-place" layer
  python_param {
    module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH
    layer: "checkFiniteLayer"
    param_str: "prefix-check_loss" # string for printouts
  }
}

1

learning_rate jest wysoki i powinien zostać zmniejszony Dokładność w kodzie RNN wynosiła nan, z wybraniem niskiej wartości szybkości uczenia się, którą naprawia


-1

Próbowałem zbudować rzadki autoenkoder i miałem w nim kilka warstw, aby wywołać rzadkość. Podczas uruchamiania sieci napotkałem NaN. Po usunięciu niektórych warstw (w moim przypadku musiałem usunąć 1), stwierdziłem, że NaN zniknęły. Tak więc, myślę, że zbyt duża rzadkość może również prowadzić do NaN (niektóre obliczenia 0/0 mogły zostać wywołane !?)


czy możesz być trochę bardziej szczegółowy? czy możesz podać szczegółowe informacje na temat konfiguracji, która miała nansi, i stałej konfiguracji? jaki rodzaj warstw? jakie parametry?
Shai,

1
@shai Użyłem kilku warstw InnerProduct (lr_mult 1, decay_mult 1, lr_mult 2, decay_mult 0, xavier, std: 0.01), po których następowała ReLU (z wyjątkiem ostatniej). Pracowałem z MNIST i jeśli dobrze pamiętam, architektura to 784 -> 1000 -> 500 -> 250 -> 100 -> 30 (i symetryczna faza dekodera); usunięcie warstwy 30 wraz z ReLU sprawiło, że NaN zniknęły.
LKB,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.