Narzędzia sztucznej inteligencji - laboratorium |
Gabriel Kachel Adam Czech |
rok III INF I st., gr. 6 środa, godz. 14.40 |
Ćwiczenie 1: Zastosowanie warstwy perceptronowej w zadaniu klasyfikacji - rozpoznawanie znaków |
||
Ćwiczenie wykonano w dniach: 05.03, 12.03, 26.03 oraz 02.04.2014 |
Sprawozdanie oddano dnia: 09.04.2014 |
ocena: |
1. Cel i zakres ćwiczenia
Celem ćwiczenia jest zastosowanie sieci neuronowej, złożonej z pojedynczej warstwy perceptronów, czyli neuronów o progowej funkcji aktywacji, w zadaniu klasyfikacji (rozpoznawaniu) wzorców w postaci map bitowych, zawierających obraz wybranych liter alfabetu[1]. W przypadku naszej grupy są to litery : E,F,G,H.
2. Wstęp teoretyczny
Rys. 1. Budowa perceptronu [2]
Perceptron może służyć jako układ klasyfikujący lub podejmujący decyzje.
Obszar, w którym perceptron ( z funkcją niesymetryczną) ma na wyjściu wartość 1 (tzn. podejmuje decyzję „tak”), jest oddzielony od obszaru w którym na jego wyjściu pojawia się 0 („nie”) tworem o równaniu:
Rys. 2. Wykres granicy decyzyjnej [2]
W ćwiczeniu wykorzystana została struktura sieci neuronowej
Rys. 3. Ogólny schemat sieci neuronowej [3]
Metoda zastosowana do znalezienia odpowiednich współczynników wagowych to metoda uczenia (treningu).
Metoda ta polega na „dostrajaniu ” współczynników wagowych neuronu z wykorzystaniem danych uczących, modyfikując je po prezentacji każdego wzorca, zgodnie z tzw. regułą perceptronową:
Wykres poniżej przedstawia schemat uczenia się perceptronu
Rys. 4. Schemat uczenia się perceptronu
Reguła perceptronowa dotyczy nauki z nauczycielem i odnosi się do sieci z neuronami dyskretnymi. Sygnałem uczącym jest popełniany błąd:
r = di - yi
gdzie
r - sygnał uczący
di - oczekiwana odpowiedź i-tego neuronu
yi - odpowiedź i=tego neuronu
Korekcja wag odbywa się według zależności:
Δwi = c[di - sgn(wit x)]x
gdzie
wi - wektor wag i-tego neuron
c - stała uczenia
di - oczekiwana odpowiedź i-tego neuronu
x- wektor wejściowy
Wartości początkowe wag powinny być losowe
3. Przebieg ćwiczenia
W pierwszym etapie ćwiczenia definiujemy macierze 8x6 z przydzielonymi nam literami
Macierz wypełniamy wartościami „1” jeżeli piksel aktywny i „0” jeżeli nieaktywny.
Macierz dla litery „E”
A=[0,0,0,0,0,0,
0,1,1,1,1,0,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,1,1,1,0,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,1,1,1,0]
Macierz dla litery „F”
B=[0,0,0,0,0,0,
0,1,1,1,1,0,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,1,1,1,0,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,0,0,0,0]
Macierz dla litery „G”
C=[0,0,0,0,0,0,
0,0,1,1,1,1,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,0,1,1,1,
0,1,0,0,0,1,
0,1,0,0,0,1,
0,0,1,1,1,1]
Macierz dla litery „H”
D=[0,0,0,0,0,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,1,1,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0]
Kolejnym krokiem jest wizualizacja na ekranie naszych liter:
figure (1)
hintonw(A)
figure (2)
hintonw(B)
figure (3)
hintonw(C)
figure (4)
hintonw(D)
Rys. 5. Wizualizacja liter
Następnie potrzebna nam będzie zmiana macierzy z wymiarów 8x6 na 48x1oraz wrzucenie ich do macierzy P. Wykonujemy to poleceniem :
kA=reshape(A,48,1)
kB=reshape(B,48,1)
kC=reshape(C,48,1)
kD=reshape(D,48,1)
P=[kA,kB,kC,kD]
W wyniku czego otrzymujemy:
Tab. 1. Ukazująca wynik wykonanego polecenia
kA = 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0
|
kB = 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 |
kC = 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 1 |
kD = 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 |
Macierz P po wykonaniu polecenia:
P =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
1 1 0 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 0 1
0 0 0 0
1 1 1 0
0 0 0 0
0 0 0 0
1 1 0 1
0 0 0 0
0 0 0 0
1 0 1 0
0 0 0 0
1 1 1 0
0 0 0 0
0 0 0 0
1 1 1 1
0 0 0 0
0 0 0 0
1 0 1 0
0 0 0 0
1 1 1 1
0 0 0 1
0 0 0 1
1 1 1 1
0 0 0 1
0 0 0 1
1 0 1 1
0 0 0 0
0 0 1 0
0 0 0 0
0 0 0 0
0 0 1 0
0 0 1 0
0 0 1 0
0 0 1 0
W kolejnym etapie zdefiniowaliśmy macierz T, będącą macierzą wzorców wyjściowych, zawierającą poprawne odpowiedzi sieci na kolejne wzorce wejściowe.
W tym celu należało założyć, że każdy neuron warstwy odpowiadać będzie za jeden znak. Wartość „1” na wyjściu tego neuronu będzie oznaczała, że „rozpoznaje” on swoją literę na wejściu. Pozostałe neurony miały w tym czasie na swoich wyjściach wartości „0” .
Do wykonania powyższych czynności wykorzystane zostało polecenie „eye” generujące macierz jednostkową:
T=eye(4)
Następnie utworzyliśmy warstwę perceptronów o odpowiedniej strukturze, wykorzystując funkcję newp:
net=newp(P,T,'hardlim','learnp')
Kolejną czynnością było dopisanie do skryptu instrukcji, które po inicjalizacji wyświetlały rozmiary i zawartość macierzy współczynników wagowych oraz wektora współczynników progowych.
disp('Rozmiary macierzy wag: ')
disp(net.IW)
disp('Zawartosc macierzy wag:')
disp(net.IW{1})
disp('Rozmiar wektora wsp. progowych: ')
disp(net.b)
disp('Zawartosc wektora wsp progowych: ')
disp(net.b{1})
Które wyglądały następująco:
Rozmiary macierzy wag:
[4x48 double]
Zawartosc macierzy wag:
Columns 1 through 12
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
Columns 13 through 24
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
Columns 25 through 36
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
Columns 37 through 48
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
Rozmiar wektora wsp. progowych:
[4x1 double]
Zawartosc wektora wsp progowych:
0
0
0
0
W następnym etapie przeprowadziliśmy uczenie sieci (przy pomocy funkcji train) z wykorzystaniem przygotowanych wcześniej wzorców uczących.
net=train(net,P,T)
Rys. 6. Wykres funkcji uczącej TRAIN
Następnie przeprowadziliśmy weryfikację działania sieci podając na jej wejścia wzorce wejściowe. Wynik działania sieci należało przypisać zmiennej Y, a następnie porównać odpowiedzi sieci na kolejne wzorce wejściowe z odpowiedziami wzorcowymi.
Y=sim(net,P)
W kolejnym etapie przeprowadziliśmy wizualizację działania sieci. Po lewej stronie okna graficznego miał wyświetlać się obraz litery podawanej na wejście sieci, a po prawej stronie - odpowiedź sieci na ten obraz.
figure(5)
for i=1:4
subplot(1,2,1)
hintonw(reshape(P(:,i),8,6))
subplot(1,2,2)
hintonw(Y(:,i))
pause()
end
W odpowiedzi otrzymaliśmy takie oto wyniki:
Rys. 7. Odpowiedzi sieci perceptronowej
Lewa strona każdej z wizualizacji przedstawiała odpowiednio zdefiniowane wcześniej mapy bitowe, natomiast prawa - odpowiedzi naszej sieci perceptronowej wskazujące do której ze stworzonych wcześniej macierzy należy badany znak.
Kolejnym bardzo istotnym w ćwiczeniu jego elementem było sprawdzenie - jak nasza sieć radziła sobie z rozpoznawaniem zakłóconych obrazów.
W tym celu skopiowano definicje macierzy z obrazami wzorcowymi, by wprowadzić do nich `zakłócenia'. Polegało to na zastąpieniu wartości wybranego piksela na odwrotną - to znaczy zamianie „1” w macierzy reprezentującej dany znak na ”0” i/lub odwrotnie -zastąpieniu „0” na „1”.
AA=[1,0,0,1,0,1,
0,1,1,1,1,0,
0,0,0,0,0,1,
1,0,0,0,1,0,
0,1,0,1,1,0,
0,0,1,1,1,0,
0,1,0,1,0,1,
0,0,0,1,1,0]
BB=[0,0,0,0,0,0,
0,1,1,1,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,1,1,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0]
CC=[0,0,0,0,0,0,
0,0,1,1,1,1,
0,1,0,0,0,0,
0,1,0,0,0,0,
0,1,0,1,1,1,
0,1,0,0,0,1,
0,1,0,0,0,1,
0,0,1,1,1,1]
DD=[0,0,0,0,0,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,1,1,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0,
0,1,0,0,1,0]
kAA=reshape(AA,48,1)
kBB=reshape(BB,48,1)
kCC=reshape(CC,48,1)
kDD=reshape(DD,48,1)
PP=[kAA,kBB,kCC,kDD]
YY=sim(net,PP)
figure(6)
for i=1:4
subplot(1,2,1)
hintonw(reshape(PP(:,i),8,6))
subplot(1,2,2)
hintonw(YY(:,i))
pause()
end
W wyniku tym otrzymaliśmy obrazy zakłócone np. literę uprzednio czytaną jako „E” sieć rozpoznaje teraz jako „G”, zaś literę „F” jako „H”. Dla porównania litery „G” i „H” zostały w pierwotnej postaci.
Litera „E”:
Litera „F”
Litera „G”:
Litera „H”:
4. Uwagi i wnioski
Ćwiczenie polegające na nauczeniu sieci perceprtonowej rozpoznawania liter oraz sprawdzenie czy sieć zdolna jest do poznania nauczonych wcześniej liter po ich zniekształceniu, wykonaliśmy zgodnie z podpowiedziami umieszczonymi w skrypcie nr 289 dr K. Barteckiego. Zadanie zostało wykonane poprawnie gdyż sieć do pewnego momentu rozpoznawała zniekształcone obrazy lecz po większej ilości zmienionych pikseli sieć nie potrafiła odczytać nauczonych wcześniej liter. Świadczy to o tym, że nawet to co dla nas jest zadanie prostym i oczywistym dla komputer nie koniecznie. Jednakże możliwość nauczenia maszyny myślenia podobnie do ludzkiego mózgu jest fascynującym doświadczeniem.
5. Wykaz literatury
Bartecki K.: Sztuczne sieci neuronowe w zastosowaniach. Zbiór ćwiczeń laboratoryjnych z wykorzystaniem przybornika Neural Network Toolbox programu Matlab. Skrypt Politechniki Opolskiej nr 289, Opole 2010.
Wykłady nr 2 i 3 udostępnione przez prowadzącego.
Żelazkowski M.: Algorytmy uczenia sieci neuronowych. Artykuł internetowy: http://www.ineur.pr.edu.pl, dostęp w dniu 10.03.2013.
13