Sztuczna inteligencja w Unity. Stworzyłem wirtualne stwory i dałem się im zaskoczyć

Zapewne znacie powiedzenie, że matematyka to królowa nauk. Jednak czy wiecie, że matematyka to również podstawa pewnego odłamu sztucznej inteligencji? Odłamu o mistycznej wręcz nazwie, bo określa się ją przecież mianem “sieci neuronowej”. Tak się jednak składa, że skrywa ona w sobie ogromny potencjał. 
Sztuczna inteligencja w Unity. Stworzyłem wirtualne stwory i dałem się im zaskoczyć

Sztuczna inteligencja i sieć neuronowa

Sztuczna inteligencja to jeden z tych tematów, które zwłaszcza w ostatnim czasie regularnie trafiają w światła reflektorów. Nie bez powodu, bo dziś często mówi się o tym, że może zmienić nasze życie na lepsze. Dlatego postanowiłem zgłębić temat jednej z nich w praktyce i sprawdzić, czy jej zastosowanie w Unity jest możliwe do czegoś nieco bardziej skomplikowanego, bo czegoś, co ma wpływ na wirtualne środowisko. Zanim jednak wejdziemy w szczegóły samej sieci oraz implementacji, warto podkreślić, że sieć neuronowa jest jednym z odłamów, a raczej narzędzi, które są wykorzystywane przy rozwoju sztucznej inteligencji, czyli systemów o zdolnościach naśladujących inteligencję ludzką.

Czytaj też: Izrael zapoczątkował koszmar. Sztuczna inteligencja w wojsku zaczęła wskazywać, kogo trzeba zabić

Zwykle na tym kończą się wszelkie wyjaśnienia tego, czym jest sieć neuronowa – ot, jeden z rodzajów sztucznej inteligencji, do których zaliczyć możemy też m.in. uczenie maszynowe czy algorytmy genetyczne. Co jednak dokładnie siedzi pod jej maską i sprawia, że wykorzystujący ją system, możemy uznać za “inteligentny”? Odpowiedź na to pytanie może was zaskoczyć, bo sprowadza się właśnie do matematyki, która umożliwia działanie temu “sztucznemu” systemowi nerwowemu.

Neurony, synapsy i warstwy – oto sieć neuronowa w skrócie

Na poniższych diagramach widać, czym – w dużym uproszczeniu – jest sieć neuronowa. To bowiem nic innego, jak zestaw ustrukturyzowanych wartości, które wspólnie budują trzy podstawowe rodzaje tak zwanych warstw (layers), bo warstwę wejść (input layer), dowolną liczbę warstw ukrytych (hidden layer) oraz finalną warstwę wyjściową (output layer). 

Wszystkie warstwy ukryte są połączone z warstwą poprzednią i łączą się z kolejną za pośrednictwem tak zwanych synaps, podczas gdy warstwa wejściowa łączy się tylko z pierwszą warstwą ukrytą, a warstwa wyjściowa już z tą ostatnią warstwą ukrytą. Mówi nam to tyle, że w całej sieci neuronowej wszystkie warstwy są w pewnym stopniu (pośrednio lub bezpośrednio) ze sobą połączone.

Za każdym razem, kiedy uzyskujecie odpowiedź od systemu z siecią neuronową, ten bierze uzyskane od was dane wejściowe, wstawia je do swojej pierwszej warstwy, procesuje przez kolejne i finalnie “wypluwa” w ostatniej. Tutaj właśnie do gry wchodzi matematyka. Cały ten proces “przetwarzania” angażuje bowiem przypisane każdej warstwie (z wyjątkiem warstwy wejściowej) węzły, zwane też mianem neuronów, występujące w nich w całkowicie dowolnej liczbie, ale zwykle dobrze dopasowanej do konkretnego zastosowania, co tyczy się też liczby warstw ukrytych. 

Każdy neuron obecny w warstwach w ukrytych i warstwie wyjściowej ma przypisane do siebie dwie wartości numeryczne. Mowa o wagach, czyli sile połączenia węzła z innym węzłem (inaczej synapsach) oraz poziomie skłonności, zwanym najczęściej mianem bias i odpowiadającym za określenie, jak “ważny” jest dany neuron w całej sieci. To podstawa, umożliwiająca działanie całej sieci neuronowej, jako że każdy węzeł warstwy poprzedniej łączy się ze wszystkimi węzłami warstwy następnej za pośrednictwem synaps o różnych wagach numerycznych.

Dzięki temu sieć może operować na surowych liczbach (danych), obliczając wartości dla kolejnych neuronów za pomocą prostego wzoru. Każde obliczenie obejmuje bowiem zsumowanie iloczynu wartości wejściowej i wagi synapsy oraz dodanie do wyniku sumy poziomu skłonności (bias), co następuje od warstwy wejściowej i surowych danych aż po warstwę wyjściową.

Przykładowo, mając prostą sieć neuronową o układzie 2, 3, 1, wprowadzamy do systemu dwie wartości numeryczne, następnie każdą z nich mnożymy przez wartość połączenia z neuronem w warstwie ukrytej, a do obliczonej wartości dodajemy jego poziom skłonności i tak uzyskaną wartość traktujemy jako wejście do kolejnego, tym razem ostatniego neuronu, zapewniającego nam wartość wyjściową. Z powyższego układu wynik wynosiłby 7,125, ale tylko teoretycznie, bo w tych obliczeniach pominąłem etap, nadający sieci neuronowej rzeczywistą użyteczność.

Sieć neuronowa to coś więcej niż tylko szereg prostych funkcji matematycznych, przez które przepuszcza się dane wejściowe. Zawdzięcza to tak zwanej funkcji aktywacyjnej, która zapewnia jej możliwość przetwarzania i tym samym “uczenia się” danych. Nie komplikuje to jednak zbytnio procesu obliczania, bo polega na modyfikacji uzyskanej wartości węzła zależnie od tego, jaką funkcję się wykorzysta. Jako że jest ich wiele, to powinniście wiedzieć przede wszystkim o funkcji ReLU, którą uznaje się za tą najbardziej wszechstronną i optymalną, jako że jedyne, co robi, to zwraca albo otrzymaną wartość, jeśli ta jest dodatnia, lub 0, jeśli jest ujemna.

Czytaj też: Tak wyglądał świat po II wojnie światowej. Sztuczna inteligencja stworzyła niesamowite rekonstrukcje

Jej zastosowanie na powyższym przykładzie sprawia, że finalny wynik wynosi nie 7,125, a 11,25, a stosuje się ją przede wszystkim po to, aby na etapie obliczeń wskazać, czy neuron jest aktywny i jeśli tak, to z jak wielką “mocą” (w przypadku nieliniowych funkcji aktywacyjnych), która sprowadza się do wynikowej wartości liczbowej przekazywanej do kolejnych warstw. Funkcja aktywacyjna wpływa więc bezpośrednio na działanie sieci neuronowej, określając jej szybkość oraz jakość uczenia się poprzez określanie kształtu i własności funkcji błędu, czyli czegoś, co ma za zadanie zminimalizować.

Taka struktura sieci neuronowej sprawia, że proces jej szkolenia obejmuje nic innego, jak wyszukiwanie odpowiedniej konfiguracji wartości synaps oraz bias, aby po wprowadzeniu do sieci danych wartości numerycznych, otrzymać oczekiwany, możliwie najbliższy prawdy wynik. Dlatego też im bardziej skomplikowane jest dane zadanie, tym więcej ukrytych warstw i węzłów potrzebuje.

Sieć neuronowa w Unity, czyli jak nauczyć NPC poruszania się po mapie

Wiedząc już to, czym dokładnie jest sieć neuronowa, możemy wykorzystać ją w praktyce i to nawet w dosyć “efektowny” sposób, bo nie z wykorzystaniem prostego zbioru danych, a wirtualnego środowiska. Tak też w prosty sposób można wykorzystać silnik Unity do stworzenia toru przeszkód w środowisku 2D lub 3D, wprawić w ruch agentów z czujnikami, które będą mierzyć odległości od przeszkód, nagradzać ich za przetrwanie możliwie najdłużej i tworzyć ich następców za każdym razem z nieco zmienionymi genotypami, kiedy tylko trafią w przeszkodę. Dzięki zmianom wartości wag oraz bias, agenci sterowani siecią neuronową będą reagować na otoczenie w odmiennym stopniu zależnie od swojej pozycji względem przeszkód w dążeniu do całkowitego unikania kolizji.

Przykład działania czegoś takiego w środowisku Unity możecie obejrzeć powyżej. Ustawienie wszystkiego nie jest może kwestią kilku minut, jako że system musi sterować poruszającymi się w tym samym tempie agentami i określać ich wpływ na środowisko oraz siebie nawzajem, a proces szkolenia wymaga np. zastosowania algorytmu genetycznego do faworyzowania najlepszych agentów. Jednak to i tak niewiele, jeśli chcecie stworzyć swój własny system sztucznej inteligencji, który będzie mógł was nawet zaskoczyć, tak jak niektórzy agenci w zaskoczyli też mnie, kiedy zamiast poruszać się zgodnie ze wskazówkami zegara, zaczęli zawracać.

Czytaj też: Apple o czymś zapomniał. Sztuczna inteligencja zdaje się nie istnieć w Cupertino

Nie oznacza to jednak, że w ten oto sposób zachowują się postaci w grach wideo. W rzeczywistości sieci neuronowe nie są praktycznie w ogóle stosowane w grach, bo są zwyczajnie zbyt obciążające i nieprzewidywalne, żeby zrobić z nich użytek w znakomitej większości mechanik. Do osiągnięcia tego, co widzicie powyżej, można równie dobrze wykorzystać niewidzialne dla gracza punkty, między którymi postać poruszałaby się, generując tym samym znacznie mniejsze obciążenie po stronie komponentów komputera. Jak więc deweloperzy tworzą zachowania postaci w grach i dlaczego jest to tak trudne? To już temat na zupełnie inny artykuł, ale jeśli temat was ciekawi, to zaglądajcie do nas częściej, bo już teraz nad nim pracuje, projektując systemy dla gry, która robi użytek właśnie ze sztucznej inteligencji, będącej jej główną mechaniką.

PS – po więcej materiałów najwyższej jakości zapraszamy na Focus Technologie. Subskrybuj nasz nowy kanał na YouTubie!