Trening sieci neuronowej pod kątem regresji zawsze przewiduje średnią

9

Trenuję prostą sieć neuronową splotową do regresji, której zadaniem jest przewidzenie (x, y) położenia ramki na obrazie, np .:

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Dane wyjściowe sieci mają dwa węzły, jeden dla x i jeden dla y. Reszta sieci jest standardową splotową siecią neuronową. Strata jest standardowym średnim kwadratowym błędem między przewidywaną pozycją pudełka a pozycją prawdziwej ziemi. Trenuję na 10000 tych obrazów i sprawdzam poprawność na 2000 roku.

Problem, który mam, polega na tym, że nawet po znacznym treningu strata tak naprawdę nie maleje. Po zaobserwowaniu wyników sieci zauważam, że sieć ma tendencję do generowania wartości bliskich zeru, dla obu węzłów wyjściowych. W związku z tym przewidywanie położenia skrzynki jest zawsze środkiem obrazu. Istnieje pewne odchylenie w przewidywaniach, ale zawsze około zera. Poniżej pokazano stratę:

wprowadź opis zdjęcia tutaj

Uruchomiłem to przez wiele więcej epok, niż pokazano na tym wykresie, a strata wciąż nie maleje. Co ciekawe, strata faktycznie wzrasta w pewnym momencie.

Wygląda więc na to, że sieć po prostu przewiduje średnią danych szkoleniowych, a nie uczy się dobrego dopasowania. Wszelkie pomysły na to, dlaczego tak jest? Używam Adama jako optymalizatora, z początkową szybkością uczenia 0,01, a relus jako aktywacje


Jeśli interesuje Cię mój kod (Keras), poniżej:

# Create the model
model = Sequential()
model.add(Convolution2D(32, 5, 5, border_mode='same', subsample=(2, 2), activation='relu', input_shape=(3, image_width, image_height)))
model.add(Convolution2D(64, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Convolution2D(128, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(2, activation='linear'))


# Compile the model
adam = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(loss='mean_squared_error', optimizer=adam)


# Fit the model
model.fit(images, targets, batch_size=128, nb_epoch=1000, verbose=1, callbacks=[plot_callback], validation_split=0.2, shuffle=True)
Karnivaurus
źródło
Czy obrazy są na najlepszych przykładach twoich rzeczywistych próbek? Czy to 5 oddzielnych próbek? Wydaje się, że na obrazach nie ma informacji, które mogłyby pomóc w uogólnieniu. To znaczy, nie potrzebujesz sieci neuronowej, aby znaleźć lokalizację x, y białego kwadratu, możesz po prostu przeanalizować obraz i poszukać białego piksela. Wyjaśnij nieco więcej na temat swojej wizji tego modelu. Czy istnieje jakiś wzorzec czasowy, według którego przewidujesz następną lokalizację?
photox
Cześć, i tak, obrazy to 5 oddzielnych próbek. Nie jestem pewien, jak są dla ciebie renderowane, ale powinny to być 5 pojedynczych kwadratowych obrazów (nieco zmieniłem układ, aby pomóc ...). Tak, zdaję sobie sprawę, że do tego zadania nie potrzebujesz sieci neuronowej, ale to tylko eksperyment testowy, który pomoże mi nauczyć się regresji z siecią neuronową. Nie rozumiem, co masz na myśli, mówiąc, że nie ma informacji, które mogłyby pomóc w uogólnieniu ... Każda para szkoleniowa składa się z kwadratowego obrazu i dwuwymiarowego wektora położenia (x, y) kwadratu. Dzięki :)
Karnivaurus
1
1) Twój kształt wejściowy na pierwszej warstwie konwekcyjnej używa 3 kanałów (rbg), ale twoje dane są w skali szarości (1 kanał) 2) Nie potrzebujesz tak wielu warstw konwekcyjnych i filtrów, w rzeczywistości myślę, że jedna warstwa i garść małych jąder będzie w porządku.
photox
Czy jesteś pewien, że obrazy rzeczywiście odpowiadają celom?
user31264
1
Jak mówi @photox, nie potrzebujesz warstw konwekcyjnych. Dodanie ich utrudnia optymalizatorowi znalezienie dobrego rozwiązania. Jeśli usuniesz 3 warstwy konwekcji, podejrzewam, że twój „model” będzie działał.
Pieter

Odpowiedzi:

8

Optymalizator nie jest w stanie połączyć się z (pod) optymalnym rozwiązaniem. Dlaczego? Twój problem jest zbyt łatwy i / lub twój model jest zbyt złożony.

Zbyt łatwy problem

Jak już powiedział @photox, problem ten można rozwiązać za pomocą tylko jednej ukrytej warstwy. Podejrzewam nawet, że da się to zrobić bez ukrytej warstwy. Jest tak, ponieważ ten problem jest liniowo oddzielny .

Pozwól mi to zilustrować. Wyobraź sobie sieć neuronową bez ukrytych warstw i liniową funkcję aktywacji (możesz też nazwać to regresją liniową). Aby obliczyć lokalizację x kwadratu, każdy piksel jest podłączony do wyjścia x. Pierwsza kolumna pikseli jest związana z wagą1/width. Druga kolumna jest związana z wagą2/width. Trwa to do ostatniej kolumny (np. Kolumnyn), który jest związany z wagą n/width. Ponieważ niektóre piksele są niezerowe, aktywacja wyjścia jest liniowa względem współrzędnej x kwadratu. Dlatego funkcja liniowa może obliczyć położenie kwadratu.

Istnieje kilka rozwiązań:

  • Wybierz trudniejszy problem, np. Klasyfikację obrazu
  • Dodaj hałas, np. Sól i pieprz lub biały szum
  • Utrudniaj problem, np. Przewidując lokalizację czerwonego kwadratu, gdy w tle jest wiele różnokolorowych kół

Zbyt skomplikowany model

Twój model składa się z kilku części, które zwiększają złożoność, jednocześnie nie pomagając optymalizatorowi znaleźć słodkiego optimum.

Na przykład warstwy splotowe. Pierwsza warstwa ma 32 splotowe filtry wielkości5×5. Czego oczekujesz od tych filtrów? W klasyfikacji obrazów filtry te uczą się rozpoznawać krawędzie, narożniki, gradienty i plamy. Ale w tym przypadku jest tylko kilka filtrów, które mają sens. Mogę myśleć o przewadze od lewej do prawej i odwrotnie oraz od góry do dołu i odwrotnie. W twoim przypadku jest więc około 28 filtrów, które po prostu dodają losowy szum. Usunięcie tych (lub tylko całej warstwy) znacznie ułatwia optymalizatorowi znalezienie optymalnego, który działa.

Innym przykładem jest optymalizator Adam z wieloma dodatkowymi parametrami. Optymalizator Adam może dobrze działać z tymi parametrami, ale dlaczego nie zacząć od prostego SGDoptymalizatora z wartościami domyślnymi.

W ten sposób możesz dokonać kilku optymalizacji:

  • korzystać LinearRegressionz scikit-learn. OK, nie tego chcesz, ale chcę tylko zilustrować, jak bardzo skomplikowany jest ten model.
  • Usuń warstwy konwekcyjne
  • Zmniejsz rozmiar ukrytych Densewarstw
  • Użyj domyślnego SGDoptymalizatora
  • Jeśli używasz ukrytej warstwy, powinieneś spróbować sigmoidaktywacji. Możesz myśleć o każdym z węzłów ukrytej warstwy jako o wykrywaniu, czy kwadrat znajduje się w określonym miejscu.
  • Jeśli to wszystko nie działa, poeksperymentuj ze współczynnikiem uczenia się, aby dowiedzieć się, czy jest on za wysoki, czy za niski.

Ps

Myślę, że spodoba ci się ten blog Adit Deshpande.

Pieter
źródło
Daj mi znać, czy te rozwiązania zmieniły zachowanie optymalizatorów.
Pieter
Dzięki, to bardzo przydatne. Pracuję nad wypróbowaniem twoich sugestii. Nie rozumiem jednak twojego pierwszego punktu. Nie wiem, dlaczego, jeśli problem jest zbyt prosty, trudniej jest go zoptymalizować niż problem bardziej złożony. Dlaczego w przypadku danej sieci łatwiej jest zoptymalizować prostszy problem niż problem bardziej złożony? W prostym problemie pomyślałbym, że będą bardzo silne gradienty i silne globalne optimum. Ale twój pierwszy punkt mówi, że prostota problemu utrudnia optymalizację, sugerując, że bardziej skomplikowany problem pomógłby w optymalizacji ...
Karnivaurus
Nie kupuję żadnego z nich jako przyczyny tego problemu. Model „złożony” powinien być bardziej zdolny do nadmiernego dopasowania i dlatego nie powinien mieć trudności z dopasowaniem danych treningowych. „Łatwy” problem nie powinien utrudniać rozwiązania ani… „łatwy” jest zresztą określeniem względnym… może masz na myśli powiedzieć, że jego architektura sieci neuronowej nie jest w stanie przechwycić sygnału w swoich danych, chociaż może to być „prostszy”, ale zasadniczo inny model.
JacKeown
> „Jestem zdezorientowany, dlaczego, jeśli problem jest zbyt prosty, trudniej jest go zoptymalizować niż problem bardziej złożony”. Ponieważ model złożony ma wiele możliwości modelowania, z których nie korzysta. Ta nadwyżka zdolności wprowadza szum i utrudnia znalezienie prawdziwego sygnału.
Pieter
> „Nie kupuję żadnego z nich jako przyczyny tego problemu” - patrząc na odpowiedź, są one napisane z praktycznego punktu widzenia. Jeśli złożony model nie zbiegnie się prawidłowo, jednym ze sposobów debugowania jest użycie prostszego modelu.
Pieter
0

Mam ten sam problem z zestawem danych. Okazuje się, że w moim przypadku predyktory są wysoce skoncentrowane z bardzo małą wariancją. Powinieneś sprawdzić wariancję zmiennych predykcyjnych i zobaczyć, jak jest ona dystrybuowana.Rozkład zmiennej, którą próbuję przewidzieć

Można jednak wykonać niektóre transformacje zmiennej wyjściowej, aby zmodyfikować lub zmienić jej skalę. Może to spowodować bardziej jednolity rozkład typów. Na przykład w zadaniach rozpoznawania obrazu wyrównanie histogramu lub wzmocnienie kontrastu czasami działa na korzyść prawidłowego podejmowania decyzji.

Ravi Shankar
źródło
-1

Wygląda to na typowy problem przeuczenia. Twoje dane nie zawierają wystarczających informacji, aby uzyskać lepszy wynik. Wybierz złożony NN wraz z pociągiem, aby zapamiętać wszystkie niuanse danych pociągu . Strata nigdy nie może wynosić zero, jak na wykresie. BTW Wygląda na to, że twoja walidacja zawiera błąd lub zestaw walidacji nie nadaje się do walidacji, ponieważ utrata walidacji również jest zerowa.

Leonid Ganeline
źródło
5
Pytanie mówi, że sieć prawie zawsze generuje zero. Byłby to przypadek poważnego niedopasowania , a nie nadmiernego dopasowania. Nie ma również luki między błędem treningu a błędem walidacji na krzywej uczenia się, co wskazuje, że przeregulowanie nie jest problemem (błąd nie jest zerem, skala jest logarytmiczna)
20160
-1

Pracowałem nad bardzo podobnym problemem. Zasadniczo miałem kilka kropek na białym tle i trenowałem NN, aby rozpoznawać kropkę umieszczoną jako pierwszą w tle. Znalazłem sposób, aby po prostu użyć jednej w pełni połączonej warstwy neuronów (czyli 1-warstwowej NN). Na przykład dla obrazu 100 x 100 miałbym 10000 neuronów wejściowych (pikseli) bezpośrednio połączonych z 2 neuronami wyjściowymi (współrzędnymi). W PyTorch, kiedy przekonwertowałem wartości pikseli na tensor, automatycznie normalizowałem moje dane, odejmując średnią i dzieląc przez odchylenie standardowe. W normalnych problemach z uczeniem maszynowym jest to w porządku, ale nie w przypadku obrazu, w którym może występować rozbieżność w liczbie kolorowych pikseli na obrazie (tj. Takich, w których jest tylko kilka białych pikseli). Więc, Ręcznie znormalizowałem dzieląc wszystkie wartości intensywności pikseli przez 255 (więc są one teraz w zakresie 0-1 bez typowej techniki normalizacji, która próbuje dopasować wszystkie wartości intensywności do rozkładu normalnego). Potem nadal miałem problemy, ponieważ przewidywał średnią współrzędną pikseli w zestawie treningowym. Tak więc moim rozwiązaniem było ustawienie bardzo wysokiej częstotliwości uczenia się, co jest sprzeczne z prawie wszystkimi instruktorami ML i samouczkami. Zamiast używać 1e-3, 1e-4, 1e-5, jak większość ludzi mówi, korzystałem ze współczynnika uczenia się 1 lub 0,1 przy stochastycznym spadku. To rozwiązało moje problemy, a moja sieć w końcu nauczyła się zapamiętywać mój zestaw treningowy. Nie uogólnia do zestawu testowego zbyt dobrze, ale przynajmniej trochę działa, co jest lepszym rozwiązaniem niż większość innych sugerowanych na twoje pytanie. są teraz w zakresie 0-1 bez typowej techniki normalizacji, która próbuje dopasować wszystkie wartości intensywności do rozkładu normalnego). Potem nadal miałem problemy, ponieważ przewidywał średnią współrzędną pikseli w zestawie treningowym. Tak więc moim rozwiązaniem było ustawienie bardzo wysokiej częstotliwości uczenia się, co jest sprzeczne z prawie wszystkimi instruktorami ML i samouczkami. Zamiast używać 1e-3, 1e-4, 1e-5, jak większość ludzi mówi, korzystałem ze współczynnika uczenia się 1 lub 0,1 przy stochastycznym spadku. To rozwiązało moje problemy, a moja sieć w końcu nauczyła się zapamiętywać mój zestaw treningowy. Nie uogólnia do zestawu testowego zbyt dobrze, ale przynajmniej trochę działa, co jest lepszym rozwiązaniem niż większość innych sugerowanych na twoje pytanie. są teraz w zakresie 0-1 bez typowej techniki normalizacji, która próbuje dopasować wszystkie wartości intensywności do rozkładu normalnego). Potem nadal miałem problemy, ponieważ przewidywał średnią współrzędną pikseli w zestawie treningowym. Tak więc moim rozwiązaniem było ustawienie bardzo wysokiej częstotliwości uczenia się, co jest sprzeczne z prawie wszystkimi instruktorami ML i samouczkami. Zamiast używać 1e-3, 1e-4, 1e-5, jak większość ludzi mówi, korzystałem ze współczynnika uczenia się 1 lub 0,1 przy stochastycznym spadku. To rozwiązało moje problemy, a moja sieć w końcu nauczyła się zapamiętywać mój zestaw treningowy. Nie uogólnia do zestawu testowego zbyt dobrze, ale przynajmniej trochę działa, co jest lepszym rozwiązaniem niż większość innych sugerowanych na twoje pytanie.

Kok
źródło