brunch

You can make anything
by writing

C.S.Lewis

by 라인하트 Jan 04. 2021

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

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



Programing Exercise 2 : Logistic Regression

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


2. Regularized logistic regression (구현)


2.3.1 Learning parameters using fminunc

         (fminunc 함수를 활용한 학습 파라미터 )

             

   Similar to the previous parts, you will use fminunc to learn the optimal parameters θ. If you have completed the cost and gradient for regularized logistic regression (costFunctionReg.m) correctly, you should be able to step through the next part of ex2 reg.m to learn the parameters θ using fminunc.


   fminunc를 사용하여 최적의 파라미터 θ를 학습합니다. 정규화된 로지스틱 회귀 (costFunctionReg.m)에 대한 비용과 기울기를 올바르게 완료했다면 ex2_reg.m의 다음 부분을 단계별로 수행하면서 fminunc를 사용한 파라미터 θ를 학습합니다. 


<해설>


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


clear; close all; clc         

data = load ('ex2data2.txt');       

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

y = [data(:,3)];

[m, n] = size(X);           


(2) 피처 매핑 함수를 호출하여 다항식으로 매핑할 데이터 생성 


X1 = X(:,1);                     

X2 = X(:,2);                      

X = mapFeature(X1,X2);


(3) 추가적인 변수 초기화 


initial_theta = zeros(size(X, 2), 1);         

lambda = 1;                                              


(4) fminunc() 함수 구현   


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

[theta, J, exit_flag] = ...

 fminunc(@(t)(costFunctionReg(t, X, y, lambda)), 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 함수를 호출합니다. 



<정답 >


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

>> [theta, J, exit_flag] = ...

 fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options);


>> J

J =  0.52900

>> theta

theta =


   1.273005

   0.624876

   1.177376

  -2.020142

  -0.912616

  -1.429907

   0.125668

  -0.368551

  -0.360033

  -0.171068

  -1.460894

  -0.052499

  -0.618889

  -0.273745

  -1.192301

  -0.240993

  -0.207934

  -0.047224

  -0.278327

  -0.296602

  -0.453957

  -1.045511

   0.026463

  -0.294330

   0.014381

  -0.328703

  -0.143796

  -0.924883


   정리하면, 다항식을 사용하지 않은 경사 하강 알고리즘은 J =  0.69315이고, 다항식을 사용한 고급 최적화 알고리즘은 J = 0.52900입니다. 다항식을 사용하면 훨씬 더 최적화된 값을 얻을 수 있습니다.

  


2.4 Plotting the decision boundary

       (결정 경계 그리기)


   To help you visualize the model learned by this classifier, we have provided the function plotDecisionBoundary.m which plots the (non-linear) decision boundary that separates the positive and negative examples. In plotDecisionBoundary.m, we plot the non-linear decision boundary by computing the classifier’s predictions on an evenly spaced grid and then and drew a contour plot of where the predictions change from y = 0 to y = 1.

   After learning the parameters θ, the next step in ex reg.m will plot a decision boundary similar to Figure 4.


  분류기가 학습한 모델을 시각화하기 위해 plotDecisionBoundary.m 파일을 제공합니다. plotDecisionBoundary.m 파일은 분류기의 예측을 균일한 간격의 그리드로 계산하여 비선형 결정 경계를 등고선으로 도식화합니다. 


   파라미터  θ를 학습하고 ex_reg.m 에서 그림 4와 유사한 결정 경계를 그립니다.


<해설>


(1) 기존의 변수를 그대로 사용합니다. 


(2) plotDecisionBoundary.m 파일 열기


function plotDecisionBoundary(theta, X, y)

%PLOTDECISIONBOUNDARY 데이터에 적합한 결정 경계를 표시 

%   PLOTDECISIONBOUNDARY(theta, X,y) 

%   파지티브 예제는 +로 네거티브 예제는 O로 표시한 데이터를 그림

%   X는 다음 두 가지 경우 

%   1) Mx3 행렬, 첫 열은 모두 1인 인터셉트 항  

%   2) MxN 행렬 (N이 3보다 큼), 첫 열은 모두 1인 인터셉트 항 


% plotData 함수를 호출하여 데이터 도식화 

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

hold on


if size(X, 2) <= 3              % 행렬 X의 열이 3보다 작거나 같다면 실행


   % X 축의 최소값과 최대값을 구하고, 보기 좋게 2의 값을 빼거나 더함

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

          

    % x의 좌표에 대한 y 좌표의 값을 구함 (가설 h(x)를 좌표 y값을 구하도록 변형)

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


    % 두 개의 좌표를 연결하는 직선을 그림

     % plot_x와 plot_y는 각각 2 X 1 열 벡터 

    plot(plot_x, plot_y)    


    % 범례를 표시하고 축의 값을 표시 

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

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


else    % 행렬 X의 열이 3보다 크다면 실행 


    % 그리드(격자무늬)의 범위를 표시 

    u = linspace(-1, 1.5, 50);        % -1부터 1.5까지 50개의 간격으로 나눔  

    v = linspace(-1, 1.5, 50);        % -1부터 1.5까지 50개의 간격으로 나눔 


    z = zeros(length(u), length(v));      % 50 X 50 행렬을 0으로 초기화  


    % 각 좌표에 가설을 입력 를 

    for i = 1:length(u)

        for j = 1:length(v)


              %  2차원 피처를 28차원으로 확대하여 hθ(x) = x *theta의 값을 좌표에 입력

            z(i,j) = mapFeature(u(i), v(j))*theta;

        end

    end


    z = z';     % 50 X 50 행렬의 z를 전치하여 데이터의 위치를 확인


    contour(u, v, z, [0, 0], 'LineWidth', 2).    % 등고선을 그림


end

hold off


end



실행하면 다음과 같은 결과를 얻을 수 있습니다.




(3) For 루프를 이해하기 


u = linspace(-1, 1.5, 50);       

v = linspace(-1, 1.5, 50);  

z = zeros(length(u), length(v));   


50 X 50차원 행렬 z가 준비되었습니다. 


    for i = 1:length(u)

        for j = 1:length(v)

            z(i, j) = mapFeature(u(i), v(j))*theta;

        end

    end


   mapFeature(u(i), v(j))는 1 X 28차원의 다항식으로 듭니다. mapFeature에 28 X1 차원의 행렬 theta를 곱하면 가설 z를 얻을 수 있습니다. 


   즉, 등고선을 그래프를 그리는 방법은 다음과 같습니다.

1) 그림 영역을 50 X 50 개의 구역으로 나누면 좌표값은 피처 x1과 x2. 

2) 각 좌표를 28차원의 선형 회귀 가설을 변환 (mapFeature(u(i),v(j))

3) 파라미터  θ의 값과 x를 알고 있으므로 가설 hθ(x)를 계산 (mapmapFeature(u(i),v(j))*theta

4) For 루프를 이용하여 모든 좌표에 가설 값을 입력 


변수 z는 50 X 50차원 행렬입니다. 


(4)  contour ()함수 이해하기 


   변수 z를 그리기 위해 contour () 함수를 활용합니다. contour() 함수는  2차원 등고선을 그리는 함수입니다. 다음과 같이 사용합니다.


contour(z)     % 행렬 z를 등고선으로 그림


 

contour (u, v, z)   % x는 x 축의 좌표, y는 y 축의 좌표, z는 z 행렬



contour (u, v, z, [0,0])   % [0,0]은 좌표 (0,0)을 중심으로 등고선을 그림



contour (u, v, z, [0,0,], 'LineWidth', 5)   % 등고선의 굶기를 5로 지정. plot 함수와 동일




<정답>


(1) 기존 변수를 그대로 활용


(2) 추가적인 변수를 선언


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

hold on


u = linspace(-1, 1.5, 50);       

v = linspace(-1, 1.5, 50);  

z = zeros(length(u), length(v));   


    for i = 1:length(u)

        for j = 1:length(v)

            z(i,j) = mapFeature(u(i), v(j))*theta;

        end

    end


z = 

contour (u, v, z, [0,0,], 'LineWidth', 5)


title(sprintf('lambda = %g', lambda));

xlabel('Microchip Test 1');

ylabel('Microchip Test 2');

legend('y = 1', 'y = 0', 'Decision boundary');

hold off;






2.5 Optional (ungraded) exercises (선택 실습)


   In this part of the exercise, you will get to try out different regularization parameters for the dataset to understand how regularization prevents over- fitting.

Notice the changes in the decision boundary as you vary λ. With a small λ, you should find that the classifier gets almost every training example correct, but draws a very complicated boundary, thus overfitting the data (Figure 5). This is not a good decision boundary: for example, it predicts that a point at x = (−0.25, 1.5) is accepted (y = 1), which seems to be an incorrect decision given the training set.

   With a larger λ, you should see a plot that shows an simpler decision boundary which still separates the positives and negatives fairly well. How- ever, if λ is set to too high a value, you will not get a good fit and the decision boundary will not follow the data so well, thus underfitting the data (Figure 6).


   이번 실습의 목적은 정규화가 과적합을 방지하는 방법을 이해하는 것입니다. 데이터 셋에 여러 가지 정규화 파라미터 λ의 값을 변경했을 때 결정 경계가 어떻게 바뀌는 지를 시험합니다. 

   정규화 파라미터 λ가 작으면 분류기는 제대로 동작하지만 매우 복잡한 결정 경계를 만듭니다. (그림 5는 좋은 결정 경계가 아닙니다. 예를 들어, x = (-0.25, 1.5) 지점에서 y=1 로 예측하지만 학습 셋과 다른 잘못된 결정입니다. 

   정규화 파라미터 λ가 크면 파지티브 예제와 네거티브 예제를 잘 구분하는 더 간단한 결정 경계를 표시합니다. 하지만, 정규화 파라미터의 값이 너무 높은 값일 때는  그림 6와 같이 데이터 셋과 잘 맞지 않고 결정 경계가 데이터를 잘 따르지 않아 데이터가 과소 적합합니다. 


<해설>


(1) 정확도 측정

   학습 데이터 셋에 가설을 적용하여 정확도를 측정합니다. 


p = zeros(m,1);

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

p(index,1) = 1;     


pos = find (p == y);

P1 = size(pos,1) /m *100


따라서 결과는 다음과 같습니다. 

P1 =  83.051



(2) 정규화 파라미터  λ = 0 일 때 도식화


정규화 파라미터의 값을 변경하고 비용과 기울기를 계산하고 정규화된 고급 최적화 알고리즘을 사용합니다.


lambda = 0;

[J, grad] = costFunctionReg(theta, X, y, lambda)


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

 [theta, J, exit_flag] = ...

 fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options)


그래프를 그립니다. 


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

hold on


u = linspace(-1, 1.5, 50);       

v = linspace(-1, 1.5, 50);  

z = zeros(length(u), length(v));   


    for i = 1:length(u)

        for j = 1:length(v)

            z(i,j) = mapFeature(u(i), v(j))*theta;

        end

    end


contour (u, v, z, [0,0,], 'LineWidth', 5)


title(sprintf('lambda = %g', lambda));

xlabel('Microchip Test 1');

ylabel('Microchip Test 2');

legend('y = 1', 'y = 0', 'Decision boundary');

hold off;


그림과 다른 이유는 벡터 z를 전치하지 않아 x1과 x2의 위치가 다릅니다. 전치합니다. 


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

hold on


u = linspace(-1, 1.5, 50);       

v = linspace(-1, 1.5, 50);  

z = zeros(length(u), length(v));   


    for i = 1:length(u)

        for j = 1:length(v)

            z(i,j) = mapFeature(u(i), v(j))*theta;

        end

    end


z = z';

contour (u, v, z, [0,0,], 'LineWidth', 5)


title(sprintf('lambda = %g', lambda));

xlabel('Microchip Test 1');

ylabel('Microchip Test 2');

legend('y = 1', 'y = 0', 'Decision boundary');

hold off;




그리고, 학습 데이터 셋에 대한 정확도를 측정합니다. 


p = zeros(m,1);

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

p(index,1) = 1;     


pos = find (p == y);

P1 = size(pos,1) /m *100


따라서 결과는 다음과 같습니다. 


P1 =  86.441



(3) 정규화 파라미터  λ = 100 일 때 도식화


정규화 파라미터의 값을 변경하고 비용과 기울기를 계산하고 정규화된 고급 최적화 알고리즘을 사용합니다.


lambda = 100;


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

 [theta, J, exit_flag] = ...

 fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options)


그래프를 그립니다. 


plotDecisionBoundary(theta, X, y)


title(sprintf('lambda = %g', lambda));

xlabel('Microchip Test 1');

ylabel('Microchip Test 2');

legend('y = 1', 'y = 0', 'Decision boundary');

hold off;




그리고, 학습 데이터 셋에 대한 정확도를 측정합니다. 


p = zeros(m,1);

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

p(index,1) = 1;     


pos = find (p == y);

P1 = size(pos,1) /m *100


따라서 결과는 다음과 같습니다. 

P1 =  61.017

매거진의 이전글 머신러닝 옥타브 실습 (2-3) : 로지스틱 회귀
작품 선택
키워드 선택 0 / 3 0
댓글여부
afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari