비선형 SVM의 분류 방법

선형 SVM 분류기가 효율적이고 많은 경우에 아주 잘 작동하지만, 선형적으로 분류할 수 없는 데이터셋이 더 많습니다. 

비선형 데이터셋을 다루는 한 가지 방법은 다항 특성과 같은 특성을 더 추가하는 것입니다. 이렇게 하면 선형적으로 구분되는 데이터셋이 만들어질 수 있습니다.


< Fig. 1. 특성을 추가하여 선형적으로 구분되는 데이터셋 만들기 예제 >


Fig. 1의 왼쪽 그래프는 하나의 특성 𝑥₁만을 가진 가장 간단한 데이터셋을 나타냅니다. 그림에서 볼 수 있듯이 이 데이터셋은 선형적인 구분이 불가능합니다.

하지만 두 번째 특성 𝑥₂ = (𝑥₁)²을 추가하여 만들어진 2차원 데이터셋은 완벽하게 선형적으로 구분할 수 있습니다.


사이킷런을 사용하여 이를 구현하려면 PolynomialFeatures 변환기와 StandardScaler, LinearSVC를 연결하여 Pipeline을 만들면 좋습니다.

아래의 예제는 moons 데이터셋에 위 3가지를 적용한 것입니다.

Code

from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
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"))
])

polynomial_svm_clf.fit(X, y)



1. 다항식 커널 (Polynomial Kernel)

다항식 특성을 추가하는 것은 간단하고 모든 머신러닝 알고리즘에서 잘 작동합니다. 하지만, 낮은 차수의 다항식은 매우 복잡한 데이터셋을 잘 표현하지 못하고 높은 차수의 다항식은 굉장히 많은 특성을 추가하므로 모델을 느리게 만듭니다.

다행히도 SVM을 사용할 땐 커널 트릭(Kernel Trick)이라는 거의 기적에 가까운 수학적 기교를 적용할 수 있습니다. 실제로는 특성을 추가하지 않으면서 다항식 특성을 많이 추가한 것과 같은 결과를 얻을 수 있습니다. 사실 어떤 특성도 추가하지 않기 때문에 엄청난 수의 특성 조합이 생기지 않습니다. 이 기법은 SVC 파이썬 클래스에 구현되어 있습니다.

Code

from sklearn.svm import SVC
import matplotlib.pyplot as plt
import mglearn

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


poly_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))

])

poly_kernel_svm_clf.fit(X, y)


poly_kernel_svm_clf2 = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=10, coef0=100, C=5))

])

poly_kernel_svm_clf2.fit(X, y)


mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
mglearn.plots.plot_2d_separator(poly_kernel_svm_clf, X)
plt.show()


mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
mglearn.plots.plot_2d_separator(poly_kernel_svm_clf2, X)
plt.show()

Output


< d = 3, 𝛾 = 1, C = 5 >


< d = 10, 𝛾 = 100, C = 5 >



2. 유사도 특성 추가

비선형 특성을 다루는 또 다른 기법은 각 샘플이 각 특정 랜드마크와 얼마나 닮았는지 측정하는 유사도 함수(Similarity Function)로 계산한 특성을 추가하는 것입니다. 예를 들어 앞에서 본 1차원 데이터셋에 두 개의 랜드마크 𝑥₁ = -2와 𝑥₁ = 1을 추가합시다. 그리고 𝛾 = 0.3인 가우시안 방사 기저 함수(Radical Basis Function, RBF)를 유사도 함수도 정의하겠습니다.

< Exp. 1. 가우시안 RBF >


이 함수의 값은 0부터 1까지 변화하며 종 모양으로 나타납니다. 이제 새로운 특성을 만들 준비가 되었습니다. 예를 들어 𝑥₁ = -1 샘플을 살펴봅시다. 이 샘플은 첫 번째 랜드마크에서 1만큼 떨어져 있고 두 번째 랜드마크에서 2만큼 떨어져 있습니다. 그러므로 새로 만든 특성은 𝑥₂ = exp(-0.3 × 1²) ≈ 0.74와 𝑥₃ = exp(-0.3 × 2²) ≈ 0.30입니다. Fig. 1.의 오른쪽 그래프는 변환된 데이터셋을 보여줍니다.



< Fig. 1. 가우시안 RBF를 사용한 유사도 측정 >


위와 같이 변환하면 이제 선형적으로 구분이 가능합니다. 랜드마크는 어떻게 선택할까요? 간단한 방법은 데이터셋에 있는 모든 샘플 위치에 랜드마크를 설정하는 것입니다. 이렇게 하면 차원이 매우 커지고 따라서 변환된 훈련 세트가 선형적으로 구분될 가능성이 매우 높습니다. 단점은 훈련 세트에 있는 n개의 특성을 가진 m개의 샘플이 m개의 특성을 가진 m개의 샘플로 변환된다는 것입니다. 훈련 세트가 매우 클 경우 동일한 크기의 아주 많은 특성이 만들어집니다.



3. 가우시안 RBF 커널 (Gaussian RBF Kernel)

다항 특성 방식과 마찬가지로 유사도 특성 방식도 머신러닝 알고리즘에 유용하게 사용될 수 있습니다. 추가 특성을 모두 계산하려면 연산 비용이 많이 드는데 특히 훈련 세트가 클 경우 더 그렇습니다. 하지만 커널 트릭이 한 번 더 SVM의 마법을 만듭니다. 유사도 특성을 많이 추가하는 것과 같은 비슷한 결과를 실제로 특성을 추가하지 않고 얻을 수 있습니다. SVC 모델에 가우시안 RBF 커널을 적용해보도록 하겠습니다.

Code

gamma_lst = [0.1, 0.1, 5, 5]
C_lst = [0.001, 1000, 0.001, 1000]

for g, c in zip(gamma_lst, C_lst):
rbf_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="rbf", gamma=g, C=c))
])

rbf_kernel_svm_clf.fit(X, y)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
mglearn.plots.plot_2d_separator(rbf_kernel_svm_clf, X)
plt.show()

Output


< 𝛾 = 0.1, C = 0.001 >


< 𝛾 = 0.1, C = 1000 >


< 𝛾 = 5, C = 0.001 >


< 𝛾 = 5, C = 1000 >

각각의 그래프를 살펴보면 𝛾를 증가시키면 종 모양 그래프가 좁아져서 각 샘플의 영향 범위가 작아집니다. 결정 경계가 조금 더 불규칙해지고 각 샘플을 따라 구불구불하게 휘어집니다. 반대로 작은 𝛾의 값은 넓은 종 모양 그래프를 만들며 샘플이 넓은 범위에 걸쳐 영향을 주므로 결정 경계가 더 부드러워집니다. 결국 하이퍼파라미터 𝛾가 규제의 역할을 합니다. 모델이 과대적합일 경우엔 감소시켜야하고 과소적합인 경우엔 증가시켜야 합니다. 



References

  • https://tensorflow.blog/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D/2-3-7-%EC%BB%A4%EB%84%90-%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0/
  • 오렐리앙 제롱, '핸즈온 머신러닝', 한빛미디어, 2018



선형 SVM의 분류 방법


1. 라지 마진 분류 (Large Margin Classification)

< Fig. 1. Large Margin Classification >


Fig. 1은 붓꽃 데이터셋의 일부를 나타낸 그림입니다. 두 클래스가 직선으로 확실히 잘 나뉘어 진 것을 확인할 수 있습니다.

왼쪽 그래프에 세 개의 선형 분류기에서 만들어진 결정 경계를 확인할 수 있습니다. 점선으로 나타난 결계는 클래스를 적절히 분류하지 못하고 있습니다.

다른 두 모델은 훈련 세트에 완벽하게 동작합니다. 하지만, 결정 경계가 샘플에 너무 가까워 새로운 샘플에 대해서는 아마 잘 작동하지 못할 것입니다.


오른쪽 그래프에 있는 실선은 SVM 분류기의 결정 경계입니다. 이 직선은 두 개의 클래스를 나누고 있을 뿐만 아니라 제일 가까운 훈련 샘플로부터 가능한 한 멀리 떨어져 있습니다.

SVM 분류기를 클래스 사이에서 가장 폭이 넓은 도로를 찾는 것으로 생각할 수 있습니다. 이를 라지 마진 분류라고 합니다.


도로 바깥쪽에 훈련 샘플을 더 추가해도 결정 경계에는 전혀 영향을 미치지 않습니다. 도로 경계에 위치한 샘플에 의해 전적으로 결정됩니다.

이런 샘플을 서포트 백터라고 합니다. (오른쪽 그래프의 동그라미로 표시된 부분)


2. 소프트 마진 분류(Soft Margin Classification)

모든 샘플이 도로 바깥쪽에 올바르게 분류되어 있다면 이를 하드 마진 분류라고 합니다.

하드 마진 분류에는 두 가지 문제점이 있습니다. 데이터가 선형적으로 구분될 수 있어야 제대로 작동하며, 이상치에 민감합니다.


< Fig. 2 이상치에 민감한 하드 마진 >


Fig. 2를 살펴보면 왼쪽 그래프에 이상치가 하나 있습니다. 왼쪽 그래프에서는 하드 마진을 찾을 수 없습니다.

오른쪽 그래프의 결정 경계는 이상치가 없던 Fig. 1과 매우 다르고 일반화가 잘 되지 않습니다.


이러한 문제를 피하기 위해서는 조금 더 유연한 모델이 필요합니다. 도로의 폭을 가능한 넓게 유지하는 것과 마진 오류(Margin Violation) 사이에 적절한 균형을 잡하야 합니다.

이를 소프트 마진 분류라고 합니다. 


< Fig. 3. 좁은 마진과 넓은 마진 >


사이킷런의 SVM 모델에서는 C 하이퍼파라미터를 사용해 이 균형을 조절할 수 있습니다. C값을 줄이면 도로의 폭이 넓어지지만 마진 오류도 커집니다. 

Fig. 3은 선형적으로 구분되지 않는 데이터셋에 두 개의 소프트 마진 SVM 분류기로 만든 결정 경계와 마진을 보여줍니다. 왼쪽 그래프에서는 큰 C 값을 사용해 분류기가 마진 오류를 적게 냈지만 마진이 좁아졌고, 오른쪽 그래프에서는 작은 C 값을 사용하여 마진이 넓어졌지만 많은 샘플이 도로 안에 포함되었습니다. 두 개의 그래프에서는 오른쪽에 있는 분류기가 더 잘 일반화될 것 같아 보입니다. 사실 대부분의 마진 오류는 결정 경계를 기준으로 올바른 클래스로 분류되기 때문에 이 훈련 세트에서 예측 에러는 마진 오류보다 적습니다.


아래의 코드는 붓꽃 데이터를 적재하고, 특성 스케일을 변경하고, Iris - Virginia 품종을 감지하기 위해 선형 SVM 모델을 훈련시킵니다.

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)

svm_clf = Pipeline([
("scaler", StandardScaler()),
("linear_svc", LinearSVC(C=1, loss="hinge"))
])

svm_clf.fit(X, y)

print(svm_clf.predict([[5.5, 1.7]]))

> array([1.])


여기에서는 선형 SVM 분류기를 훈련시키기 위해 일반적인 확률적 경사 하강법을 적용합니다.

LinearSVC만큼 빠르게 수렴하지는 않지만 데이터셋이 아주 커서 메모리에 적재할 수 없거나, 

온라인 학습으로 분류 문제를 다룰 때는 유용합니다.



SVM (Support Vector Machine)

서포트 벡터 머신(SVM)은 매우 강력하고 선형, 비선형 분류, 회귀, 이상치 탐색에도 사용할 수 있는 다목적 머신러닝 모델입니다.
두 카테고리 중 어느 하나에 속한 데이터의 집합이 주어졌을 때, 주어진 데이터 집합을 바탕으로 새로운 데이터가 어느 카테고리에 속할지 판단하는 모델입니다.
SVM은 특히 복잡한 분류 문제에 잘 들어맞으며 작거나 중간 크기의 데이터셋에 적합합니다.

SVM의 분류 방법

< Fig. 1. SVM 분류 예시 1 >


Fig. 1을 보면 '빨간 원'과 '녹색 사각형'을 구분하는 3개의 직선 (Line 1 ~ 3)이 있는 것을 확인할 수 있습니다.

SVM에서는 어떠한 선을 사용하여 구분할까? 정답은 Line 2입니다.


< Fig. 2. SVM 분류 예시 2 >


Fig. 2를 보면 마찬가지로 '빨간 원'과 '녹색 사각형'을 구분하는 3개의 직선 (Line 1 ~ 3)이 있는 것을 확인할 수 있습니다.

SVM에서는 어떠한 선을 사용하여 구분할까요? 아마도 Line 2를 선택할 것이다. 왜냐하면, SVM에서는 Margin이 가장 큰 Line을 사용하기 때문이다. 여기서 Margin이란 Boundary(Line)에 가까이 있는 요소(Element)에서 Boundary까지 거리의 합을 의미합니다. (얼마나 가까이에 있는 원소까지 사용할 것인지는 Parameter 설정에 따릅니다.)

또한, 강건함(Robust) 관점에서 Line 1과 Line 3은 적절하지 않다. Line 1의 경우 왼쪽 위의 빨간 원의 위치가 조금 바뀌면 Boundary를 넘어 다른 Label을 침범하게 됩니다.


< Fig. 3. SVM 분류 예시 3 >


그렇다면 Fig. 3에서는 어떨까? '빨간 원' 원소 중 하나가 '초록 사각형' 원소들 가까이 위치하고 있습니다.

여기에서는 Line 1을 선택하게 됩니다. SVM은 먼저 Classification 한 다음 Margin이 가장 큰 선을 선택하기 때문입니다.


< Fig.  4. SVM의 Outlier 예시 >


Fig. 4에서는 SVM에서의 Outlier를 표현하는 그래프가 나타나있다. 빨간 원 중 하나가 초록 사각형 사이에 분포하고 있습니다.

여기에서는 어떠한 선을 선택하게 될까요? 정답은 Line 1입니다. 선형 SVM은 Outlier를 어느정도 무시하며 최선의 선택을 진행합니다.


References

  • http://hiuaa.tistory.com/78
  • 오렐리앙 제롱, '핸즈온 머신러닝', 한빛미디어, 2018


+ Recent posts