Testowanie jednostkowe jest twoim przyjacielem
Wśród autorów jest powiedzenie, że „Całe pisanie jest pisaniem od nowa” - to znaczy większa część pisania jest rewizji. W przypadku programistów (lub przynajmniej naukowców zajmujących się danymi) wyrażenie to może zostać zmienione na „Debugowanie całego kodowania”.
Za każdym razem, gdy piszesz kod, musisz sprawdzić, czy działa on zgodnie z przeznaczeniem. Najlepszą metodą, jaką kiedykolwiek znalazłem do weryfikacji poprawności, jest rozbicie kodu na małe segmenty i sprawdzenie, czy każdy segment działa. Można to zrobić przez porównanie wyniku segmentu z odpowiedzią, o której wiesz, że jest poprawną odpowiedzią. Nazywa się to testowaniem jednostkowym . Pisanie dobrych testów jednostkowych jest kluczem do zostania dobrym statystykiem / naukowcem danych / ekspertem w dziedzinie uczenia maszynowego / praktykiem sieci neuronowych. Po prostu nie ma substytutu.
Musisz sprawdzić, czy Twój kod jest wolny od błędów, zanim będziesz mógł dostroić wydajność sieci! W przeciwnym razie równie dobrze możesz zmienić układ leżaków na RMS Titanic .
Istnieją dwie cechy sieci neuronowych, które sprawiają, że weryfikacja jest jeszcze ważniejsza niż w przypadku innych typów uczenia maszynowego lub modeli statystycznych.
Sieci neuronowe nie są „gotowymi” algorytmami, tak jak losowy regres leśny lub logistyczny. Nawet w przypadku prostych sieci z przekazywaniem informacji spoczywa w dużej mierze na użytkowniku podejmowanie licznych decyzji dotyczących konfiguracji, połączenia, inicjalizacji i optymalizacji sieci. Oznacza to pisanie kodu, a pisanie kodu oznacza debugowanie.
Nawet jeśli kod sieci neuronowej działa bez zgłaszania wyjątku, sieć może nadal zawierać błędy! Błędy te mogą nawet być podstępnym rodzajem, dla którego sieć będzie trenować, ale utknie na nieoptymalnym rozwiązaniu lub sieć wynikowa nie będzie miała pożądanej architektury. ( Jest to przykład różnicy między błędem składniowym a semantycznym ).
W tym średnim poście „ Jak testować kod uczenia maszynowego jednostki ” Chase Roberts bardziej szczegółowo omawia testy jednostkowe modeli uczenia maszynowego. Ten przykład błędnego kodu pożyczyłem z artykułu:
def make_convnet(input_image):
net = slim.conv2d(input_image, 32, [11, 11], scope="conv1_11x11")
net = slim.conv2d(input_image, 64, [5, 5], scope="conv2_5x5")
net = slim.max_pool2d(net, [4, 4], stride=4, scope='pool1')
net = slim.conv2d(input_image, 64, [5, 5], scope="conv3_5x5")
net = slim.conv2d(input_image, 128, [3, 3], scope="conv4_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool2')
net = slim.conv2d(input_image, 128, [3, 3], scope="conv5_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool3')
net = slim.conv2d(input_image, 32, [1, 1], scope="conv6_1x1")
return net
Czy widzisz błąd? Wiele różnych operacji nie jest faktycznie używanych, ponieważ poprzednie wyniki są nadpisywane nowymi zmiennymi. Korzystanie z tego bloku kodu w sieci nadal będzie się trenować, a wagi będą się aktualizować, a utrata może nawet spaść - ale kod zdecydowanie nie robi tego, co było zamierzone. (Autor jest również niekonsekwentny w stosowaniu pojedynczych lub podwójnych cudzysłowów, ale jest to czysto stylistyczny).
Najczęstsze błędy programowania dotyczące sieci neuronowych to
- Zmienne są tworzone, ale nigdy nie są używane (zwykle z powodu błędów kopiowania i wklejania);
- Wyrażenia dotyczące aktualizacji gradientu są niepoprawne;
- Aktualizacje wagi nie są stosowane;
- Funkcje strat nie są mierzone we właściwej skali (na przykład utratę entropii można wyrazić w kategoriach prawdopodobieństwa lub logarytmów)
- Utrata nie jest odpowiednia dla zadania (na przykład przy użyciu kategorycznej utraty entropii krzyżowej dla zadania regresji).
Czołgaj się przed tobą; Idź zanim uciekniesz
Szerokie i głębokie sieci neuronowe oraz sieci neuronowe z egzotycznym okablowaniem są obecnie najważniejszym elementem uczenia maszynowego. Ale sieci te nie powstały w pełni uformowane; ich projektanci zbudowali je z mniejszych jednostek. Najpierw zbuduj małą sieć z jedną ukrytą warstwą i sprawdź, czy działa poprawnie. Następnie stopniowo zwiększaj złożoność modelu i sprawdź, czy każdy z nich również działa.
Zbyt mało neuronów w warstwie może ograniczyć reprezentację, której uczy się sieć, powodując niedopasowanie. Zbyt wiele neuronów może powodować nadmierne dopasowanie, ponieważ sieć „zapamiętuje” dane treningowe.
Nawet jeśli możesz udowodnić, że matematycznie jest tylko niewielka liczba neuronów niezbędnych do modelowania problemu, często zdarza się, że posiadanie „kilku kolejnych” neuronów ułatwia optymalizatorowi znalezienie „dobrej” konfiguracji. (Ale nie sądzę, aby ktokolwiek w pełni rozumiał, dlaczego tak jest.) Podaję tutaj przykład tego w kontekście problemu XOR: Czy moje iteracje nie są potrzebne do trenowania NN dla XOR z MSE <0,001 zbyt wysokim? .
Wybór liczby ukrytych warstw pozwala sieci nauczyć się abstrakcji na podstawie surowych danych. Głębokie uczenie się jest obecnie modne, a sieci z dużą liczbą warstw pokazały imponujące wyniki. Ale dodanie zbyt wielu ukrytych warstw może spowodować zbyt duże ryzyko lub bardzo utrudnić optymalizację sieci.
Wybór sprytnego okablowania sieciowego może zrobić dla ciebie wiele pracy. Czy Twoje źródło danych jest dostosowane do wyspecjalizowanych architektur sieciowych? Konwolucyjne sieci neuronowe mogą osiągać imponujące wyniki w „strukturalnych” źródłach danych, danych obrazu lub dźwięku. Nawracające sieci neuronowe mogą dobrze sobie radzić z sekwencyjnymi typami danych, takimi jak język naturalny lub dane szeregów czasowych. Pozostałe połączenia mogą poprawić sieci z głębokim sprzężeniem zwrotnym.
Szkolenie w sieci neuronowej przypomina wybieranie blokady
Aby osiągnąć najnowszy stan techniki, a nawet po prostu dobre wyniki, musisz skonfigurować wszystkie części skonfigurowane tak, aby dobrze ze sobą współpracowały . Konfigurowanie konfiguracji sieci neuronowej, która faktycznie się uczy, jest bardzo podobne do wybierania blokady: wszystkie elementy muszą być ustawione w jednej linii . Podobnie jak nie wystarczy mieć jeden kubek we właściwym miejscu, tak samo nie wystarczy mieć tylko architekturę, czy tylko optymalizator, poprawnie skonfigurowany.
Strojenie opcji konfiguracji nie jest tak proste, jak stwierdzenie, że jeden rodzaj wyboru konfiguracji (np. Szybkość uczenia się) jest mniej lub bardziej ważny niż inny (np. Liczba jednostek), ponieważ wszystkie te opcje współdziałają ze wszystkimi innymi wyborami, więc jeden wybór może mieć się dobrze w połączeniu z innym wyborem dokonanym gdzie indziej .
Jest to niewyczerpująca lista opcji konfiguracji, które nie są również opcjami regularyzacji ani opcjami optymalizacji numerycznej.
Wszystkie te tematy są aktywnymi obszarami badań.
Inicjalizacja sieci jest często pomijana jako źródło błędów w sieci neuronowej. Inicjalizacja w zbyt dużych odstępach czasu może ustawić zbyt duże wagi początkowe, co oznacza, że pojedyncze neurony mają ogromny wpływ na zachowanie sieci.
Kluczowa różnica między siecią neuronową a modelem regresji polega na tym, że sieć neuronowa jest kompozycją wielu funkcji nieliniowych, zwanych funkcjami aktywacyjnymi . (Zobacz: Jaka jest zasadnicza różnica między siecią neuronową a regresją liniową )
Wyniki klasycznej sieci neuronowej koncentrują się na sigmoidalnych funkcjach aktywacyjnych (funkcje logistyczne lub ). Niedawny wynik wykazał, że jednostki ReLU (lub podobne) zwykle działają lepiej, ponieważ mają bardziej strome gradienty, dzięki czemu aktualizacje można szybko zastosować. (Zobacz: Dlaczego używamy ReLU w sieciach neuronowych i jak go używamy? ) Jedną z ostrzeżeń dotyczących ReLU jest zjawisko „martwego neuronu”, które może utrudniać naukę; nieszczelny relus i podobne warianty pozwalają uniknąć tego problemu. Widziećtanh
Istnieje wiele innych opcji. Zobacz: Kompleksowa lista funkcji aktywacyjnych w sieciach neuronowych z zaletami / wadami
Pozostałe połączenia to zgrabny rozwój, który może ułatwić trenowanie sieci neuronowych. „Deep Residual Learning for Recognition
Records ” Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun In: CVPR. (2016). Ponadto zmiana kolejności operacji w bloku resztkowym może dodatkowo poprawić wynikową sieć. „ Mapowania tożsamości w głębokich sieciach rezydualnych ” Kaiming He, Xiangyu Zhanga, Shaoqing Ren i Jian Sun.
Optymalizacja niewypukła jest trudna
Funkcja celu sieci neuronowej jest wypukła tylko wtedy, gdy nie ma ukrytych jednostek, wszystkie aktywacje są liniowe, a matryca projektowa ma pełną rangę - ponieważ ta konfiguracja jest identycznym problemem regresji.
We wszystkich innych przypadkach problem optymalizacji nie jest wypukły, a optymalizacja niewypukła jest trudna. Wyzwania związane z treningiem sieci neuronowych są dobrze znane (patrz: Dlaczego trudno trenować głębokie sieci neuronowe? ). Ponadto sieci neuronowe mają bardzo dużą liczbę parametrów, co ogranicza nas do metod wyłącznie pierwszego rzędu (patrz: Dlaczego metoda Newtona nie jest szeroko stosowana w uczeniu maszynowym? ). To bardzo aktywny obszar badań.
Ustawienie zbyt dużej szybkości uczenia się spowoduje rozbieżność optymalizacji, ponieważ przeskoczysz z jednej strony „kanionu” na drugą. Ustawienie tej zbyt małej wartości uniemożliwi wykonywanie jakichkolwiek rzeczywistych postępów i możliwe, że hałas związany z SGD będzie przytłaczał oszacowania gradientu.
Obcinanie gradientu przeskalowuje normę gradientu, jeśli jest powyżej pewnego progu. Kiedyś myślałem, że jest to parametr „ustaw i zapomnij”, zwykle 1.0, ale odkryłem, że mogę znacznie ulepszyć model językowy LSTM, ustawiając go na 0,25. Nie wiem dlaczego tak jest.
Planowanie szybkości uczenia się może obniżyć szybkość uczenia się w trakcie szkolenia. Z mojego doświadczenia wynika, że próba użycia harmonogramu jest bardzo podobna do wyrażenia regularnego : zastępuje jeden problem („Jak nauczyć się kontynuować po określonej epoce?”) Dwoma problemami („Jak mogę nauczyć się kontynuować po określonej epoce ? ”i„ Jak wybrać dobry harmonogram? ”). Inni twierdzą, że planowanie jest niezbędne. Pozwolę ci zdecydować.
Wybór dobrego rozmiaru mini-partii może pośrednio wpłynąć na proces uczenia się, ponieważ większa mini-partia będzie miała mniejszą wariancję ( prawo dużej liczby ) niż mniejsza mini-partia. Chcesz, aby mini-partia była wystarczająco duża, aby informować o kierunku gradientu, ale wystarczająco mała, aby SGD mogła uregulować sieć.
Istnieje wiele wariantów stochastycznego spadku gradientu, które wykorzystują pęd, adaptacyjne wskaźniki uczenia się, aktualizacje Niestierowa i tak dalej, aby ulepszyć SGD waniliowy. Projektowanie lepszego optymalizatora jest bardzo aktywnym obszarem badań. Kilka przykładów:
Gdy pojawił się po raz pierwszy, optymalizator Adam cieszył się dużym zainteresowaniem. Jednak niektóre ostatnie badania wykazały, że SGD z pędem może przewyższyć adaptacyjne metody gradientu dla sieci neuronowych. „ Marginalna wartość adaptacyjnych metod gradientowych w uczeniu maszynowym ” Ashii C. Wilson, Rebecca Roelofs, Mitchell Sterna, Nathana Srebro, Benjamina Rechta
Ale z drugiej strony, ten bardzo niedawny artykuł proponuje nowy optymalizator adaptacyjnej szybkości uczenia się, który rzekomo zamyka lukę między metodami adaptacyjnej szybkości uczenia się a SGD. „ Zamykanie luki uogólniającej w adaptacyjnych metodach gradientowych w szkoleniu głębokich sieci neuronowych ” Jinghui Chen, Quanquan Gu
Zaobserwowano, że metody gradientu adaptacyjnego, które przyjmują historyczne informacje o gradiencie w celu automatycznego dostosowania szybkości uczenia się, generalizują gorsze niż stochastyczne obniżanie gradientu (SGD) z pędem w uczeniu głębokich sieci neuronowych. To pozostawia otwarty problem, jak zamknąć lukę uogólniającą w metodach gradientu adaptacyjnego. W tej pracy pokazujemy, że metody gradientu adaptacyjnego, takie jak Adam, Amsgrad, są czasami „nadmiernie dostosowane”. Projektujemy nowy algorytm, zwany Częściowo adaptacyjną metodą szacowania pędu (Padam), który łączy Adama / Amsgrada z SGD, aby osiągnąć to, co najlepsze z obu światów. Eksperymenty na standardowych testach porównawczych pokazują, że Padam może utrzymać szybki wskaźnik konwergencji jako Adam / Amsgrad, jednocześnie uogólniając, a także SGD w szkoleniu głębokich sieci neuronowych.
Normalizacja
Skala danych może mieć duży wpływ na trening.
Przed przedstawieniem danych do sieci neuronowej, standaryzacja danych w celu uzyskania 0 wartości średniej i wariancji jednostkowej lub w krótkich odstępach czasu, takich jak może poprawić trening. Sprowadza się to do wstępnego kondycjonowania i usuwa wpływ, jaki wybór jednostek ma na wagi sieci. Na przykład długość w milimetrach i długość w kilometrach reprezentują tę samą koncepcję, ale są w różnych skalach. Dokładne szczegóły standaryzacji danych zależą od wyglądu danych.[−0.5,0.5]
Normalizacja warstw może poprawić szkolenie w sieci, utrzymując bieżącą średnią i standardowe odchylenie dla aktywacji neuronów. Nie jest do końca zrozumiałe, dlaczego pomaga to w szkoleniu i pozostaje aktywnym obszarem badań.
- „ Zrozumienie normalizacji partii ” Johan Bjorck, Carla Gomes, Bart Selman
- „ Ku teoretycznemu zrozumieniu normalizacji partii ” Jonasa Kohlera, Hadi Daneshmanda, Aurelien Lucchi, Ming Zhou, Klausa Neymeyra, Thomasa Hofmanna
- „W jaki sposób normalizacja partii pomaga w optymalizacji? (Nie, nie chodzi o wewnętrzne przesunięcie współzmiennych ) ” Shibani Santurkar, Dimitris Tsipras, Andrew Ilyas, Aleksander Madry
Regularyzacja
Wybór i dostrajanie regularyzacji sieci jest kluczową częścią budowy modelu, który dobrze się uogólnia (tj. Modelu, który nie jest zbyt dopasowany do danych treningowych). Jednak w momencie, gdy twoja sieć stara się zmniejszyć utratę danych treningowych - gdy sieć się nie uczy - regularyzacja może ukryć problem.
Kiedy moja sieć się nie uczy, wyłączam wszelką regularyzację i sprawdzam, czy sieć nieregulowana działa poprawnie. Następnie dodaję z powrotem każdy element regulacyjny i sprawdzam, czy każdy z nich działa po drodze.
Ta taktyka może wskazać, gdzie pewna regularyzacja może być źle ustawiona. Niektóre przykłady to
L2 (inaczej rozpad masy) lub regularyzacja jest ustawiona zbyt duża, więc ciężary nie mogą się poruszać.L1
Dwie części regularyzacji są w konflikcie. Na przykład powszechnie obserwuje się, że normalizacja warstw i usuwanie są trudne do zastosowania razem. Ponieważ jedno z nich jest bardzo przydatne, zrozumienie, jak korzystać z obu, jest aktywnym obszarem badań.
Prowadź dziennik eksperymentów
Kiedy konfiguruję sieć neuronową, nie koduję na stałe ustawień parametrów. Zamiast tego robię to w pliku konfiguracyjnym (np. JSON), który jest odczytywany i używany do zapełniania szczegółów konfiguracji sieci w czasie wykonywania. Trzymam wszystkie te pliki konfiguracyjne. Jeśli dokonam modyfikacji parametru, utworzę nowy plik konfiguracyjny. Na koniec dołączam jako komentarz wszystkie straty przypadające na epokę w celu szkolenia i walidacji.
Powodem, dla którego mam obsesję na punkcie zachowania starych wyników, jest to, że bardzo łatwo jest wrócić i przejrzeć poprzednie eksperymenty. Zabezpiecza również przed błędnym powtórzeniem tego samego ślepego eksperymentu. Z psychologicznego punktu widzenia, ale także pozwala spojrzeć wstecz i obserwować „Cóż, projekt nie może być tam, gdzie chcę być dzisiaj, ale robię postępy w stosunku do miejsca, gdzie byłem tygodnie temu.”k
Jako przykład chciałem dowiedzieć się o modelach językowych LSTM, dlatego postanowiłem stworzyć bota Twittera, który będzie pisać nowe tweety w odpowiedzi na innych użytkowników Twittera. Pracowałem nad tym w wolnym czasie, między szkołą średnią a pracą. Zajęło to około roku, a ja przejrzałem ponad 150 różnych modeli, zanim dotarłem do modelu, który zrobił to, co chciałem: wygenerować nowy tekst w języku angielskim, który (w pewnym sensie) ma sens. (Jednym kluczowym punktem spornym i jednym z powodów, dla których tyle prób było, jest to, że nie wystarczyło po prostu uzyskać małą stratę poza próbą, ponieważ wczesne modele o niskiej stracie udało się zapamiętać dane treningowe, więc w odpowiedzi na podpowiedzi odtwarzał po prostu dosłownie bloki tekstu dosłownie - zajęło mi to trochę czasu, aby model stał się bardziej spontaniczny i nadal miał niską stratę).