Kolejny problem z OpenAI Classic control Gym, który został opisany po raz pierwszy w 1990 roku w pracy doktorskiej Pana Andrew Moore’a ( https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-209.pdf). Startujemy z wagonikiem w głębokim dole, możemy nim poruszać w lewo lub w prawo ale nie dysponujemy wystarczającą mocą, by siłą napędu własnego wydostać się z pułapki. A właśnie dotarcie do flagi na szczycie prawego zbocza, jest naszym celem kończącym zadanie.Tak więc, żeby dotrzeć do naszego celu musimy wagonik rozbujać i wykorzystać potencjał grawitacji do skumulowania energii naszych słabych popchnięć wagonika. Utrudnieniem jest to, że nie dostajemy za nasze działania nagrody natychmiastowej, a jesteśmy karani (-1) za każdy krok czasowy jaki pozostajemy w grze (maksymalnie -200). Jedynie stan kończący zadanie, jest stanem za który otrzymujemy nagrodę. Dlatego dopóki choć raz nie osiągniemy celu, nie możemy się dowiedzieć czy nasze działania są prawidłowe i nadają się do nauki i powtarzania. Pierwszy pomysł, żeby losowo poruszać wagonikiem i poczekać na taką udaną próbę, na której można by później oprzeć dalsze strategie postępowania, skończyły się na 10k bezskutecznych powtórzeniach. Drugi pomysł by podzielić losowo przestrzeń stanów środowiska na obszary dla każdej z możliwej akcji okazał się bardziej skuteczny.
Tu należy opisać dokładniej samo środowisko. Stan środowiska definiuje wektor o dwóch składowych: prędkość <-0.07, 0.07> i położenie <-1.2,0.6>. Przestrzeń możliwych akcji to przestrzeń dyskretna o trzech wartościach: 0 – pchnij w lewo, 1 – nic nie rób, 2 -pchnij w prawo. Pomysł jest taki żeby płaszczyznę stanu środowiska podzielić losową prostą na dwie części. Stanom z jednej strony przypisać pchnięcie w lewo a stanom z drugiej pchnięcie w prawo. Punktom na prostej i jej pewnym otoczeniu brak działania. Nie jestem przekonany czy takie podejście do problemu nie powoduje, że pewne wiedza i intuicja programisty zostaje przekazana do agenta. Nie szukałem w Internecie rozwiązań tego problemu, a to jest jedyne co na chwilę obecną udało mi się wymyślić. Przy takim losowym podziale przestrzeni stanów, po około 2500 wykonanych próbach mamy 50 zakończonych sukcesem, po maksymalnie 190 krokach. Ta „szczęśliwa pięćdziesiątka” udanych może nam posłużyć za bazę do nauczenia naszej sieci własnej polityki zachowań. Wystarczy te 50 prób kilka razy „przepuścić” przez naszą sieć neuronową aby uzyskać dość skutecznie działająca politykę. Przed każdym powtórzeniem uczenia sieci do danych wejściowych dodawany jest pewien losowy szum, nie przekraczający przyjętej do obliczeń rozdzielczości środowiska (dS).
Całość kodu można pobrać z mojego repo GitHub https://github.com/majchernet/RL_MountainCar . Powoli docieram do momentu gdzie napisanie kodu robi się mniej pracochłonne niż jego późniejsze, nawet tak lakoniczne opisanie, więc na razie pozwolę sobie zakończyć ten wpis.
Poniżej przykłady polityk, z losowym liniowym podziałem przestrzeni stanów, które dały sukces:
Po nauczeniu sieci neuronowej danymi z losowym podziałem uzyskujemy skuteczne polityki jak poniżej:
Proces uczenia w kolejnych krokach może wyglądać następująco:
Wyjście naszej sieci neuronowej ma 3 wartości, dlatego bardzo prosto możemy też zrobić wizualizację polityki w kolorze (RGB). Polityka w po kolejnych iteracjach uczenia sieci:
Program w działaniu: