====== Laboratorium 6 - Sztuczne sieci neuronowe ====== Ćwiczenia bazujące na materiałach Andrew Ng.\\ Przed zajęciami przejrzyj wykłady [[https://class.coursera.org/ml/lecture/preview|VIII i IX]] \\ {{:pl:dydaktyka:ml:ex4.pdf|Instructions}} in English. Ćwiczenia do pobrania (files to download): {{:pl:dydaktyka:ml:neural-networks.zip|Neural Networks}} ===== Lista i opis plików ===== * //ex4.m// - Skrypt pomagający przejść przez laboratorium * //ex4data1.mat// - Dane uczące zawierające pismo odręczne * //ex4weights.mat// - Parametry sieci neuronowej * //displayData.m// - funkcja wizualizująca zbiór danych * //fmincg.m// - Funkcja wyznaczająca minimum (podobna do //fminunc//) * //sigmoid.m// - funkcja sigmoidalna * //computeNumericalGradient.m// - Numerycznie oblicza gradienty * //checkNNGradients.m// - Funkcja sprawdzajaca gradienty * //debugInitializeWeights.m// - Funkcja inicjalizujaca wagi początkowe * //predict.m// - Funkcja predykcji dla sieci neuronowej * :!: sigmoidGradient.m - Obliczanie gradientów dla funkcji sigmoidalnej * randInitializeWeights.m - Losowa inicjalizacja wag sieci neuronowej * :!: nnCostFunction.m - funkcja kosztu dla sieci neuronowej ===== Rozgrzewka ===== Zanim zaczniemy właściwą część zajęć, poświeć chwilę na obejrzeniu jak działa prosta sieć neuronowa w akcji: http://playground.tensorflow.org/ Zastanów się co wpływa na jakość klasyfikacji: * ilość neuronów w warstwie ukrytej? * funkcja aktywacji neuronu? * cechy, które podajemy na wejściu? * ilość danych wejśćiowych? * współczynnik regularyzacji lub learning rate? * ilość warstw ukrytych? ===== Wstęp ===== Celem ćwiczeń laboratoryjnych jest nauczenie sieci neuronowej rozpoznawania cyfr. Sieć neuronowa będzie składać się z 3 warstw. Ilość neuronów w warstwie wyjściowej będzie równa ilości klasyfikowanych wzorców (czyli w naszym przypadku 10). Struktura sieci neuronowej przedstawiona jest na rysunku poniżej. Pierwsza warstwa zawiera 400 perceptronów, warstwa ukryta zabiera 25 neuronów, a warstwa wyjściowa 10. {{:pl:dydaktyka:ml:digit-nn.png?700|Struktura sieci neuronowej do rozpoznawania cyfr}} ===== Funkcja kosztu ===== Uzupełnij plik //nnCostFunction.m// wyznaczając koszt i gradient dla sieci neuronowej. **Uwaga** Macierz X, zawierająca zbiór uczący, zbudowana jest w taki sposób, że poszczególne elementy uczące znajdują się w wierszach. Aby dostać się do //i-tego// przykładu uczącego należy zatem odwołać się do niego w następujący sposób: //X(i,:)//. **Uwaga** Macierz X **nie** zawiera elementów biasu, dlatego w funkcji //nnCostFunction.m// konieczne jest dodanie tych elementów! **Uwaga** Parametry $\Theta$ dla poszczególnych warstw sieci znajdują się w zmiennych //Theta1// oraz //Theta2//. //Theta1// ma rozmiar 25 x 401. //Theta2// ma rozmiar 10 x 26. Wartość funkcji kosztu obliczany jest za pomocą wzoru: $$J(\theta)= \frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{K}\left [ -y_k^{(i)}log((h_\theta(x^{(i)}))_k)-(1-y_k^{(i)})log(1-(h_\theta(x^{(i)}))_k \right ]$$ Gdzie $m$ to ilość przykładów w zbiorze uczącym, a $K$ to ilość etykiet (w naszym przypadku 10). **Uwaga** Pamiętaj aby poprawnie obliczyć wartość $h(x)$, która w przypadku sieci neuronowej polega na wymnożeniu współczynników wag //Theta// i danych wejściowych - zobacz rysunek powyżej. **Uwaga** Sieć neuronowa ma 10 neuronów w warstwie wyjściowej. Zatem wyjście sieci oznaczające, że rozpoznano np liczbę 3, będzie wyglądać następująco (cyfrę **zero** reprezentować będzie 10 indeks wektora //y//): $$y = \begin{bmatrix} 0\\ 0\\ 1\\ 0\\ ...\\ 0 \end{bmatrix}$$ Sprawdź działanie funkcji za pomocą skrypty //check.m//. Uruchom skrypt //ex4.m//. Powinieneś zobaczyć koszt równy około 0.287629. ===== Funkcja kosztu z regularyzacją ===== Wartość funkcji kosztu obliczany jest za pomocą wzoru: $$ J(\theta)= \frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{K}\left [ -y_k^{(i)}log((h_\theta(x^{(i)}))_k)-(1-y_k^{(i)})log(1-(h_\theta(x^{(i)}))_k \right ] + R(\theta) $$ Gdzie $$ R(\theta) = \frac{\lambda}{2m}\left [ \sum_{j=1}^{25}\sum_{k=1}^{400}(\Theta_{j,k}^{(1)})^2+\sum_{j=1}^{10}\sum_{k=1}^{25}(\Theta_{j,k}^{(2)})^2 \right ] $$ **Uwaga** Pamiętaj, żeby we wzorze na remaskularyzację nie uwzględniać biasu. Przetestuj działanie funkcji za pomocą skryptu //check.m//. Przetestuj działanie funkcji za pomocą skryptu //ex4.m//. Powinieneś otrzymać wynik funkcji kosztu na poziomie około 0.383770. ===== Gradient funkcji sigmoidalnej ===== Do wykonania następnego zadnia konieczne jest wyznaczenie gradientu funkcji sigmoidalnej. Uzupełnij plik //sigmoidGradient.m//. Gradient dla funkcji sigmoidalnej obliczany jest wg. wzoru: $$ g'(z) = \frac{d}{dz}g(z) = g(z)(1-g(z)) $$ Sprawdź poprawność działania funkcji za pomocą skryptu //check.m//. ===== Backpropagation ===== {{:pl:dydaktyka:ml:nn-backpropagation.png?700|Backpropagation}} Dla każdego elementu //t// ze zbioru uczącego wykonaj następujące kroki (tutaj nie da się uniknąć pętli //for t=1:m ... end//). - Ustaw wartości perceptronów (warstwa wejściowa $a^{(1)})$ na //t-ty// element ze zbioru uczącego $x^{(t)}$. Wykonaj propagacje wprzód (patrz {{:pl:dydaktyka:ml:digit-nn.png?linkonly|rysunek pierwszy}}), obliczając poszczególne wartości dla warstw wewnętrznych ($z^{(2)}, a^{(2)},z^{(3)},a^{3)}$). Pamiętaj o uwzględnieniu biasu w zmiennych $a^{(1)}$ oraz $a^{(2)}$. Np. //a_1 = [1; a_1]//. - Dla każdego neuronu z warstwy wyjściowej oblicz $$\delta_k^{(3)} = (a_k^{(3)}-y_k)$$ - Dla ukrytej warstwy $l = 2$, ustaw: $$\delta^{(2)}=(\Theta^{(2)})^T\delta^{(3)}.*g'(z^{(2)})$$ - Oblicz zakumulowany gradient dla danego elementu //t//. Pamiętaj żeby pominąć $\delta_0^{(2)}$:$$\Delta^{(l)} = \Delta^{(l)} + \delta^{(l+1)}(a^{(l)})^T$$ - Wyznacz niezregularyzowany gradient:$$\frac{\partial}{\partial\Theta_{i,j}^{(l)})}J(\Theta) = \frac{1}{m}\Delta_{ij}^{(l)}$$ Uruchom skrypt //ex4.m// i sprawdź poprawność działania algorytmu. Sprawdź działanie algorytmu za pomocą skryptu //check.m// ===== Regularyzowane backpropagation ===== Regularyzacja gradientu polega na następującej modyfikacji wzoru: $$\frac{\partial}{\partial\Theta_{i,j}^{(l)})}J(\Theta) = \frac{1}{m}\Delta_{ij}^{(l)}+\frac{\lambda}{m}\Theta_{ij}^{(l)}$$ **Uwaga** Pamiętaj aby pominąć bias! Przetestuj działanie algorytmu przy pomocy skryptu //check.m// oraz //ex4.m//. ===== Uwagi =====