brunch

You can make anything
by writing

C.S.Lewis

by 라인하트 Jan 11. 2021

머신러닝 옥타브 실습(4-4):신경망손글씨 인식

   온라인 강의 플랫폼 코세라의 창립자인 앤드류 응 (Andrew Ng) 교수는 인공지능 업계의 거장입니다. 그가 스탠퍼드 대학에서 머신 러닝 입문자에게 한 강의를 그대로 코세라 온라인 강의 (Coursera.org)에서 무료로 배울 수 있습니다. 이 강의는 머신러닝 입문자들의 필수코스입니다. 인공지능과 머신러닝을 혼자 공부하면서 자연스럽게 만나게 되는 강의입니다. 


Programming Exercise 4: Neural Networks Learning

프로그래밍 실습 4 : 신경망 학습   


2. Backpropagation (역전파)


2.2 Random initialization (랜덤 초기화)


   When training neural networks, it is important to randomly initialize the pa- rameters for symmetry breaking. One effective strategy for random initializa- tion is to randomly select values for Θ(l) uniformly in the range [−εinit, εinit]. You should use εinit = 0.12. This range of values ensures that the parameters are kept small and makes the learning more efficient.

   Your job is to complete randInitializeWeights.m to initialize the weights for Θ; modify the file and fill in the following code:

   

   신경망을 설계할 때 대칭 문제를 해결하기 위해 파라미터 행렬 Θ를 랜덤 초기화합니다. 가장 효과적인 방법은 [-epsilon_init, + epsilon_init] 범위에서 균일하게 파라미터 행렬 Θ를 랜덤 하게 선택합니다. 실습에서 epsilon_init 은 0.12를 사용합니다. 랜덤 초기화의 범위는 파라미터 행렬 Θ를 작게 유지하고 신경망이 효율적으로 학습하도록 돕습니다. 

   randLinitializeWeights.m 파일에 코드를 작성합니다. 다음 코드를 사용합니다. 


% 파라미터 행렬 Θ를 작은 값으로 랜덤 초기화  

epsilon_init = 0.12;
W = rand(L out, 1 + L in) * 2 * epsilon_init − epsilon_init;


<해설>


(1) epsilion_init 의 이해

   epsilon_init를 선택하는 방법 중 하나는 다음과 같은 방법을 이용합니다. 

   손글씨 숫자를 인식하는 신경망에서 epsilon의 값을 추정합니다. 입력층과 출력 계층만을 가진 2 계층 신경망이라고 가정합니다. 파라미터 Θ 를 인접한 계층의 유닛수는 L_in = 400이고, L_out = 10입니다.  따라서 epsilon_init의 값을 계산할 때 0.12097이고, 세 자릿수에서 반올림을 하면 0.12입니다. 


>> sqrt(6) / sqrt(410)

ans =  0.12097



(2) 데이터 업로드 및 기본 변수 설정 


clear; close all; clc         

load ('ex4data1.mat');  % 5000X 400의 손글씨 숫자 흑백 이미지 행렬을 업로드   

[m, n] = size(X);              % 행렬 X가 5000X 400차원일 때 m = 5000, n= 400    



(3) 신경망 변수 설정


input_layer_size  = 400;    % 20x20 이미지를 입력하기 위한 유닛 수

hidden_layer_size = 25;     % 25 은닉 유닛의 수 

num_labels = 10;                   % 멀티 클래스의 수, 0은 10으로 처리


(2) randInitializeWeights.m 파일 분석

   


function W = randInitializeWeights(L_in, L_out)

%RANDINITIALIZEWEIGHTS  Theta 행렬 성분을 초기화 

%   W = RANDINITIALIZEWEIGHTS(L_in, L_out) randomly initializes the weights 

%    L_in : Theta의 들어오는 인접층의 유닛 수 ( Θ^(1)의 L_in은 a^(1)의 유닛 수)

%    L_out : Theta의 나가는 인접층의 유닛 수  (Θ^(1))의 L_out은 a^(2)의 유닛 수)

%

%   Note :

%     W :  (L_out, 1 + L_in)의 행렬이고 바이어스 항을 고려하여 +1을 추가

%


% 변수 초기화  

W = zeros(L_out, 1 + L_in);


% ====================== YOUR CODE HERE ======================

% Instructions: 신경망의 대칭 문제를 파괴하기 위해 가중치 W를 무작위로 초기화

%

% Note: W의 첫 열은 바이어스 항 

%




% =========================================================================


end



(4) 가중치 W로 랜덤 초기화 변수 초기화


   파라미터 행렬 Θ 의 Θ^(1)10, Θ^(1)11,.., Θ^(1)1n 와 같이 단일 유닛에서 다음 계층으로 연결하는 Θ의 값이 0이거나 같은 값을 사용할 경우 대칭 문제가 발생합니다. 대칭 문제를 해결하기 위해 파라미터 행렬  Θ의 값을 - ε과 +ε 사이의 난수로 초기화합니다옥타브 프로그램에서 난수 열의 함수를 만들기 위해 rand() 함수를 사용합니다. 


rand(L_out,L_in);      % L_in 은 입력 유닛의 수, L_out은 출력 유닛의 수 


   바이어스 항을 고려하기 위해 인입 방향의 유닛 수에 1을 추가합니다.


rand(L_out,1+ L_in);      % L_in 은 입력 유닛의 수, L_out은 출력 유닛의 수 


   행렬 성분이 -epsilon과 +epsilon 사이의 값을 가져야 하므로 2 * epsilon을 곱한 후 epsilon 뺍니다.

   

Theta = rand(L_out, 1 + L_in) * (2*epsilon_init) - epsilon_init; 


   결국,  - ε과 +ε 사이의 숫자가 됩니다.  여기에 있는 ε은 경사도 검사의 ε과 전혀 상관없습니다. 


W = zeros(L_out, 1+ L_in);


epsilon_init = 0.12;

W = rand(L_out, 1+ L_in) * (2 * epsilon_init) - epsilon_init;


   다음과 같이 확인합니다. 


W1 = rand(hidden_layer_size, input_layer_size)*(2 * epsilon_init) - epsilon_init;

W2 = rand(num_labels, hidden_layer_size)*(2 * epsilon_init) - epsilon_init;


>> size(W1)

ans =

    25   400          % 바이어스 항을 고려한다면 input_layer_size에 1을 추가


>> size(W2)

ans =

   10   25            % 바이어스 항을 고려한다면 hidden_layer_size에 1을 추가


(5) 파라미터를 언롤링 (Unroll parameters)

 

    initial_Theta1는 25 X 401차원 행렬이고, initial_Theta2는 10 X 26차원 행렬입니다. 고급 초적화 알고리즘에서 사용하기 위해 파라미터 행렬을 파라미터 벡터로 재배열합니다.


initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)];



(6)  정답 


function W = randInitializeWeights(L_in, L_out)

%RANDINITIALIZEWEIGHTS  Theta 행렬 성분을 초기화 

%   W = RANDINITIALIZEWEIGHTS(L_in, L_out) randomly initializes the weights 

%    L_in : Theta의 들어오는 인접층의 유닛 수 ( Θ^(1)의 L_in은 a^(1)의 유닛 수)

%    L_out : Theta의 나가는 인접층의 유닛 수  (Θ^(1))의 L_out은 a^(2)의 유닛 수)

%

%   Note 

%     W :  (L_out, 1 + L_in)의 행렬이고 첫 열은 바이어스 항

%


% 변수 초기화  

W = zeros(L_out, 1 + L_in);


% ====================== YOUR CODE HERE ======================

% Instructions: 신경망의 대칭 문제를 파괴하기 위해 가중치 W를 무작위로 초기화

%

% Note: W의 첫 열은 바이어스 항 

%


epsilon_init = 0.12;

W = rand(L_out, 1+ L_in) * (2 * epsilon_init) - epsilon_init;


% =========================================================================


end


<결과 확인>


clear; close all; clc         

load ('ex4data1.mat');    

[m, n] = size(X);              


input_layer_size  = 400;    

hidden_layer_size = 25;     

num_labels = 10;                 


initial_Theta1 = randInitializeWeights(input_layer_size, hidden_layer_size);

initial_Theta2 = randInitializeWeights(hidden_layer_size, num_labels);


initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)];


다음의 결과를 확인할 수 있습니다.


>> size(initial_Theta1)

ans =

    25   401


>> size(initial_Theta2)

ans =

   10   26


>> size(initial_nn_params)

ans =

   10285       1



2.3 Backpropagation (역전파)


   Now, you will implement the backpropagation algorithm. Recall that the intuition behind the backpropagation algorithm is as follows. Given a training example (x(t),y(t)), we will first run a “forward pass” to compute all the activations throughout the network, including the output value of the hypothesis hΘ(x). Then, for each node j in layer l, we would like to compute an “error term” δ(l) that measures how much that node was “responsible” j for any errors in our output.

   For an output node, we can directly measure the difference between the network’s activation and the true target value, and use that to define δ(3)j (since layer 3 is the output layer). For the hidden units, you will compute δ(l) based on a weighted average of the error terms of the nodes in layer (l + 1).

   In detail, here is the backpropagation algorithm (also depicted in Figure 3). You should implement steps 1 to 4 in a loop that processes one example at a time. Concretely, you should implement a for-loop for t = 1:m and place steps 1-4 below inside the for-loop, with the tth iteration performing the calculation on the tth training example (x(t),y(t)). Step 5 will divide the accumulated gradients by m to obtain the gradients for the neural network cost function.


   이번 실습은 역전파 알고리즘을 구현합니다. 학습 예제 (x^(t), y^(t))가 있을 때 순전파 알고리즘으로 신경망 전체의 모든 유닛의 활성화 함수를 계산하고, 출력 유닛의 출력값 hΘ(x)를 계산합니다. 그런 다음 l 계층의 j노드에서 오차를 계산하는 오차항 δ^(l)을 계산합니다. 

   출력 노드는 δ^(3)j 는 신경망의 출력값과 학습 예제의 실제값과의 차이입니다. (출력 계층은 3 계층). 은닉 유닛은 (ㅣ+1) 계층에 있는 노드의 오차항에 대한 평균을 기반으로 δ^(l)을 계산합니다. 

   자세한 내용은 그림 3의 역전파 알고리즘 설명에 있습니다. 한 번에 하나의 예제를 처리하는 For 루프에서 1에서부터 4 단계를 구현합니다. 예를 들면, t = 1:m까지 For 루프를 구현하고 For 루프 내부에 1에서 4단계를 배치합니다. t 번째 반복은 t 번째 학습 예제 (x^(t), y^(t))에 대한 계산을 수행합니다. 5 단계는 누적된 기울기를 m으로 나누어 신경망 비용 함수에 대한 기울기를 얻습니다.


1. Set the input layer’s values (a(1)) to the t-th training example x(t). Perform a feedforward pass (Figure 2), computing the activations (z(2), a(2), z(3), a(3)) for layers 2 and 3. Note that you need to add a +1 term to ensure that the vectors of activations for layers a(1) and a(2) also include the bias unit. In Octave/MATLAB, if a 1 is a column vector, adding one corre- spondstoa1 = [1 ; a1].


1. 입력 계층의 값 a^(1)을 t 번째 학습 예제 x^(t)로 설정합니다. 피드 포워드 패스 (그림 2)로 2 계층과 3 계층에 대한 활성화 함수 a^(2) = g(z^(2)), a^(3) = g(z^(3))를 계산합니다. a^(1) 계층과 a^(2) 계층의 활성화 벡터 벡터에도 바이어스 유닛을 포함하는 지를 확인합니다. 옥타브 프로그램에서 1이 열 벡터 일 때 [1; a1]입니다.  


2. For each output unit k in layer 3 (the output layer), set

   where yk ∈ {0,1} indicates whether the current training example be- longs to class k (yk = 1), or if it belongs to a different class (yk = 0). You may find logical arrays helpful for this task (explained in the pre- vious programming exercise).


   3 계층의 출력 유닛 k에 대한 오류는 다음과 같습니다. yk ∈ {0,1}이고 학습 예제가 클래스 k(yk =1)인지 아니면 다른 클래스에 속하는지 (yk = 0)를 나타냅니다. 이때 논리 배열을 통해 찾을 수 있습니다.


3. For the hidden layer l = 2, set

   은닉 계층인 2 계층의 오차 항을 계산합니다. 


4. Accumulate the gradient from this example using the following formula. Note that you should skip or remove δ(2). In Octave/MATLAB, removing δ(2) corresponds to delta 2 = delta 2(2:end).

 다음 공식으로  학습 예제에 대한 경사를 누적합니다. δ^(2)0를 건너 뛰거나 제거합니다. 옥타브 프로그램은 δ^(2)0를 제거하면 delta2 = deta2(2:end)


5. Obtain the (unregularized) gradient for the neural network cost function by dividing the accumulated gradients by 1 :

   누적된 기울기를 1/m으로 나누어 신경망 비용 함수에 기울기를 구합니다.



   Octave/MATLAB Tip: You should implement the backpropagation algorithm only after you have successfully completed the feedforward and cost functions. While implementing the backpropagation algorithm, it is often useful to use the size function to print out the sizes of the vari- ables you are working with if you run into dimension mismatch errors (“nonconformant arguments” errors in Octave/MATLAB).

   옥타브 팁 : 피드 포워드 및 비용 함수를 성공적으로 완료한 후에 역전파 알고리즘을 구현합니다. 역전파 알고리즘을 구현하는 동안 행렬 차원 크기 불일치 오류 ("nonconformant arguments")가 발생하면 작업 중인 변수의 행렬의 차원을 확인하기 위해 size() 함수를 사용합니다.   


   After you have implemented the backpropagation algorithm, the script ex4.m will proceed to run gradient checking on your implementation. The gradient check will allow you to increase your confidence that your code is computing the gradients correctly.


   역전파 알고리즘을 구현한 후 ex4.m스크립트는 경사도 검사 (Gradient Checking)를 실행합니다. 경사도 검사는 코드가 경사를 제대로 계산하는 지를 검증합니다. 



<해설>


(1) 데이터 업로드 및 기본 변수 설정 


clear; close all; clc         

load ('ex4data1.mat');  % 5000X 400의 손글씨 숫자 흑백 이미지 행렬을 업로드   

[m, n] = size(X);              % 행렬 X가 5000X 400차원일 때 m = 5000, n= 400    



(2) 신경망 변수 설정


input_layer_size  = 400;    % 20x20 이미지를 입력하기 위한 유닛 수

hidden_layer_size = 25;     % 25 은닉 유닛의 수 

num_labels = 10;                   % 멀티 클래스의 수, 0은 10으로 처리


lambda = 1;                          % 정규화 파라미터 λ를 초기화   

X = [ones(m, 1), X];      



(3) nnCostFunction.m 파일 분석 


function [J grad] = nnCostFunction(nn_params,input_layer_size, ...

                                   hidden_layer_size, num_labels, X, y, lambda)

%NNCOSTFUNCTION  2층 신경망의 비용 함수 구현 

%

%   [J grad] = NNCOSTFUNCTON(nn_params, hidden_layer_size, num_labels, ...

%   X, y, lambda) 신경망의 비용 J과 기울기 grad를 계산 

%   신경망의 파라미터는 벡터 nn_params로 변환했다가 가중치 행렬로 다시 변환

%   변환될 파라미터는 신경망의 편미분에 대한 unrolled 벡터가 변환

%   

%   Reshape() 함수로 nn_params를 Theta1과 Theta2로 전환 

Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...

                 hidden_layer_size, (input_layer_size + 1));


Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...

                 num_labels, (hidden_layer_size + 1));


% 변수 초기화 

m = size(X, 1);

         

% 반환할 변수 초기화  

J = 0;

Theta1_grad = zeros(size(Theta1));

Theta2_grad = zeros(size(Theta2));


% ====================== YOUR CODE HERE ======================

% Instructions: 다음 두 부분을 코드로 완성 

%

% Part 1: 신경망을 피드 포워드 하고 변수 J에 비용을 반환

 %             Part 1을 구현한 후 비용 함수 계산이 맞는 지를 확인

%

% Part 2: 경사를 계산하기 위해 역전파 알고리즘을 구현

%               (Theta1_grad과 Theta2_grad에 있는 Theta1과 Theta2의 비용 함수의 편미분을 반환

%              Part 2를 구현 후 checkNNGradients를 실행하여 맞는 지를 확인

%

%         노트:  벡터 y는 1부터 K까지를 포함하는 벡터

%               신경망의 비용 함수에 사용되는 1 또는 0으로 된 이진 벡터 

%

%         힌트: 학습 예제를 대상으로 For 루프를 사용하여 역전파를 구현 

%          

%

% Part 3: 비용 함수와 기울기에 대해 정규화를 구현

%

%         힌트: 역전파 코드를 활용하여 정규화된 비용 함수와 기울기 구현 

%                  정규화를 위한 경사를 계산하고 Part 2의 Theta1_grad와 Theta2_grad를 추가

%        

%


X = [ones(m,1) X];


a2 = sigmoid(X*Theta1');

a2 = [ones(m,1) a2];


a3 = sigmoid (a2 * Theta2');


yVec = zeros(m,num_labels);     

temp = eye(num_labels);           

yVec  = temp(y,:);     


%Cost Function

J = - 1/m *sum(sum  (yVec .*log(a3) + (1-yVec) .*log(1-a3)));


% Regularized Cost Function

regularizer = lambda/(2*m) * (sum(sum(Theta1(:, 2:end) .* Theta1(:, 2:end))) + sum(sum( Theta2(:, 2:end) .* Theta2(:, 2:end))));


J = J + regularizer;




% -------------------------------------------------------------


% =========================================================================


% 기울기를 언롤링(Unroll)

grad = [Theta1_grad(:) ; Theta2_grad(:)];



end



(4) 파라미터 행렬 Theta 랜덤 초기화 


   조금 전 구현한 randInitializeWeights() 함수를 활용하여 initial_Theta1과 initial_Theta2의 값을 랜덤 초기화합니다. 


initial_Theta1 = randInitializeWeights(input_layer_size, hidden_layer_size);

initial_Theta2 = randInitializeWeights(hidden_layer_size, num_labels);


initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)];


(5) 오차 항 δ^(2)와 δ^(3)를 초기화


Theta1 = initial_Theta1;    % 옥타브에서 테스트하기 위해 변수 동기화

 Theta2 = initial_Theta2;   % 옥타브에서 테스트하기 위해 변수 동기화


Delta1 = zeros(size(Theta1));        % Delta1은 25 X 401차원 행렬

Delta2 = zeros(size(initial_Theta2));          % Delta2는 10 X 26차원 행렬



(6) 단 하나의 예제에 대한 순전파를 수행하여 출력값 계산


   for i = 1:m 을 사용하여 5,000개의 학습 예제에 대해 실행합니다. 우선 단 하나의 예제에 대한 순전파로 가설 hΘ(x)를 구합니다. 



   xt = X(i, :);              % X는 5000 X 400차원 행렬, xt는 1X 401차원 행 벡터


    z2t = xt*Theta1';       % Theta1은 25 X 401차원 행렬을 전치 401 X 26차원 행렬

    a2t = sigmoid(z2t);    

   a2t = [1 a2t];                           % a 2t는 1 X 26 행렬


   z3t = a2t * Theta2'     % Theta2는 10 X 26차원 행렬을 전치 26 X 10차원 행렬

   a3t = sigmoid (z3t);   % a 3t는 1 X 10차원 행렬

                                                               


(7) 단 하나의 예제에 대한 역전파를 수행하여 오차 항 계산


   오 차 항을 계산하는 공식은 다음과 같습니다. 

   특히, 은닉 계층의 오차를 계산하기 위해 g(z)를 미분하는 g'(z)를 계산하는 함수를 구현하였습니다. sigmoidGradient() 함수를 분석합니다. 


function g = sigmoidGradient(z)

%SIGMOIDGRADIENT z에 대한 시그모이드 함수의 기울기를 반환 

%

%   g = SIGMOIDGRADIENT(z) z에 대한 시그모이드 함수의 기울기를 반환

%   z는 스칼라, 행렬 또는 벡터일 경우 성분에 대한 기울기를 반환


g = zeros(size(z));   % z의 차원에 맞추어 g를 초기화


% ====================== YOUR CODE HERE ======================

% Instructions:  z에 대한 시그모이드 함수의 기울기를 계산  

%                          z는 스칼라, 행렬 또는 벡터



    g = sigmoid(z) .* (1-sigmoid(z));



% =============================================================


end


  역전파 알고리즘을 활용하여 오 차 항을 구현합니다. 실제 값의 y의 값을 멀티 클래스의 벡터로 변환합니다. 


for k = 1:m

    yVec(k,y(k)) = 1;

end  


   for i = 1:m을 사용하여 5,000개의 학습 예제에 대해 실행합니다. 우선 단 하나의 예제에 대한 순전파로 가설 hΘ(x)를 구합니다. 



     yt = yVec(i,:);                          % y는 5000 X 1차원 행렬, yt는 1X1 스칼라 값, 실수 


     delta3t = a3t - yt;                   % a3t는 1X 10 행렬


   여기서, Theta2는 10X 26 행렬입니다. 전치하여 26 X 10 행렬로 재배열하고 바이어스 항을 제거하여 25 X 10차원 행렬로 재배열합니다. delta3t는 1 X 10차원 행렬로 전치하여 10 X1 행렬로 재배열합니다. 따라서, Theta2(:, 2:end)' * delta3 t'는 25 X 1차원 행렬입니다. 결과 행렬인 delta2t는 1X 25차원 행렬이다


      delta2t = (Theta2(:, 2:end)' * delta3t')' .* (sigmoidGradient(z2t));



(8) 오차를 누적 


Delta1 = Delta1 + delta2t' * xt;          % Delta1은 25 X 401차원 행렬

Delta2 = Delta2 + delta3t' *a2t;          % Delta2는 10 X 26차원 행렬



<정답>


function [J grad] = nnCostFunction(nn_params,input_layer_size, ...

                                   hidden_layer_size, num_labels, X, y, lambda)

%NNCOSTFUNCTION  2층 신경망의 비용 함수 구현 

%

%   [J grad] = NNCOSTFUNCTON(nn_params, hidden_layer_size, num_labels, ...

%   X, y, lambda) 신경망의 비용 J과 기울기 grad를 계산 

%   신경망의 파라미터는 벡터 nn_params로 변환했다가 가중치 행렬로 다시 변환

%   변환될 파라미터는 신경망의 편미분에 대한 unrolled 벡터가 변환

%   

%   Reshape() 함수로 nn_params를 Theta1과 Theta2로 전환 

Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...

                 hidden_layer_size, (input_layer_size + 1));


Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...

                 num_labels, (hidden_layer_size + 1));


% 변수 초기화 

m = size(X, 1);

         

% 반환할 변수 초기화  

J = 0;

Theta1_grad = zeros(size(Theta1));

Theta2_grad = zeros(size(Theta2));


% ====================== YOUR CODE HERE ======================

% Instructions: 다음 두 부분을 코드로 완성 

%

% Part 1: 신경망을 피드 포워드 하고 변수 J에 비용을 반환

 %             Part 1을 구현한 후 비용 함수 계산이 맞는 지를 확인

%

% Part 2: 경사를 계산하기 위해 역전파 알고리즘을 구현

%               (Theta1_grad과 Theta2_grad에 있는 Theta1과 Theta2의 비용 함수의 편미분을 반환

%              Part 2를 구현 후 checkNNGradients를 실행하여 맞는 지를 확인

%

%         노트:  벡터 y는 1부터 K까지를 포함하는 벡터

%               신경망의 비용 함수에 사용되는 1 또는 0으로 된 이진 벡터 

%

%         힌트: 학습 예제를 대상으로 For 루프를 사용하여 역전파를 구현 

%          

%

% Part 3: 비용 함수와 기울기에 대해 정규화를 구현

%

%         힌트: 역전파 코드를 활용하여 정규화된 비용 함수와 기울기 구현 

%                  정규화를 위한 경사를 계산하고 Part 2의 Theta1_grad와 Theta2_grad를 추가

%        

%



X = [ones(m,1) X];


a2 = sigmoid(X*Theta1');


a2 = [ones(size(a2,1), 1) a2];

a3 = sigmoid(a2*Theta2');


for k = 1:m

    yVec(k,y(k)) = 1;

end


% Computing Cost Function J

J = - 1/m *sum(sum(yVec .*log(a3) + (1-yVec) .*log(1-a3)));


% Computing Regularized Cost Function J

regularizer = lambda/(2*m) * (sum(sum(Theta1(:, 2:end) .^2 )) + sum(sum (Theta2(:, 2:end) .^2)));


J = J + regularizer;   



% Backpropagation

Delta1 = zeros(size(Theta1));        

Delta2 = zeros(size(Theta2));  


for t = 1: m

   xt = X(t, :);

   a2t = sigmoid(xt*Theta1');  

   a2t = [1 a2t];

   a3t = sigmoid (a2t * Theta2');

   delta3t = a3t - yVec(t,:);

   delta2t = (Theta2(:, 2:end)' * delta3t')' .* (sigmoidGradient(xt*Theta1'));

   Delta1 = Delta1 + delta2t' * xt;  

   Delta2 = Delta2 + delta3t' *a2t; 

end

Theta1_grad = 1/m *Delta1;

Theta2_grad = 1/m *Delta2;


% ================================================================


% 기울기를 언롤링(Unroll)

grad = [Theta1_grad(:) ; Theta2_grad(:)];



end


<결과 확인>


매거진의 이전글 머신러닝 옥타브 실습(4-3):신경망손글씨 인식
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari