brunch

You can make anything
by writing

C.S.Lewis

by 라인하트 Jan 02. 2021

머신러닝 옥타브 실습 (2-2): 로지스틱 회귀

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



Programing Exercise 2 : Logistic Regression

프로그래밍 실습 2 : 로지스틱 회귀  


1. Logistic Regression (로지스틱 회귀) 


1.2 Implementation (구현)


1.2.2 Cost function and gradient (비용 함수와 경사 하강법)


   Now you will implement the cost function and gradient for logistic regression. Complete the code in costFunction.m to return the cost and gradient. Recall that the cost function in logistic regression is and the gradient of the cost is a vector of the same length as θ where the jth  element (for j = 0,1,...,n) is defined as follows:



   Note that while this gradient looks identical to the linear regression gra- dient, the formula is actually different because linear and logistic regression have different definitions of hθ(x). Once you are done, ex2.m will call your costFunction using the initial parameters of θ. You should see that the cost is about 0.693.


   로지스틱 회귀의 비용 함수와 기울기(미분항 계산)를 구현합니다.  CostFunction.m의 코드를 완성하여 비용과 기울기를 반환합니다. 로지스틱 회귀의 비용 함수는 다음과 같고, 비용 함수에 대한 미분항은 다음과 같습니다. 

   경사 하강은 선형 회귀와 경사 하강과 동일해 보이지만, 가설 hθ(x)의 정의가 다르기 때문에 실제로 다릅니다. ex2.m은 초기 파라미터 θ를 사용하여 costFunction을 호출합니다.  비용은 약 0.693입니다. 


<해설> 


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


clear; close all; clc          % 옥타브 프로그램 초기화

data = load ('ex2data1.txt');       

X = [data(:,1:2)];

y = [data(:,3)];

[m, n] = size(X);               % 데이터 행렬의 행은 학습 예제의 수 m이고, 열은 피처의 개수 n


(2) 인터셉트 항 x0를 추가


>> X = [ones(m,1), X]    % 데이터 행렬 X에 인터셉트 항 x0를 적용

X =

    1.0000   34.6237   78.0247

    ...


(3) costFunction.m 함수 파일에 인계할 변수를 설정


   ex2.m 파일에서 costFunction.m 파일은 다음과 같이 호출합니다.


   [cost, grad] = costFunction(initial_theta, X , y);


   ex2.m 파일은 변수 Initial_theta, X, y를 입력으로 제공하고,  변수 cost와 grad 값을 반환합니다.  이미 X, y는 구성되었으므로 변수 initial_theta를 지정합니다. 


   initial_theta = zeros(n + 1, 1);         % theta를 초기화

   

(4) costFunction.m 파일 열고 추가 변수 확인

function [J, grad] = costFunction(theta, X, y)

% COSTFUNCTION  로지스틱 회귀의 비용과 경사를 계산 

%   J = COSTFUNCTION(theta, X, y) 로지스틱 회귀의 파라미터 theta를 사용하여 비용을 계산 

%   parameter for logistic regression and the gradient of the cost

%   w.r.t. to the parameters.


% 학습 예제의 수 m

m = length(y); % number of training examples


% 변수 초기화  

J = 0;

grad = zeros(size(theta));


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

% Instructions: Compute the cost of a particular choice of theta.

%               비용 함수 J를 적으시오 

%               theta의 각 파라미터에 대해 cost w.r.t의 편미분을 하고 grad를 설정하시오 

%               

%

% Note:  grad는 theta와 같은 차원 

%









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


end


(5) 비용 함수 J(θ)를 작성


   비용 함수는 다음과 같습니다.

  우선, 행렬 X에 대한 가설의 예측치를 계산합니다. 

      z = X * theta;      % g(z)를 sigmoid(z)로 표현할 수 있음

     J = -1/m * (y*log(sigmoid(z)) + (1-y)*log(1-sigmoid(z)))

      

      여기서, y는 100 X 1차원 벡터이고, log(sigmoid(z))는 100 X 1차원 벡터입니다. 두 변수에 대한 행렬 곱셈을 하기 위해서는 y를 전치해야 합니다. 따라서 다음과 같이 다시 적을 수 있습니다. 

 

     J = -1/m * (y'*log(sigmoid(z)) + (1-y)'*log(1-sigmoid(z)))


옥타브 프로그램에서 이 식을 직접 대입한 후 값을 확인합니다.


>>    z = X * theta; 

>>   J = -1/m * (y'*log(sigmoid(z)) + (1-y)'*log(1-sigmoid(z)))

J =  0.69315


   이 비용은 이미 계산된 값과 동일합니다.


(6) 미분항을 계산


   미분항을 구하는 공식은 다음과  같습니다.

   이 식을 옥타브 프로그램의 명령어로 적으면 다음과 같습니다.  


    grad = 1/m * (sigmoid(z) - y)*X


     여기서, sigmoid(z)는 100 X1 차원 벡터이고, y도 100 X1 차원 벡터이고, X도 100X1차원 벡터입니다. 따라서, 행렬 곱셈을 위해서는 (sigmoid(z)-y)항이 전치되어야 합니다.


      grad = 1/m * (sigmoid(z) - y)'*X


실제 계산하면 다음과 같습니다. 



>> grad = 1/m * (sigmoid(z) - y)*X

error: operator *: nonconformant arguments (op1 is 100x1, op2 is 100x3)

>> grad = 1/m * (sigmoid(z) - y)'*X

grad =

   -0.10000  -12.00922  -11.26284


<정답>

costFunction.m 파일에 다음과 같이 입력합니다.


function [J, grad] = costFunction(theta, X, y)

%COSTFUNCTION  로지스틱 회귀의 비용과 경사를 계산 

%   J = COSTFUNCTION(theta, X, y) 로지스틱 회귀의 파라미터 theta를 사용하여 비용을 계산 

%   parameter for logistic regression and the gradient of the cost

%   w.r.t. to the parameters.


% 학습 예제의 수 m

m = length(y); % number of training examples


% 변수 초기화  

J = 0;

grad = zeros(size(theta));


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

% Instructions: Compute the cost of a particular choice of theta.

%               비용 함수 J를 적으시오 

%               theta의 각 파라미터에 대해 cost w.r.t의 편미분을 하고 grad를 설정하시오 

%               

%

% Note:  grad는 theta와 같은 차원 

%



z = X * theta; 

J = -1/m * (y'*log(sigmoid(z)) + (1-y)'*log(1-sigmoid(z)));


grad = 1/m * (sigmoid(z) - y)'*X;



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


end


<결과 확인>


>>  [cost, grad] = costFunction(initial_theta, X , y)

cost =  0.69315

grad =


   -0.10000  -12.00922  -11.26284



>> submit



1.2.3 Learning parameters using fminunc


   In the previous assignment, you found the optimal parameters of a linear re- gression model by implementing gradent descent. You wrote a cost function and calculated its gradient, then took a gradient descent step accordingly. This time, instead of taking gradient descent steps, you will use an Octave/- MATLAB built-in function called fminunc.

   Octave/MATLAB’s fminunc is an optimization solver that finds the min- imum of an unconstrained2 function. For logistic regression, you want to optimize the cost function J(θ) with parameters θ.

   Concretely, you are going to use fminunc to find the best parameters θ for the logistic regression cost function, given a fixed dataset (of X and y values). You will pass to fminunc the following inputs:


• The initial values of the parameters we are trying to optimize.

• A function that, when given the training set and a particular θ, computes the logistic regression cost and gradient with respect to θ for the dataset (X, y)


   In ex2.m, we already have code written to call fminunc with the correct arguments.


%  Set options for fminunc 
     options = optimset('GradObj', 'on', 'MaxIter', 400); 

%  Run fminunc to obtain the optimal theta 
%  This function will return theta and the cost 
    [theta, cost] = ... 
    fminunc(@(t)(costFunction(t, X, y)), initial theta, options);


   In this code snippet, we first defined the options to be used with fminunc. Specifically, we set the GradObj option to on, which tells fminunc that our function returns both the cost and the gradient. This allows fminunc to use the gradient when minimizing the function. Furthermore, we set the MaxIter option to 400, so that fminunc will run for at most 400 steps before it terminates.

   To specify the actual function we are minimizing, we use a “short-hand” for specifying functions with the @(t) ( costFunction(t, X, y) ). This creates a function, with argument t, which calls your costFunction. This allows us to wrap the costFunction for use with fminunc.

   If you have completed the costFunction correctly, fminunc will converge on the right optimization parameters and return the final values of the cost and θ. Notice that by using fminunc, you did not have to write any loops yourself, or set a learning rate like you did for gradient descent. This is all done by fminunc: you only needed to provide a function calculating the cost and the gradient.

   Once fminunc completes, ex2.m will call your costFunction function using the optimal parameters of θ. You should see that the cost is about 0.203.

   This final θ value will then be used to plot the decision boundary on the training data, resulting in a figure similar to Figure 2. We also encourage you to look at the code in plotDecisionBoundary.m to see how to plot such a boundary using the θ values.



   이전 과제에서 경사 하강을 구현하고 선형 회귀 모델의 최적 파라미터를 찾았습니다. 비용 함수를 작성하고 경사를 계산한 후 경사 하강 업데이트를 수행했습니다. 이번에는 경사 하강법 단계를 수행하는 대신에 fminunc 명령어를 사용합니다. 

   옥타브 프로그램의 fminunc은 unconstrained2 함수의 최소값을 찾는 최적화 해찾기(solver)입니다. 로지스틱 회귀 분석의 경우 파라미터 θ를 사용하여 비용 함수 J(θ)를 최적화합니다. 예를 들면, fminunc 함수를 고정된 데이터 셋 (X 및 y )에서 로지스틱 회귀 비용 함수에 대한 최적의 파라미터 θ를 찾을 것입니다. 


    fminunc 함수는 다음 변수를 반환합니다.


• 최적화를 하기 위한 파라미터의 초기값

• 학습 셋과 특정 파라미터 θ가 있을 때 θ에 대한 로지스틱 회귀 비용 및 기울기를 계산하는 함수


   ex2.m 파일에 fminunc를 올바르게 호출하는 코드를 삽입하였습니다.


options = optimset('GradObj', 'on', 'MaxIter', 400); 

[theta, cost] = ... 

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);

   

코드 조각에서 fminunc에 사용할 옵션을 정의합니다. 


'GradObj', 'on' : GradObj 옵션을 활성화하는 설정

                           fminunc 함수는 비용과 기울기를 모두 반환

                                  fminunc 함수를 최소화할 때 기울기를 활용


 'MaxIter', 400 : MaxIter 옵션을 400으로 설정

                               fminunc가 400 단계를 실행


 @(t)(costFunction(t, X, y)) : costFunction(t,X,y)를 호출

                                fminunc는 costFunction 함수를 감싸는 것입니다. 


   CostFunction 함수를 제대로 작성했다면 fminunc 는 최적화 파라미터에 수렴하고  Cost와 파라미터 θ의 최적값을 반환합니다. fminunc는 경사 하강법처럼 학습률을 설정할 필요가 없습니다. 비용과 기울기(미분항)를 계산하는 함수인 costFunction.m 함수를 제공하면 됩니다.

   ex2.m은 파라미터 θ를 사용하여 costFunction 함수를 호출할 때 비용은 약 0.203입니다.

   학습 데이터 셋에 결정 경계를 그릴 것이고, 그림 2와 유사한 그림이 될 것입니다. 결정 경계를 그리는 방법을 알기 위해 plotDecisionBoundary.m 코드를 보는 것도 좋습니다.


<해설>

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


clear; close all; clc          % 옥타브 프로그램 초기화

data = load ('ex2data1.txt');       

X = [data(:,1:2)];

y = [data(:,3)];

[m, n] = size(X);      % 데이터 행렬의 행은 학습 예제의 수 m이고, 열은 피처의 개수 n

X = [ones(m,1), X];    % 데이터 행렬 X에 인터셉트 항 x0를 적용

initial_theta = zeros(n + 1, 1);         % theta를 초기화


(2) fminunc 함수를 위한 옵션 값과 함수 설정 


options = optimset('GradObj', 'on', 'MaxIter', 400); 

[theta, cost] = ... 

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options)



   옥타브 프로그램에서 fminunc 명령어를 입력하고, 결과를 확인합니다. 


theta =

  -25.16127

    0.20623

    0.20147


cost =  0.20350



(3) 데이터 도식화


  결정 경계를 그리는 함수 plotDecisonBoundary.m 파일이 작성되어 있습니다.  파일을 간단하게 분석합니다. 처음 직선을 그리는 부분만을 분석하고 등고선을 그리는 부분은 다음에 설명합니다. 

   

plotData(X(:,2:3), y);     % plotData 함수를 호출. 데이터 행렬 X에서 인터셉트 항은 제외

hold on                           % 처음 그림 창에 계속 추가



(4) 결정 경계를 그리기 위해 x 값을 결정


   plot_x 변수를 선언하고, X축의 최소값과 최대값을 구합니다. X축에는 x1의 값이 위치합니다. 선을 그리기 위해서는 2개의 점이 필요하기 때문입니다. -2와  +2를 한 것은 보기 좋게 합니다.  


>> plot_x = [min(X(:,2))-2,  max(X(:,2))+2]

plot_x =

    28.059   101.828

   

   따라서, plot_x 는 1X2 차원 행렬입니다. 


   plot_y 변수를 선언하고, plot_x축의 값에 따른 y의 값의 범위를 지정


h(x) = θ0 + θ1*x1 + θ2*2 를 n+1 행렬이므로 다음과 같이 정리합니다.  이미 X축의 최소값과 최대값을 알고 있고 이때 Y축의 값을 알아야 합니다. 


h(x) = θ1 + θ2*x2 + θ3*x3  = 0 

                                   θ3*x3  = - θ1 - θ2*x2/

                                         x3 = - 1/θ3*(θ1 +  θ2*x2) 

              

옥타브 프로그램의 식으로 표현합니다. X축의 값 x2은 plot_x 변수에 있습니다. 


>>  plot_y = -1 ./theta(3) .* (theta(2) .* plot_x + theta(1))

plot_y =

   96.166   20.653


이것을 도식화합니다. 

 plot(plot_x, plot_y)    



   X축과 Y축이 값이 이상합니다. 점수는 100점을 넘을 수 없기 때문입니다. 그래프가 잘못된 것이 아니라 축의 시작 값과 끝 값이 잘못된 것입니다. 변경합니다.


axis([30, 100, 30, 100]);




< 정답 > 


(1) 변수를 선언


clear; close all; clc         

data = load ('ex2data1.txt');       

X = [data(:,1:2)];

y = [data(:,3)];

[m, n] = size(X);     

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

initial_theta = zeros(n + 1, 1);         



(2) fminunc를 호출


options = optimset('GradObj', 'on', 'MaxIter', 400); 

[theta, cost] = ... 

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options)


(3) 데이터 도식화

plotData(X(:,2:3), y);    

hold on                 


(4) 결정 경계 그리기 


plot_x = [min(X(:,2)),  max(X(:,2))];

plot_y = -1 ./theta(3) .* (theta(2) .* plot_x + theta(1));

plot(plot_x, plot_y);

hold off;

axis([30, 100, 30, 100])

legend('Admitted', 'Not admitted', 'Decision Boundary')





1.2.4 Evaluating logistic regression (로지스틱 회귀 평가)


   After learning the parameters, you can use the model to predict whether a particular student will be admitted. For a student with an Exam 1 score of 45 and an Exam 2 score of 85, you should expect to see an admission probability of 0.776.

   Another way to evaluate the quality of the parameters we have found is to see how well the learned model predicts on our training set. In this part, your task is to complete the code in predict.m. The predict function will produce “1” or “0” predictions given a dataset and a learned parameter vector θ.

   After you have completed the code in predict.m, the ex2.m script will proceed to report the training accuracy of your classifier by computing the percentage of examples it got correct.



   파라미터를 학습한 후 모델을 사용하여 특정 학생의 입학 여부를 예측합니다. Exam 1의 점수는 45이고, Exam 2는 85점입니다. 이 학생의 입학 확률 0.776입니다. 

   파라미터의 값의 품질을 평가하는 또 다른 방법은 학습 셋에 얼마나 잘 예측하는 지를 확인하는 것입니다. predict.m 파일이 코드를 완성합니다.  예측은 파라미터 벡터  θ가 있을 때 0 또는 1을 예측합니다. 

   predict.m 코드를 완성하고 ex2.m 스크립트가 올바르게 백분율을 계산하여 분류기의 학습 정확도를 확인합니다.


<해설>

(1) 변수를 선언


clear; close all; clc         

data = load ('ex2data1.txt');       

X = [data(:,1:2)];

y = [data(:,3)];

[m, n] = size(X);     

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

initial_theta = zeros(n + 1, 1);         



(2) fminunc를 호출


options = optimset('GradObj', 'on', 'MaxIter', 400); 

[theta, cost] = ... 

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options)



(3) 새로운 학습 데이터를 축정 


  

   따라서, 시그모이드 함수 sigmoid.m 파일에 전달할 값 z = θ^Tx입니다. 옥타브 프로그램의 식으로 정리하면

    새로운 학습 데이터 [1, 45, 85]이고 theta과 연산합니다. 학습 데이터는 1X3 행 벡터이고 theta는 3X1 열 벡터입니다.


   z = sigmoid([1, 45, 85]* theta)


   옥타브 프로그램에서 실행합니다.


>>    z = sigmoid([1, 45, 85]* theta)

z =  0.77629


   주어진 값과 동일합니다.


(4) 확률을 계산하는 predict.m 파일 열기


function p = predict(theta, X)

% PREDICT는 로지스틱 회귀 파라미터 theta를 활용하여 레이블이 0 인지 1인지를 예측 

%

%   p = PREDICT(theta, X)는 sigmoid(theta'*x) >= 0.5 이면 y의 레이블을 1로 설정

%   


m = size(X, 1); % Number of training examples


%  변수 p를 0으로 초기화 

p = zeros(m, 1);


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

% Instructions: Complete the following code to make predictions using

%               your learned logistic regression parameters. 

%               p의 값을 0 또는 1로 정의 You should set p to a vector of 0's and 1's

%








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



end


(5) y의 레이블을 예측


  predict 함수는 변수 theta, X를 입력받아 확률 p를 반환합니다.


function p = predict(theta, X)


   theta는 3 X1 열 벡터, X는 100 X 3 행렬, 확률 p는 100 X 1 열 벡터입니다.


 우선, 변수를 초기화합니다. 


m = size(X,1);

p = zeros(m,1);   % 예측 p를 0으로 초기화 


   p의 값을 예측하기 위해 시그모이드 함수를 호출하여 X*theta의 값을 반환받습니다.


index = find(sigmoid(X*theta) >= 0.5);  % 결과가 0.5보다 큰 인덱스를 반환

p(index,1) = 1;                                       % 예측을 1로 변환 



<정답>

(1) 변수를 선언


clear; close all; clc         

data = load ('ex2data1.txt');       

X = [data(:,1:2)];

y = [data(:,3)];

[m, n] = size(X);     

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

initial_theta = zeros(n + 1, 1);         



(2) fminunc를 호출


options = optimset('GradObj', 'on', 'MaxIter', 400); 

[theta, cost] = ... 

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options)


(3) predict.m 파일 변경 


function p = predict(theta, X)

%PREDICT 는 로지스틱 회귀 파라미터 theta를 활용하여 레이블이 0 인지 1인지를 예측 

%

%   p = PREDICT(theta, X)는 sigmoid(theta'*x) >= 0.5 이면 y의 레이블을 1로 설정

%   


m = size(X, 1); % Number of training examples


%  변수 p를 0으로 초기화 

p = zeros(m, 1);


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

% Instructions: Complete the following code to make predictions using

%               your learned logistic regression parameters. 

%               p의 값을 0 또는 1로 정의 You should set p to a vector of 0's and 1's

%



index = find(sigmoid(X*theta) >= 0.5);  

p(index,1) = 1;                                       



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


end


(4) 결과 확인


>> clear; close all; clc

>> data = load ('ex2data1.txt');

>> X = [data(:,1:2)];

>> y = [data(:,3)];

>> [m, n] = size(X);

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

>> initial_theta = zeros(n + 1, 1);

>> options = optimset('GradObj', 'on', 'MaxIter', 400);

>> [theta, cost] = ...

    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options)

theta =


  -25.16127

    0.20623

    0.20147


cost =  0.20350


>> p = predict(theta,X)

p =


   0

   0

   0

   1

   1

...


(5) Submit


매거진의 이전글 머신러닝 옥타브 실습 (2-1) : 로지스틱 회귀
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari