SVM
서포트 벡터 머신(Support Vector Machine, SVM)은 매우 강력하며, 선형, 비선형 분류, 회귀, 특이치 탐지 등에 폭넓게 사용할 수 있다. 다만 매우 큰 dataset으로는 잘 확장되지 않는다.
선형 SVM 분류
왼쪽 모델은 주어진 샘플에 대해서는 완벽하지만, 결정 경계가 너무 가까워서 새로운 샘플에 대해서 잘 작동할 수 없다. 하지만 오른쪽 모델은 경계가 클래스를 잘 구분할 뿐만 아니라 샘플로부터 멀어서, 새로운 샘플이 들어오더라도 잘 작동할 것으로 보인다. 이처럼 SVM 분류기는 클래스 사이에 가장 폭이 넓은 도로를 찾는 문제(large margin classification)라고 할 수 있다.
위 그림에서 회색으로 표시된 샘플과 같이 경계에 위치한 샘플을 서포트 벡터(support vector)라고 한다.
SVM은 특성의 스케일에 민감하므로, 반드시 스케일링을 해주어야 한다.
소프트 마진 분류
모든 샘플이 도로 경계 바깥쪽에 있는 상황을 하드 마진 분류(hard margin classification)라고 한다. 이는 두 가지 문제가 있다.
- 데이터가 반드시 선형적으로 구분되어야 한다.
- 이상치에 민감하다.
그림과 같이 이상치가 있는 데이터의 경우, 도로의 폭을 넓게 하는 것과 마진 오류(샘플이 도로 중간에 있거나 반대쪽에 있음) 사이의 균형을 잡아야 한다. 이를 소프트 마진 분류(soft margin classification)라고 한다.
from sklearn.datasets import load_iris
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris = load_iris(as_frame=True)
X = iris.data[['petal length (cm)', 'petal width (cm)']].values
y = (iris.target == 2) # Iris-Virginica
svm_clf = make_pipeline(StandardScaler(), LinearSVC(C=1, random_state=42))
svm_clf.fit(X, y)
LinearSVC(C=1, random_state=42)
에서 C
는 규제 하이퍼파라미터이다. 일반적인 생각과는 반대로, C
가 커지면 규제가 줄어들고, C
가 작아지면 규제가 커진다. C
에 따른 결과의 차이는 다음과 같다.
cf. 로지스틱 회귀과는 다르게,
LinearSVC
에는predict_proba()
메서드가 없다. 사용하고 싶다면LinearSVC
대신 그냥SVC
를 사용하고,probability=True
로 설정한 다음에predict_proba()
를 사용해야 한다.
비선형 SVM 분류
비선형 데이터의 경우, 앞서 다항 회귀에서 살펴본 것처럼 다항 특성을 추가하여 해결할 수 있다.
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 = make_pipeline(
PolynomialFeatures(degree=3),
StandardScaler(),
LinearSVC(C=10, max_iter=10_000, random_state=42)
)
polynomial_svm_clf.fit(X, y)
다항식 커널
물론 다항 특성을 추가하는 것은 모델을 매우 느리게 한다. 커널 트릭(kernel trick)을 사용하면 실제로는 특성을 추가하지 않으면서도 다항 특성을 많이 추가한 것과 같은 효과를 낼 수 있다.
from sklearn.svm import SVC
poly_kernel_svm_clf = make_pipeline(StandardScaler(),
SVC(kernel='poly', degree=3, coef0=1, C=5))
poly_kernel_svm_clf.fit(X, y)
coef0
은 모델이 높은 차수와 낮은 차수에 얼마나 영향을 받을지를 조절한다.
유사도 특성, 가우스 RBF 커널
각 샘플이 특정 랜드마크와 얼마나 닮았는지를 측정하는 유사도 함수로 계산한 특성을 추가할 수 있다. 유사도 함수로는 가우스 방사 기저 함수(RBF)를 많이 사용한다.
- 랜드마크를 정한다.
- 샘플이 랜드마크에서 얼마나 떨어져 있는지를 구하고, 그 값을 유사도 함수에 넣는다.
- 도출된 값을 새로운 특성으로 한다.
예시는 책을 참고하자.
랜드마크를 선택하는 가장 좋은 방법은 dataset 모든 샘플 위치에 랜드마크를 설정하는 것이지만, 이렇게 하면 n개의 특성을 가진 m개의 샘플이 m개의 특성을 가진 m개의 샘플로 변환된다(즉, 동일한 크기의 아주 많은 특성이 만들어진다)는 단점이 있다.
rbf_kernel_svm_clf = make_pipeline(StandardScaler(),
SVC(kernel='rbf', gamma=5, C=0.001))
rbf_kernel_svm_clf.fit(X, y)
gamma
는 그래프의 폭을 결정하는 값이다. 예를 들어, gamma
가 커지면 RBF함수의 폭이 좁아지고, 각 샘플의 영향 범위가 작아진다. 이는 결정 경계가 불규칙해지고 각 샘플을 따라 구불구불하게 된다는 특징이 있다.
gamma
와 C
모두를 적절하게 조절하여 원하는 결정 경계를 만드는 것이 중요하다.
SVC 클래스에서도 선형 커널을 사용할 수 있지만(
SVC(kernel='linear')
),LinearSVC
가 언제나 더 빠르다.
SVM 회귀
분류와는 목표가 조금 달라진다. 제한된 마진 오류(도로 밖의 샘플) 안에서 도로 안에 가능한 많은 샘플이 들어가도록 하는 것이 목표이다.
도로의 폭은 $\epsilon$ 으로 조절한다.
다음 코드는 차례대로 선형 SVM 회귀와 비선형 SVM 회귀이다.
# 선형
import numpy as np
from sklearn.svm import LinearSVR
np.random.seed(42)
X = 2 * np.random.rand(50, 1)
y = 4 + 3 * X[:, 0] + np.random.randn(50)
svm_reg = make_pipeline(StandardScaler(), LinearSVR(epsilon=0.5, random_state=42))
svm_reg.fit(X, y)
# 비선형
from sklearn.svm import SVR
np.random.seed(42)
X = 2 * np.random.rand(50, 1) - 1
y = 0.2 + 0.1 * X[:, 0] + 0.5 * X[:, 0] ** 2 + np.random.randn(50) / 10
svm_poly_reg = make_pipeline(StandardScaler(), SVR(kernel='poly', degree=2, C=0.01, epsilon=0.1))
svm_poly_reg.fit(X, y)
별도의 출처 표시가 있는 이미지를 제외한 모든 이미지는 강의자료에서 발췌하였음을 밝힙니다.
댓글남기기