ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SVM의 개념 및 Python에서의 사용
    Programming & Machine Learning/Python X 머신러닝 2017. 8. 10. 03:26

    SVM (Support Vector Machine)

    1. SVM의 원리

    SVM은 퍼셉트론을 확장한 개념으로, 데이터를 선형으로 분리하는 최적의 선형 결정 경계를 찾는 알고리즘이다.
    SVM은 선형 분류와 더불어 비선형 분류에서도 사용될 수 있다. 
    
    SVM에서 비선형 분류를 하기 위해서 주어진 데이터를 고차원 특징 공간으로 사상하는 작업이 필요한데, 
    이를 효율적으로 하기 위해 커널 트릭을 사용하기도 한다.
    만약 훈련 데이터가 비선형 데이터라면, 이를 비선형 매핑(Mapping)을 통하여 고차원으로 변환시킨 뒤, 
    새로운 차원에서의 최적의 결정 경계면을 찾는다. 이것이 커널 트릭을 사용한 것이다.
    
    SVM을 나타낸 것이 위의 그림이다.
    위의 그림은 두 분류를 하나의 결정 경계로 나눈 그림이다. 위에서는 두 개의 분류 경계면이 존재하는데, 
    margin이 더 많이 남는 경계가 당연히 더 좋다. 새로운 데이터를 분류한다고 할 때 여유공간이 많기 때문이다.
    SVM은 이러한 마진을 최대로 하는 분류 경계면(초평면)을 찾는 알고리즘이라고 생각하면 된다.
    그리고 margin을 결정하게 되는, 초평면(결정 경계면)과 가장 가까운 훈련용 샘플들이 바로 서포트 벡터이다.
    (위의 그림에서 빨간 동그라미가 쳐져있는 샘플들)
    
    초평면의 마진이 크면 클 수록, 낮은 일반화 오차를 갖는 경향이 있다는 것이고, 작은 마진을 가진 초평면의 경우는
    오버피팅의 경향이 조금 더 크다는 것을 의미한다.
    
    입력 데이터가 선형 분리가 가능하지 않을 때는, 앞서 말한 것 처럼
    비선형 데이터의 초평면을 최적으로 분리하기 위해서 SVM에서는 더 높은 차원으로 비선형 매핑을 하게된다.
    이 이유는 다음의 그림으로 쉽게 이해할 수 있다.
    

    위의 그림을 보면 왼쪽의 경우 2차원에서는 선형 분리가 불가능하다. 하지만 이 데이터들을 3차원으로
    매핑시키면 오른쪽처럼 분리가 가능해지는 마법을 볼 수 있다. 이러한 과정을 거쳐 비선형 영역을 선형으로 분리한다.
    

    2. 초평면을 찾는 원리와 라그랑즈 승수법

    초평면은 마진을 최대로 하는 것이 기본적인 대전제라고 할 수 있다.
    그렇다면 어떻게 마진을 최대로 하는 초평면을 찾을 수 있는가?
    
    음의 하이퍼 평면과 양의 하이퍼 평면의 두 식을 하나로 합치고, 영역에 속한다는 조건 등에서
    나오는 변수들을 방정식으로 사용한다. 이때 방정식에 사용되는 변수들이 나오는 조건은
    아래의 그림과 같이 convex hull 안에 분류 데이터들을 넣어놓고, convex hull에서의 수직 벡터와
    새롭게 생성되는 초평면 사이의 가장 적절한 경계면이나 기울기를 찾아가는 과정에서 나온다.
    왜냐하면 조건을 만족하는 초평면은 무수히 많을 수 있기 때문에, convex hull등의 개념을 이용하여
    가장 적절한 초평면을 찾아가는 과정을 나오는 변수들을 방정식으로 사용해야 하기 때문이다.
    

    가장 효과적인 초평면을 찾아가면서 그룹간의 categorization을 할 때 발생하는 오류를 최소화해야 하는데,
    이 과정에서 라그랑즈 승수법이라는 것을 사용해서 가장 적절한 변수들을 찾는다.
    
    수학적으로 꽤나 복잡한 과정을 거친 후, 데이터의 convexity를 고려하면서 변수를 추출한다.
    그리고 이후에 라그랑즈 승수법을 적용하여 최적의 초평면을 찾는다는 정도만 알아두면 되겠다.
    

    여유변수 파라미터를 사용하여 선형 분리를 조절

    이제 여유변수라는 파라미터가 필요해지게 된다. 여유변수는 말 그대로, 비선형의 분리 가능 데이터를 위한
    선형 제약에 대한 여유값이다. SVM에서는 변수 C를 사용해서 오분류에 대한 벌칙을 제어할 수 있는데,
    C가 커진다면, 오분류에 대한 벌칙을 강하게 주는 것이고 작아진다면, 벌칙을 약하게 주는 것이다.
    
    위의 그림에서 왼쪽의 경우, C값을 크게 주어 오분류를 엄격하게 관리하고 있기 때문에
    굉장히 쪼잔한(?) 초평면을 그리게 된다. 반면 오른쪽은 오분류 하나쯤은 관대하게 넘어가기 때문에 훨씬 좋은 초평면을 그린다.
    즉, C값이 증가할수록 바이어스는 증가하게 되고, 모델의 분산은 작아진다는 것이다.
    
    이러한 관대한 SVM을 소프트 마진 분류법이라고 한다.
    

    3. 파이썬 코드의 구현

    아래의 파이썬 코드는, 선형 분리가 가능한 데이터에서의 SVM 분류 적용의 예시이다.
    
    from sklearn.svm import SVC
    
    svm = SVC(kernel='linear', C=1.0, random_state=0)
    # 로지스틱 회귀에서의 C와 반대의 개념. 모델을 조율해주는 값이라고 보면 됨.
    svm.fit(X_train_std, y_train)
    y_pred_svc = svm.predict(X_test_std)
    print('Accuracy: %.2f' % accuracy_score(y_test, y_pred_svc))
    
    import matplotlib.pyplot as plt
    import numpy as np
    
    np.random.seed(0)
    X_xor = np.random.randn(200, 2)
    y_xor = np.logical_xor(X_xor[:, 0] > 0,
                           X_xor[:, 1] > 0)
    y_xor = np.where(y_xor, 1, -1)
    
    plt.scatter(X_xor[y_xor == 1, 0],
                X_xor[y_xor == 1, 1],
                c='b', marker='x',
                label='1')
    plt.scatter(X_xor[y_xor == -1, 0],
                X_xor[y_xor == -1, 1],
                c='r',
                marker='s',
                label='-1')
    
    plt.xlim([-3, 3])
    plt.ylim([-3, 3])
    plt.legend(loc='best')
    plt.tight_layout()
    # plt.savefig('./figures/xor.png', dpi=300)
    plt.show()
    
    
    svm = SVC(kernel='rbf', C=10.0, random_state=0, gamma=0.10)
    svm.fit(X_xor, y_xor)
    y_pred_ksvc = svm.predict(X_xor)
    print('Accuracy: %.2f' % accuracy_score(y_xor, y_pred_ksvc))

    4. 비선형 데이터에서의 커널 트릭 사용

    SVM으로 문제를 해결함에 있어서, XOR 문제처럼 데이터가 비선형의 그룹 모양을 하고 있을 때,
    초평면을 이용하여 분리하는 것이 불가능한 경우가 있다.
    이 경우에 위에서 언급한 커널 트릭이라는 개념으로 해결이 가능하다.
    
    커널 트릭은, input data들을 특정 커널을 이용해서 새로운 output처럼 만들어내는 과정을 거친다.
    이 때, 새로운 data를 배출해내는 커널로써 RBF나 가우시안 커널을 주로 사용한다.
    
    위의 SVM 클래스를 사용하는 python 코드에서
    
    svm = SVC(kernel='linear', C=1.0, random_state=0)
    
    라고 되어있는 부분의 의미를 살펴보자. kernel='linear'라는 것의 의미는, 디폴트 커널 트릭이
    linear라는 것이다. 즉, 커널 트릭을 사용하지 않는다는 것과 일맥상통하다.
    커널 트릭을 사용하기 위해서는 kernel='rbf'와 같이 커널 파라미터만 바꿔주면 된다.
    
    svm = SVC(kernel='rbf', C=1.0, random_state=0, gamma=0.10)
    여기서 C 파라미터는 여유변수에 관한 파라미터이고, gamma는 커널 자체에 대한 파라미터로, 
    가우시안 구(Gaussian sphere)같은, 훈련 샘플의 영향력을 증가시키는 등의 역할을 하는 파라미터 계수이다.
    감마를 증가시키면 일반적으로 훈련 샘플의 영향력이 증가하고, 결정경계가 더욱 부드러워지게 된다.
    
    어찌되었든 결론적으로, SVM 알고리즘을 적용하여 분류문제를 해결하는 상황에서는 반드시 EDA 과정에서 
    데이터가 선형 분리가 가능한지 여부를 확인하고, 커널 트릭에 대해서 지정해줘야 한다.


    댓글

분노의 분석실 Y.LAB