Sterowanie samochodu autonomicznego za pomocą sieci neuronowej End to End to wspaniały eksperyment by rozpocząć przygodę z głębokimi sieciami neuronowymi i przetwarzaniem obrazu w zastosowaniu do samochodów autonomicznych. A zatem jak sterować samochodem autonomicznym?
W rzeczywistym świecie unikamy stosowania rozwiązania end to end z uwagi na brak uzasadnienia procesu decyzyjnego czy chęć planowania trasy. Mówiąc end to end mam tu na myśli sieć neuronową, której wejściem jest obraz z kamery (ew. chmura punktów z lasera), a wyjściem jest kąt skrętu kierownicy oraz poziom wciśnięcia hamulca czy gazu. Chodzi o to by na podstawie dużej liczby przykładów nauczyć zaprojektowaną sieć neuronową co najczęściej robi „ludzki kierowca”. Tu jest ważna rzecz – sieć wytrenowana na danych nagranych przez jednego kierowcę będzie prowadzić w jego stylu.
Musimy zadbać o zróżnicowanie danych – to jest duży problem.
Jeśli wyobrazimy sobie nagrany miesiąc naszych codziennych podróży praca-dom, to okaże się że najczęściej jedziemy prosto – na histogramie kąta skrętu kierownicy zobaczymy, że większość danych jest w zerze, albo tuż obok, co może wynikać z przesuniętego kąta 0°.

Co w takiej sytuacji możemy zrobić? Co zrobić by nasz sieć nie stwierdziła, że najczęściej to jednak jedziemy prosto, więc jeżeli dam na wyjściu 0° na stałe to na zbiorze trenującym uzyskam zadowalająco niski błąd i biedny człowiek pilnujący procesu uczenia stwierdzi, że 80-90% wyników się zgadza. W takiej sytuacji zbiór danych wykorzystywany do walidacji dawać może podobne wyniki – szczególnie jeśli jest to część jednego zbioru np. 10%, albo są to dane pozyskane w ten sam sposób, ale z innego miesiąca (tu uwaga na pory roku, pogodę itd.). Dopiero w praktyce zauważymy, że nasz pojazd po prostu nie skręca w ogóle!
Poświęć 90% uwagi na przygotowanie danych, a nie modeli i architektur!

W wielu problemach istnieją już architektury, które dają dobre wyniki i to od nich warto zacząć. W przypadku rozwiązania End to End dla problemu prowadzenia samochodu autonomicznego mamy tu artykuł Nvidii (artykuł znajdziesz na dole w linkach, tu dam wpis z bloga, bo to przystępniejsza forma):
W ramach PLinML 2018 prowadziłem całodniowy warsztat (4x 1.5h, kto był ten wie co to znaczy; serdecznie Was pozdrawiam!) na temat zastosowania głębokich sieci neuronowych, głębokiego uczenia w samochodach autonomicznych. Postanowiłem zrealizować 4 tematy:
Było to ambitne założenie, ale uważam, że to wyszło całkiem dobrze. Przy następnym warsztacie zapewne zmienię koncepcję, zobaczymy.

Tutaj skupimy się na pierwszym z tematów.
Wejdź tu: http://bit.ly/PLinML18_EndToEnd. Wykonaj kopię i możesz działać!
W ramach ćwiczenia wykorzystamy symulator opracowany przez Udacity, wykorzystywany przez nich w kursie Udacity Self-Driving Car Engineer Nanodegree. Symulator może pobrać tutaj:
https://github.com/karolmajek/self-driving-car-sim
Możesz pracować na Windowsie, Linuxie czy iOS, symulator jest dostępny na każdą platformę. Pobierz proszę z Available Game Builds (Precompiled builds of the simulator) Version 2, 2/07/17 wersję odpowiednią dla Twojego systemu operacyjnego.
Uruchamiając symulator ustaw detale i rozdzielczość na minimum, chyba że dysponujesz kartą graficzną. Prędkość symulacji wpływa na osiągane wyniki, warto o tym pamiętać. Prędkość działania naszej sieci neuronowej również ma wpływ na osiągane wyniki.
Aby uruchomić symulator na nieWindowsie – ustaw atrybut wykonywalności dla pliku z symulatorem (piszę tu o wersji 64bitów bo raczej masz 64bitowy system operacyjny):
chmod +x beta_simulator.x86_64
Następnie możemy uruchomić symulator poprzez
./beta_simulator.x86_64
Na Windowsie to klasycznie – po prostu klikamy dwukrotnie.

Nagrywając dane polecam używać joystick (ja osobiście używam joysticka USB od XBOXa – działa na Ubuntu 16.04) z uwagi na to, że możemy uzystkiwać sterowania nie tylko binarne (max lewo, środek, max prawo) jak w przypadku klawiatury, ale wiele wartości między -1, a 1.
Nie musisz nagrywać danych, nagrałem jedno okrążenie na warsztat, ale jeżeli chcesz osiągnąć naprawdę dobre wyniki, przydadzą Ci się dodatkowe dane.
Po przejściu kilku komórek związanych z pobraniem zbioru danych na maszynę w Google Colab, możesz zobaczyć film z danymi wejściowymi oraz przykładowy obraz jak poniżej.

Obraz jest dość duży i zawiera nadmiarowe informacje – pixele u góry i dołu można usunąć bez negatywnych konsekwencji. Zmniejszymy też szerokość i wysokość by nasz model był kompatkowy. Możemy sobie na to pozwolić, gdyż pracujemy z danymi z symulatora.
Wykorzystamy poniższy kod który:
def process_image(image):
image=image[10:130:4,::2,:]
image=np.mean(image,axis=2)
image=(image-image.min())/255.0-0.5
image=image.reshape(image.shape[0],image.shape[1],1)
return image

Przez to że zmniejszyliśmy zdjęcia, nie możemy wykorzystać oryginalnego modelu od Nvidia’i, ale możemy stworzyć podobny model, nieco uproszczony. Poniżej prezentuję opis modelu pochcodzący z biblioteki Keras – funkcja model.summary().
Image shape before processing: (160, 320, 3)
Image shape after processing: (30, 160, 1)
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 28, 158, 64) 640
activation_1 (Activation) (None, 28, 158, 64) 0
conv2d_2 (Conv2D) (None, 26, 156, 32) 18464
activation_2 (Activation) (None, 26, 156, 32) 0
conv2d_3 (Conv2D) (None, 24, 154, 16) 4624
activation_3 (Activation) (None, 24, 154, 16) 0
conv2d_4 (Conv2D) (None, 22, 152, 8) 1160
activation_4 (Activation) (None, 22, 152, 8) 0
max_pooling2d_1 (MaxPooling2 (None, 11, 76, 8) 0
dropout_1 (Dropout) (None, 11, 76, 8) 0
-------------------------------------------------------------
flatten_1 (Flatten) (None, 6688) 0
-------------------------------------------------------------
dense_1 (Dense) (None, 16) 107024
activation_5 (Activation) (None, 16) 0
dense_2 (Dense) (None, 16) 272
activation_6 (Activation) (None, 16) 0
dense_3 (Dense) (None, 16) 272
activation_7 (Activation) (None, 16) 0
dropout_2 (Dropout) (None, 16) 0
dense_4 (Dense) (None, 1) 17
=================================================================
Total params: 132,473
Trainable params: 132,473
Non-trainable params: 0
Teraz właściwe uczenie. Nie trwa to długo z uwagi na wielkość problemu i to że wykorzystujemy kartę graficzną – tak, mamy za darmo możliwość wykorzystywania kart graficznych w Google Colab!

Nauczony model możemy pobrać i uruchomić, tak by samochód w symulatorze sam zaczął jeździć! Wystarczy pobrać wytrenowany model i ściągnąć kod http://bit.ly/drive_py. Aby uruchomić kod włączamy sumulator w trybie Autonomous i uruchamiamy drive.py z modelem:
python drive.py model.h5
Ten model nie powinien Cię zachwycić, przejedzie kilka metrów, chyba że mu pomożesz, wtedy i na górkę wjedzie! Powinniśmy zwiększyć rozmiar naszego zbioru trenującego. Jeździmy czy generujemy dane? (10 sekund na zastanowienie)
Możemy wykonać proste przekształcenia aby zwiększyć liczbę danych. Ten tutorial pokrywa tylko pogrubione metody:


Mając generator danych do trenowania możemy wreszcie wytrenować kolejny model i sprawdzić jak sobie poradzi.
Tu zostawiam miejsce by wkleić Twoje wyniki – kod na Githubie/Colabie i/oraz film na Youtube z samochodem przejeżdżającym pełne okrążenie. Zgłoś się przez formularz kontaktowy.
Jeśli coś jest niejasne, albo wprost nie działa – pisz do mnie przez formularz kontaktowy, postaram się pomóc. Wybacz, że ten wpis nie jest super obszerny
Dodaj komentarz