본문 바로가기
  • 조금 느려도, 꾸준히
Artificial Intelligence/Machine Learning

핸즈온 머신러닝(6) - 서포트 벡터 머신 1

by chan 2020. 1. 27.
반응형

Suppor Vector Machine

- 매우 강력한 다목적 머신러닝 모델 (선형/비선형 분류, 회귀, 이상치 탐색 등)

- 머신러닝에서 가장 인기 있는 모델

- 복잡한 분류 문제에 적합

- 소규모, 중간 규모의 데이터셋에 적합

 

 

 

# 선형 SVM 분류

예를 들어 두 가지 클래스를 구분하는 선형 SVM 분류기가 있다고 할 때, SVM 분류기의 결정 경계는 두 개의 클래스를 나누면서 제일 가까운 훈련 샘플로부터 가능한 한 멀리 떨어져 있으려 한다. 이러한 특성을 라지 마진 분류(large margin classification) 라고 함.

 

라지 마진 분류의 결정 경계는 결정 경계과 가장 가깝게 위치한 샘플에 의해 전적으로 결정된다( 즉 결정 경계와 비교적 먼 샘플은 아무런 영향을 미치지 못함). 이렇게 결정 경계와 가장 가깝게 위치한 샘플을 서포트 벡터(suppor vector)라고 한다.

 

* SVM 은 특성의 스케일에 민감함. 특성의 스케일을 조정하면 결정 경계가 훨씬 좋아진다.

 

 

 

 

 

# 소프트 마진 분류

 

만약 모든 샘플이 결정 경계 범위(도로)의 바깥쪽에 올바르게 분류되어 있다면 이를 하드 마진 분류 라고 한다. 

 

하드 마진의 문제점 

- 데이터가 선형적으로 구분될 수 있어야 제대로 작동

- 이상치에 민감함

--> 결정 경계 찾는것이 불가능하거나, 훈련 데이터셋에 과대적합되어 일반화가 잘 안될 수 있음

 

좀 더 유연한 모델을 위해 결정 경계 범위의 폭을 가능한 넓게 유지하는것과 마진 오류(margin violation, 샘플이 도로 중간이나 심지어 반대쪽에 있는 경우) 사이에 적절한 균형을 잡아야 함 --> 소프트 마진 분류

 

 

사이킷런의 SVM 모델에서는 C 하이퍼파라미터를 사용해 균형 조절이 가능하다.

C 값을 줄일 경우: 도로의 폭이 넓어지지만 마진 오류도 커짐

C 값을 늘릴 경우: 도로의 폭이 좁아지면서 마진 오류도 적어짐

 

 

 

다음은 사이킷런 LinearSVC 클래스를 사용한 붓꽃 데이터셋 Iris-Virginia 품종 감지 분류기를 훈련시킨 코드이다.

 

import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

iris = datasets.load_iris()
X = iris['data'][:,(2,3)] # 꽃잎 길이, 꽃잎 너비
y = (iris['target'] == 2).astype(np.float64) # Iris-Virginica

svm_clf = Pipeline([
                    ('scaler', StandardScaler()),
                    ('linear_svc', LinearSVC(C=1, loss='hinge')),
                  ])
svm_clf.fit(X,y)

 

* linearSVC 는 클래스에 대한 확률을 나타내는 predict_proba() 메서드를 제공하지 않음. SVC 모델은 probablilty = True 로 지정하면 predict_proba() 메서드를 제공.

* linearSVC 는 규제에 편향을 포함시키므로 훈련 세트에서 평균을 빼 중앙에 맞춰야 함. 또한 loss 매개변수를 'hinge'로 지정해야 함. 훈련 샘플보다 특성이 많지 않다면 성능 향상을 목적으로 dual 매개변수를 False 로 지정.

 

 

 

 

 

 

 

# 비선형 SVM 분류

 

선형적으로 분류할 수 없는 데이터셋을 다루는 방법 중 한가지는 앞에서도 설명한 다항 특성과 같은 특성을 더 추가하는 것이다. 사이킷런을 사용하여 이를 구현하려면 PolynomialFeatures, StandardScaler, LinearSVC 를 연결하여 Pipeline 을 만들면 좋다. 다음은 이를 moons 데이터셋에 적용한 코드이다.

 

 

from sklearn.datasets import make_moons
from sklearn.preprocessing import PolynomialFeatures

X,y = make_moons(n_samples=100, noise=0.15, random_state=42)

polynomial_svm_clf = Pipeline([
                               ('poly_features', PolynomialFeatures(degree=3)),
                               ('scaler', StandardScaler()),
                               ('svm_clf', LinearSVC(C=10, loss='hinge', max_iter=2000))
])

polynomial_svm_clf.fit(X,y)

 

 

 

 

 

 

 

# 다항식 커널

 

다항식 특성을 추가하는 것은 간단하고 잘 작동하지만 단점이 있다.

낮은 차수의 다항식: 매우 복잡한 데이터셋을 잘 표현하지 못함

높은 차수의 다항식: 굉장히 많은 특성을 추가하므로 모델을 느리게 만듦.

 

SVM 을 사용할 땐 커널 트릭(kernel trick) 이라는 수학적 기교를 적용할 수 있다. 이는 어떠한 특성도 추가하지 않으면서 다항식 특성을 많이 추가한 것과 같은 결과를 얻을 수 있는 엄청난 기법이다.

 

다음은 커널 트릭을 활용해 moons 데이터셋에서 테스트 해본 코드이다.

 

from sklearn.svm import SVC
poly_kernel_svm_clf = Pipeline([
                ('scaler', StandardScaler()),
                ('svm_clf',SVC(kernel='poly', degree=3, coef0=1, C=5)),
                # coef0 parameter = 높은 차수와 낮은 차수에 얼마나 영향을 받을지 결정
])
poly_kernel_svm_clf.fit(X,y)

 

위의 r 상수는 coef0 매개변수에 의해 결정된다

 

 

 

 

 

 

# 유사도 특성 추가

 

비선형 특성을 다루는 또 다른 기법은 각 샘플이 특정 랜드마크 와 얼마나 닮았는지 추정하는 유사도 함수 로 계산한 특성을 추가하는 것이다.

 

 

데이터 중 랜드마크를 설정하여 유사도 함수를 정의하고 모든 데이터에 대한 유사도 함수를 계산하여 도출된 함숫값을 특성으로 변수변환하여 나타내면 선형적으로 구분이 가능해진다.

 

 

위 그래프는 가우시안 방사 기저 함수(Radial Basis Function, RBF) 를 유사도 함수로 정의하였다.

 

가우시안 RBF

$$ \phi_\gamma (\mathrm{x}, \ell) = e^{(-\gamma \| \mathrm{x} - \ell \|^2)} $$

 

 

랜드마크를 선택하는 간단한 방법은 데이터셋에 있는 모든 샘플 위치에 랜드마크를 설정하는 것이다.

이렇게 설정하면 차원이 매우 커지고 변환된 훈련 세트가 선형적으로 구분될 가능성이 높지만, 단점은 훈련 세트에 있는 $n$ 개의 특성을 가진 $m$ 개의 샘플이 $m$ 개의 특성을 가진 $m$ 개의 샘플로 변환된다는 것이다. 훈련 세트가 매우 클 경우 동일한 크기의 아주 많은 특성이 만들어진다.

 

 

 

# 가우시안 RBF 커널 

 

유사도 특성 방식도 머신러닝 알고리즘에 유용하게 사용될 수 있다. 이때 역시 커널 트릭에 의해 특성을 추가하지 않고도 유사도 특성을 많이 추가한 것과 같은 비슷한 결과를 얻을 수 있다. 다음은 SVC 모델에 가우시한 RBF 커널을 적용한 코드이다.

 

rbf_kernel_svm_clf = Pipeline([
              ('scaler', StandardScaler()),
              ('svm_clf', SVC(kernel='rbf', gamma=5, C=0.001))
])
rbf_kernel_svm_clf.fit(X,y)

gamma를 증가시키면 종 모양의 그래프가 좁아져서 각 샘플의 영향 범위가 작아진다. 따라서 결정 경계가 더 불규칙해지고 각 샘플을 따라 구불구불하게 휘는 모습을 볼 수 있다. 

 

모델이 과대적합일 경우 하이퍼파라미터 gamma를 감소시켜야 하며 과소적합일 경우 증가시켜야 한다.

 

 

 

 

 

 

# 계산 복잡도

 

LinearSVC 파이썬 클래스는 선형 SVM 을 위한 최적화된 알고리즘을 구현한 liblinear 라이브러리를 기반으로 하며, 훈련 샘플 수와 특성 수에 거의 선형적으로 늘어난다. 

 

정밀도를 높이면 알고리즘의 수행 시간이 길어지며 허용오차 하이퍼파라미터 $\varepsilon$ 으로 조절한다. (사이킷런에서 매개변수 tol, 기본값 0.0001) 대부분의 분류 문제는 기본값에서 잘 작동한다.

 

 

SVC 는 커널 트릭 알고리즘을 구현한 libsvm 라이브러리를 기반으로 하며 훈련의 시간 복잡도는 특성 수에 샘플 수의 제곱에서 세제곱의 곱에 비례한다. 계산의 복잡성으로 인해 작거나 중간 규모의 훈련 세트에 잘 맞는다.

하지만 특성의 개수에는 선형적이며 희소 특성일 경우 잘 확장된다. 이때 알고리즘의 성능은 샘플이 가진 0이 아닌 특성의 평균 수에 비례한다.

 

파이썬 클래스 시간 복잡도 외부 메모리 학습 지원 스케일 조정 필요성 커널 트릭
LinearSVC $O(m\times n)$ 아니오 아니오
SGDClassifier $O(m \times n)$  아니오
SVC $O(m^2 \times n)$ ~ $O(m^3 \times n)$ 아니오

 

 

이미지 출저 : handson-ml 옮긴이 github

반응형

댓글