brunch

You can make anything
by writing

C.S.Lewis

by 라인하트 Jan 27. 2021

머신러닝 옥타브 실습(6-1): 서포트 벡터 머신 구현

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


Programming Exercise 6: 

Support Vector Machine (서포트 벡터 머신) 


1. Support Vector Machine (서포트 벡터 머신)  


   In the first half of this exercise, you will be using support vector machines (SVMs) with various example 2D datasets. Experimenting with these datasets will help you gain an intuition of how SVMs work and how to use a Gaussian kernel with SVMs. In the next half of the exercise, you will be using support vector machines to build a spam classifier.

   The provided script, ex6.m, will help you step through the first half of the exercise.


   이번 실습의 전반부는 2차원 데이터셋을 활용하여 SVM의 동작 방식과 가우스 커널을 다룹니다. 후반부에서는 서포트 벡터 머신을 사용하여 스팸 분류기를 구현합니다. 

    이번 실습은  ex6.m 파일이 진행할 것입니다. 



1.1 Example Dataset 1 (데이터 셋 1)


   We will begin by with a 2D example dataset which can be separated by a linear boundary. The script ex6.m will plot the training data (Figure 1). In this dataset, the positions of the positive examples (indicated with +) and the negative examples (indicated with o) suggest a natural separation indicated by the gap. However, notice that there is an outlier positive example + on the far left at about (0.1, 4.1). As part of this exercise, you will also see how this outlier affects the SVM decision boundary.


   여기 선형 경계로 분리될 수 있는 2차원 데이터셋이 있습니다.  ex6.m 파일은 학습 데이터를 그림 1과 같이 표시합니다. 데이터 셋에서 파지티브 예제는 +로 표시하고 네거티브 예제는 O로 표시합니다. 이진 분류 예제는 자연스럽게 분리되어 있지만, (0.1, 4.1) 좌표에 특이한 파지티브 예제가 하나 있습니다. 실습에서 이상 예제가 SVM 결정 경계에 어떤 영향을 미치는 지를 확인할 수 있습니다. 



   In this part of the exercise, you will try using different values of the C parameter with SVMs. Informally, the C parameter is a positive value that controls the penalty for misclassified training examples. A large C parameter tells the SVM to try to classify all the examples correctly. C plays a role similar to 1 , where λ is the regularization parameter that we were using λ previously for logistic regression.


   실습에서 SVM과 함께 파라미터 C에 다양한 값을 사용합니다. 비공식적으로 파라미터 C는 잘못 분류된 학습 예제에 대한 페널티를 제어하는 파지티브 값입니다. SVM은 큰 값의 파라미터 C로 인해 올바르게 분류합니다. 파라미터 C는 1과 유사합니다. 여기서  λ는 로지스틱 회귀에서 사용했던 정규화 파라미터입니다. 


   The next part in ex6.m will run the SVM training (with C = 1) using SVM software that we have included with the starter code, svmTrain.m. When C = 1, you should find that the SVM puts the decision boundary in the gap between the two datasets and misclassifies the data point on the far left (Figure 2).


   C = 1 일 때 SVM은 svmTrain.m 파일을 시작 코드로 하는 SVM 소프트웨어를 사용하여 학습합니다. SVM은 그림 2와 같이 두 데이터셋 사이의 갭에 결정 경계를 그리지만, 왼쪽의 이상 예제를 잘못 분류합니다.  


   Implementation Note: 

   Most SVM software packages (including svmTrain.m) automatically add the extra feature x0 = 1 for you and au- tomatically take care of learning the intercept term θ0. So when passing your training data to the SVM software, there is no need to add this ex- tra feature x0 = 1 yourself. In particular, in Octave/MATLAB your code should be working with training examples x ∈ Rn (rather than x ∈ Rn+1); for example, in the first example dataset x ∈ R2.


   대부분의 svmTrain.m 파일의 SVM 소프트웨어 패키지는 자동으로 피처 x0 = 1을 추가하고 인터셉트 항 θ0를 처리합니다. 학습 데이터를 SVM 소프트웨어로 전달할 때 피처 x0 = 1을 직접 추가할 필요가 없습니다. 옥타브 프로그래에서 피처 x가 n차원일 때 동작합니다. 


   Your task is to try different values of C on this dataset. Specifically, you should change the value of C in the script to C = 100 and run the SVM training again. When C = 100, you should find that the SVM now classifies every single example correctly, but has a decision boundary that does not appear to be a natural fit for the data (Figure 3).


   C = 100 일 때 같은 데이터 셋에서 SVM 학습을 다시 실행합니다. SVM은 모든 예제를 올바르게 분류하지만 그림 3과 같이 데이터에 적합하지 않은 결정 경계를 그립니다.



<Part 1: 데이터 시각화>


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


clear ;             % 옥타브 프로그램에 모든 변수를 제거

close all;         % 터미널 이외의 창을 닫음

clc                   % 터미널을 깨끗이 정리 


load ('ex6data1.mat');    % 옥타브 프로그램으로 데이터 업로드 

[m,n] = size(X);                % 학습 예제의 수와 피처의 수를 정의 


(2) 데이터셋을 확인


>> ls

dataset3Params.m             plotData.m

emailFeatures.m                 porterStemmer.m

emailSample1.txt                processEmail.m

emailSample2.txt                readFile.m

ex6.m                                     spamSample1.txt

ex6.mlx                                  spamSample2.txt

ex6_companion.mlx           spamTest.mat

ex6data1.mat                       spamTrain.mat

ex6data2.mat                       submit.m

ex6data3.mat                       svmPredict.m

gaussianKernel.m               svmTrain.m

getVocabList.m                   visualizeBoundary.m

lib                                          visualizeBoundaryLinear.m

linearKernel.m                    vocab.txt


>> load ('ex6data1.mat')

>> whos

Variables in the current scope:


   Attr Name        Size                     Bytes  Class

   ==== ====        ====                     =====  =====

        X                   51x2                        816  double

        y                   51x1                        408  double


Total is 153 elements using 1224 bytes


(3) 데이터셋을 도식화


   로지스틱 회귀 실습에서 이진 분류 예제를 그리기 위해 plotData.m 파일 작성했습니다. 


plotData(X,y);



(4)plotData.m 파일 분석


   이미 직접 작성했던 파일이지만 다시 한번 기억을 되살리는 의미에서 파일을 분석합니다.



function plotData(X, y)

%. PLOTDATA  데이터를 도식화  

%   PLOTDATA(x,y) 파지티브 예제는 + 표시, 네거티브 예제는 O로 표시

%   


% 새로운 그림 창을 생성하고 겹쳐서 그림

figure; hold on;


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

% Instructions:

%               파지티브 예제는 'k+' 옵션을, 네거티브 예제는 'ko' 옵션을 사용할 것

%              


positive = find (y==1);

negative = find(y==0);

plot (X(positive,1),X(positive,2),'k+','LineWidth',1,'MarkerSize', 7);

plot (X(negative,1),X(negative,2), 'ko','MarkerFaceColor','y', 'MarkerSize', 7);


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


hold off;   % 그림을 겹쳐서 그리는 것 해제 


end


   find() 함수는 인덱스를 반환합니다. 


>> find(y==1)       % y=1인 학습 예제의 인덱스를 반환

ans =

    1

    2

    3

    4

    5

    6

    ...

   20

   51


>> find(y==0).    y=0인 학습 예제의 인덱스를 반환

ans =

   21

   22

   23

   24

   25

   26

   27

   ...

   49

   50


   따라서, 데이터셋 X는 50 X 2차원 행렬입니다. y=1 일 때 인덱스 번호와 y=0일 때 인덱스 번호를 안다면 같은 인덱스 번호의 데이터셋 X의 값을 알 수 있습니다. 



<Part 2: 선형 SVM 학습하기>


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


clear ;             % 옥타브 프로그램에 모든 변수를 제거

close all;         % 터미널 이외의 창을 닫음

clc                   % 터미널을 깨끗이 정리 


load ('ex6data1.mat');    % 옥타브 프로그램으로 데이터 업로드 

[m,n] = size(X);                % 학습 예제의 수와 피처의 수를 정의 


(2) SVM 학습하기


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

   SVM 비용 함수의 상수 C의 값이 1일 때 학습을 합니다. 


C = 1;


    가설 모델을 계산하기 위해 svmTrain.m 파일을 이용합니다.  svmTrain.m 파일은 이미 구현이 되어 있습니다. 매우 복잡하게 설계되어 있으므로 분석은 하지 않습니다. 


model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);


>> C = 1;

>> model = svmTrain(X, y, C, @linearKernel, 1e-3, 20)

Training ......................................................................

...................... Done!

model =

  scalar structure containing the fields:

    X =

       3.577200   2.856000

       3.104800   3.070900

       1.918200   4.053400

       2.655500   3.500800

       3.035700   3.316500

       1.584100   3.357500

       2.010300   3.203900

       1.952700   2.784300

       2.309900   2.958400

       2.828300   2.630900

       1.319100   3.510900

       2.540300   2.886700

       0.086405   4.104500


    y =

       1

       1

       1

       1

       1

      -1

      -1

      -1

      -1

      -1

      -1

      -1

       1


    kernelFunction = @linearKernel

    b = -10.245

    alphas =

       1.0000e+00

       1.0000e+00

       5.3742e-01

       1.0000e+00

       9.3386e-01

       1.0000e+00

       1.0000e+00

       5.5511e-17

       1.0000e+00

       1.0000e+00

       4.7128e-01

       1.0000e+00

       1.0000e+00


    w =

       1.3951

       2.1157


 

(3)linearKernel.m 파일 분석


   

function sim = linearKernel(x1, x2)

%LINEARKERNEL x1과 x2 사이의 선형 커널을 반환 

%   sim = linearKernel(x1, x2) 은 x1과 x2 사이의 선형 커널(유사도) sim 반환 


% 행벡터 x1과 x2를 열벡터로 변환

x1 = x1(:); x2 = x2(:);


% 커널을 계산하기 위해 두 식의 벡터의 내적을 계산

sim = x1' * x2;  % dot product


end



   SVM 학습에서 linearKernel.m 파일을 가리키는 포인터가 있습니다. 이 파일은 간단하게 분석합니다.


model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);



(4) visualizeBoundaryLinearl.m 파일 분석


function visualizeBoundaryLinear(X, y, model)

%VISUALIZEBOUNDARYLINEAR   SVM이 학습한 선형 결정 경계를 그림

%   VISUALIZEBOUNDARYLINEAR(X, y, model) 

%   데이터셋 X와 분류 y의 값에 의한 데이터를 시각화하고, SVM이 학습한 결정 경계를 그림


w = model.w;

b = model.b;

xp = linspace(min(X(:,1)), max(X(:,1)), 100);

yp = - (w(1)*xp + b)/w(2);

plotData(X, y);

hold on;

plot(xp, yp, '-b'); 

hold off


end


   여기서 변수 model은  svmTrain.m 파일이 데이터셋 X와 y를 학습 결과입니다. 변수 model은 여러 개의 하위 변수를 가집니다. 그중에 model.w는 파라미터 θ의 가중치이고, model.b는 바이어스 항입니다. 다음의 결과를 나타냅니다. 


>> model.w

ans =

   1.3951

   2.1157


>> model.b

ans = -10.245


   linspace() 함수는 처음 값과 마지막 값 사이를 100 등분한 값을 반환합니다. 


>>  linspace(1,2)

ans =

 Columns 1 through 7:

   1.0000   1.0101   1.0202   1.0303   1.0404   1.0505   1.0606


 Columns 8 through 14:

   1.0707   1.0808   1.0909   1.1010   1.1111   1.1212   1.1313


...


 Columns 92 through 98:

   1.9192   1.9293   1.9394   1.9495   1.9596   1.9697   1.9798


 Columns 99 and 100:

   1.9899   2.0000


>> linspace(1,2,10)

ans =

 Columns 1 through 7:

   1.0000   1.1111   1.2222   1.3333   1.4444   1.5556   1.6667


 Columns 8 through 10:

   1.7778   1.8889   2.0000 


  수평축을 나타내는 첫 번째 열의 값 중 최소값과 최대값 사이를 100 등분한 값을 반환받기 위해 linspace() 함수를 사용합니다. 


xp = linspace(min(X(:,1)), max(X(:,1)), 100);


그리고, 수평축의 값에 따른 수직축의 값을 구하기 위해 가설을 적용합니다. 즉, 가설 hθ(x) = θ1x1 + θ2*x2 = 0에서 x2의 값을 구하는 식을 만듭니다. 


hθ(x) = θ1x1 + θ2*x2 + b= 0  

              θ2*x2 = - (θ1x1 + b)

                    x2 = - (θ1x1+b)/θ2


   이것을 옥타브 프로그램에서 수식을 정리합니다. 특히, θ1은 벡터 w의 첫 번째 성분인 w(1)이고 θ2는 벡터 w의 두 번째 성분인 w(2)입니다. 


yp = - (w(1)*xp + b)/w(2);



(4) 학습한 SVM의 결정 경계 그리기


   그리고 결정 경계를 도식화합니다. 



w = model.w;

b = model.b;

xp = linspace(min(X(:,1)), max(X(:,1)), 100);

yp = - (w(1)*xp + b)/w(2);


plot(xp, yp);




(5) 데이터셋과 선형 결정 경계 그리기 (C = 1)


   로지스틱 회귀 실습에서 결정 경계를 그리는 법을 다루었습니다. 이미 구현된 visualizeBoundaryLinear.m 파일을 이용하여 그립니다. 



C = 1;

model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);

visualizeBoundaryLinear(X, y, model);



(6) 데이터셋과 선형 결정 경계 그리기 (C = 100)


   로지스틱 회귀 실습에서 결정 경계를 그리는 법을 다루었습니다. 이미 구현된 visualizeBoundaryLinear.m 파일을 이용하여 그립니다. 



C = 100;

model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);



>> C = 100;

>> model = svmTrain(X, y, C, @linearKernel, 1e-3, 20);


Training ................................................................................................................................................................................................................................................................................

...................................................................................................................................... Done!


>> model

model =

  scalar structure containing the fields:


    X =

       3.577200   2.856000

       4.015000   3.193700

       3.600200   3.122100

       2.010300   3.203900

       1.491900   2.027100

       0.812200   2.999200

       1.319100   3.510900

       0.086405   4.104500


    y =

       1

       1

       1

      -1

      -1

      -1

      -1

       1


    kernelFunction = @linearKernel

    b = -35.756

    alphas =

       2.3906e+01

       8.3267e-17

       6.5919e-16

       9.4278e-01

       8.3267e-17

       1.7434e-16

       6.3612e+01

       4.0649e+01


    w =

       3.2220

       8.7629



>> visualizeBoundaryLinear(X, y, model);




매거진의 이전글 머신러닝 옥타브 실습(5-3): 댐의 방수량 예측
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari