Inteligencja obliczeniowa Laboratorium 9: Sieci neuronowe. Na dzisiejszych laboratoriach poznamy kolejny algorytm inspirowany biologicznie (wcześniej mieliśmy algorytmy genetyczne), który pozwoli na klasyfikowanie rekordów, ale jest też stosowany do szacunków, obliczeń, przewidywań. Są to (sztuczne) sieci neuronowe, które przypominają nieco graf, a nieco również sieć neuronów w naszych mózgach. Zadanie 1 Zapoznamy się z działaniem sieci neuronowej na prostym przykładzie. Mamy małą bazę danych ludzi, których zachęcaliśmy do gry w siatkówkę na plaży (a przy okazji popytaliśmy o parametry ich organizmu). Część ludzi zgodziła się zagrać, a część nie. Korzystając z R stworzyliśmy sieć neuronową o następującej strukturze: Sieć neuronowa, niczym mały sztuczny mózg, miała nauczyć się rozpoznawać, które osoby będą
chciały grać w siatkówkę. Sprawdziliśmy jak sieć poradziła sobie z naszymi siedmioma osobami. Otrzymaliśmy wynik : Widać, że gdyby zaokrąglić wartości do 1 (TRUE) i 0 (FALSE) to nasza sieć wypadła całkiem nieźle. Nie zgadła jedynie rekordu 6. Pytanie: jak obliczone zostały powyższe wartości? Sieć neuronowa dostaje trzy dane na wejściu. Wartości liczbowe są mnożone przez wagi na strzałkach i przekazywane kolejnym neuronom, które sumują wszystko co dostają. Dodane są też do tego wartości dodatkowe (bias) zaznaczone na niebiesko. Zsumowane wartości przepuszczone są przez funkcję aktywacji (fct.act) wynoszącą w tym przypadku fct.act(x)= 1/(1+exp(-x)), po czym neuron przesyła je dalej. Napisz prostą funkcję, która sprawdzi czy sieć działa dobrze tj. funkcja na input dostanie wiek, wagę, wzrost, a na output zwróci liczbę przewidującą granie w siatkówkę. Wagi z sieci pobierz z rysunku w tym pdf. forwardpass <- function(wiek,waga,wzrost){ hidden1 <- hidden2 <- output <- return(output) Sprawdź jej działanie dla dwóch wybranych przez ciebie rekordów np. forwardpass(23,75,176) = 0.798528 W razie problemów zachęcam do skorzystania z Google / Youtube (wyszukanie: sieć neuronowa, perceptron, neural network) lub z wykładów. Zadanie 2 Do tworzenia sieci neuronowej w R wykorzystamy paczkę neuralnet (proszę zainstalować). Kilka linków o niej: https://hub.packtpub.com/training-and-visualizing-a-neural-network-with-r/ (iris) https://www.r-bloggers.com/fitting-a-neural-network-in-r-neuralnet-package/ https://www.analyticsvidhya.com/blog/2017/09/creating-visualizing-neural-network-in-r/ Dokonamy klasyfikacji irysów za pomocą sieci neuronowej. a) Znormalizuj kolumny liczbowe bazy danych irysów, wzorem (x-min(x))/(max(x)-min(x)) i zapisz zmienioną bazę jako iris.norm. Możesz ten wzór zapisać jako funkcję i zaaplikować ją komendą lapply na 4 kolumny numeryczne irysów.
b) Rozbij kolumnę Species na kolumnę: setosa, versicolor, virginica. Łącznie będzie w bazie 8 kolumn, 4 numeryczne, 1 kategorialna (tekst) i 3 logiczne. W kolumnie setosa będą wartości 0 (dany irys nie jest setosą) i 1 (dany irys jest setosą). Podobnie będą działały pozostałe kolumny z gatunkami. iris.norm$setosa = iris.norm$species == "setosa" c) Podziel zbiór irysów z punktu b) na iris.train, iris.test tak, jak robiliśmy to przy innych algorytmach klasyfikujących. Proporcje mogą być 67/33. d) Zainstaluj i załaduj paczkę neuralnet. Uruchom komendę neuralnet na zbiorze treningowym. Wszystkie trzy kolumny logiczne będą brane pod uwagę jako klasa. Należy uwzględnić je uruchamiając sieć neuronową: Iris.net <- neuralnet(setosa + versicolor + virginica ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width,... Wówczas sieć neuronowa będzie miała trzy neurony wyjściowe. d) Zewaluuj klasyfikator uruchamiając komendę compute na zbiorze testowym. iris_predictions <- compute(iris.net, iris.test[, 1:4]) W wyniku funkcji compute na danych numerycznych ze zbioru testowego dostaniemy 3 kolumny numeryczne, które powinny odpowiadać kolumną binarnym setosa/versicolor/virginica. Z tych trzech kolumn wybieramy największą wartość i zapisujemy jaki irys jest przez nią wskazywany. Przykład: -0.056 0.866 0.001 versicolor (0.866 jest największe, najbliżej 1 czyli TRUE) Porównujemy obliczone gatunki z prawdziwymi ze zbioru testowego. Przydatna będzie tutaj funkcja max.col. Jak ją zastosować? Podaj macierz błędu i dokładność klasyfikatora.
Zadanie 3 Sieci neuronowe nie tylko mogą klasyfikować rekordy, ale też sterować obiektami. Wówczas na wyjściu muszą dawać 1 jeśli chcą akcję wykonać, lub 0 gdy nie chcą jej wykonać. Na stronie https://inf.ug.edu.pl/~gmadejsk/tanks/tanks.html znajduje się prosta gra w strzelające czołgi. Czołgami można sterować z klawiatury lub za pomocą skryptu, wówczas należy go wkleić do okienka na kod (dwa proste skrypty typu jedź na przód i strzelaj są domyślnie wklejone do okien). Chcemy napisać skrypt symulujący sieć neuronową, która będzie jedynie sterowała naszym czołgiem. Na wejściu dostaje jego podstawowe parametry (współrzędne i kąt rotacji), na wyjściu ma odpowiedzieć jaką akcję wykonać: skręć w lewo, skręć w prawo, jedź na przód i jedź do tyłu (ustawiając wartości 1 jeśli chcemy wykonać akcję i 0 jeśli nie chcemy). Do zajęć został załączony plik z kodem takiego skryptu: neural-bot.js. Przestudiuj jego działanie. Niestety wszystkie wagi (weights1, bias1, weights2, bias2) zostały twardo ustawione na 0. a) Metodą eksperymentów pozmieniaj niektóre z nich na liczby z przedziału [-1,1], tak aby czołg jechał na przód. b) Spróbuj ustawić je tak, aby czołg kręcił się w kółko. c) * (Nieobowiązkowo) Zamiast szukać interesujących wag wykorzystaj przeglądarkowe Console, by pozyskać interesujące cię dane i wytrenować sieć.
function(e) { var response = {; var enemy = e.data.enemytank; var me = e.data.mytank; /*Simple neural network*/ /*we want our tank only to move around the field*/ /*let's take input layer with 3 neurons - extracted from game data*/ var input = [me.x, me.y, me.rotation]; /*is it a good idea to normalize the inputs here?*/ input = [me.x/500.0, me.y/500.0, (me.rotation%360)/360.0]; console.log("neunet input: "+input[0]+", "+input[1]+", "+input[2]); /*we take 3 hidden neurons*/ /*from every input neuron there is a connection to every hidden neuron (3 connections), so we need 9 weights; and 3 for bias*/ var weights1 = [0,0,0,0,0,0,0,0,0]; var bias1 = [0,0,0]; /*we compute the output values for hidden neurons*/ var hidden = [0,0,0]; var i,j; for (i=0; i<3; i++){ for (j=0; j<3; j++){ hidden[i] = input[j]*weights1[i*3+j]; hidden[i] = hidden[i]+bias1[i]; hidden[i] = 1/(1+Math.pow(Math.E, -hidden[i])); console.log("neunet hidden: "+hidden[0]+", "+hidden[1]+", "+hidden[2]); /*we consider 4 outputs each corresponding to a control-key: turnleft, turnright, goforward, goback - so we need 3*4=12 additional weights + 4 bias*/ var weights2 = [0,0,0,0,0,0,0,0,0,0,0,0]; var bias2 = [0,0,0,0]; /*we compute the output values for the network*/ var output = [0,0,0,0]; for (i=0; i<4; i++){ for (j=0; j<3; j++){ output[i] = hidden[j]*weights2[i*3+j]; output[i] = output[i]+bias2[i]; output[i] = 1/(1+Math.pow(Math.E, -output[i])); output[i] = Math.round(output[i]); console.log("neunet output: "+output[0]+", "+output[1]+", "+output[2]+", "+output[3]); /*we return the values*/ response.turnleft = output[0];
response.turnright = output[1]; response.goforward = output[2]; response.goback = output[3]; self.postmessage(response);