본문으로 건너뛰기

033 SVM 분류 상세

키워드: SVM, svc

개요

SVM(Support Vector Machine)은 결정 경계와 가장 가까운 데이터 포인트(서포트 벡터)를 기반으로 분류하는 알고리즘입니다. 커널 트릭을 통해 비선형 분류도 가능합니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: pycaret[full]>=3.0

SVM 원리

  1. 마진 최대화: 클래스 간 거리(마진)를 최대화하는 초평면 찾기
  2. 서포트 벡터: 결정 경계에 가장 가까운 데이터 포인트
  3. 커널 트릭: 고차원 공간으로 매핑하여 비선형 분류

PyCaret에서 SVM

from pycaret.classification import *
from pycaret.datasets import get_data

# 033 데이터 로드
data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 033 Linear SVM
svm_linear = create_model('svm')

# 033 RBF SVM
svm_rbf = create_model('rbfsvm')

주요 하이퍼파라미터

C (정규화)

# 033 C: 오분류 허용 정도 (작을수록 마진 넓음, 오분류 허용)
svm_c1 = create_model('svm', C=1.0) # 기본값
svm_c01 = create_model('svm', C=0.1) # 소프트 마진
svm_c10 = create_model('svm', C=10.0) # 하드 마진

커널

# 033 kernel: 커널 함수 종류
svm_linear = create_model('rbfsvm', kernel='linear')
svm_rbf = create_model('rbfsvm', kernel='rbf') # 기본값
svm_poly = create_model('rbfsvm', kernel='poly')
svm_sigmoid = create_model('rbfsvm', kernel='sigmoid')

gamma (RBF, Poly, Sigmoid)

# 033 gamma: 커널 계수 (높을수록 복잡한 결정 경계)
svm_gamma_auto = create_model('rbfsvm', gamma='auto')
svm_gamma_scale = create_model('rbfsvm', gamma='scale') # 기본값
svm_gamma_01 = create_model('rbfsvm', gamma=0.1)

Polynomial 커널 파라미터

# 033 degree: 다항식 차수
svm_poly = create_model('rbfsvm', kernel='poly', degree=3)

# 033 coef0: 독립항
svm_poly = create_model('rbfsvm', kernel='poly', coef0=0.0)

커널 비교

from pycaret.classification import *
from pycaret.datasets import get_data
import pandas as pd

data = get_data('iris')
clf = setup(data, target='species', session_id=42, verbose=False)

kernels = ['linear', 'rbf', 'poly', 'sigmoid']
results = []

for kernel in kernels:
svm = create_model('rbfsvm', kernel=kernel, verbose=False)
metrics = pull()

results.append({
'kernel': kernel,
'accuracy': metrics['Accuracy'].mean(),
'auc': metrics['AUC'].mean()
})

df = pd.DataFrame(results)
print(df)

스케일링의 중요성

SVM은 거리 기반이므로 스케일링 필수:

from pycaret.classification import *
from pycaret.datasets import get_data

data = get_data('diabetes')

# 033 스케일링 없이
clf1 = setup(data, target='Class variable', normalize=False, session_id=42, verbose=False)
svm1 = create_model('rbfsvm', verbose=False)
results1 = pull()

# 033 스케일링 적용
clf2 = setup(data, target='Class variable', normalize=True, normalize_method='zscore', session_id=42, verbose=False)
svm2 = create_model('rbfsvm', verbose=False)
results2 = pull()

print(f"스케일링 없이: {results1['Accuracy'].mean():.4f}")
print(f"스케일링 적용: {results2['Accuracy'].mean():.4f}")

확률 예측

from pycaret.classification import *
from pycaret.datasets import get_data

data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 033 probability=True로 확률 예측 활성화
svm = create_model('rbfsvm', probability=True, verbose=False)

# 033 예측
predictions = predict_model(svm)
print(predictions[['Class variable', 'prediction_label', 'prediction_score']].head())

튜닝

from pycaret.classification import *
from pycaret.datasets import get_data

data = get_data('diabetes')
clf = setup(data, target='Class variable', normalize=True, session_id=42, verbose=False)

# 033 기본 모델
svm = create_model('rbfsvm', verbose=False)

# 033 자동 튜닝
tuned_svm = tune_model(svm, optimize='AUC')

# 033 커스텀 그리드
custom_grid = {
'C': [0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.01, 0.1, 1],
'kernel': ['rbf', 'poly']
}

tuned_svm = tune_model(svm, custom_grid=custom_grid, optimize='AUC')

결정 경계 시각화

from pycaret.classification import *
from pycaret.datasets import get_data

data = get_data('iris')
clf = setup(
data,
target='species',
session_id=42,
verbose=False
)

svm = create_model('rbfsvm', verbose=False)

# 033 결정 경계 시각화 (2차원)
plot_model(svm, plot='boundary')

서포트 벡터 확인

from pycaret.classification import *
from pycaret.datasets import get_data

data = get_data('iris')
clf = setup(data, target='species', session_id=42, verbose=False)

svm = create_model('rbfsvm', verbose=False)

# 033 서포트 벡터 개수
print(f"서포트 벡터 개수: {svm.n_support_}")
print(f"클래스별 서포트 벡터: {list(svm.n_support_)}")

# 033 서포트 벡터 인덱스
print(f"총 서포트 벡터: {len(svm.support_)}")

장단점

장점:

  • 고차원 데이터에서 효과적
  • 결정 경계가 명확
  • 커널 트릭으로 비선형 분류 가능
  • 과적합에 강건 (마진 최대화)

단점:

  • 대용량 데이터에서 느림 (O(n²) ~ O(n³))
  • 스케일링 필수
  • 확률 출력이 느림
  • 하이퍼파라미터 튜닝 필요
  • 해석이 어려움

언제 사용하나?

# 1. 고차원, 소규모 데이터
# 033 특성 수 >> 샘플 수 (텍스트, 유전자 데이터)

# 2. 명확한 마진이 필요할 때
# 033 클래스가 잘 분리되는 경우

# 3. 비선형 관계가 있을 때
# 033 RBF 커널로 복잡한 결정 경계

# 033 주의: 대용량 데이터에서는 다른 알고리즘 권장

SVM vs 다른 알고리즘

상황SVM대안
대용량느림XGBoost, LightGBM
고차원적합SVM
해석 필요어려움로지스틱, 결정 트리
비선형RBF랜덤 포레스트
빠른 프로토타이핑느림랜덤 포레스트

정리

  • SVM은 마진 최대화 기반 분류기
  • C로 소프트/하드 마진 조절
  • RBF 커널이 가장 범용적
  • 스케일링 필수
  • 소규모 고차원 데이터에 적합
  • 대용량 데이터에서는 비효율적

다음 글 예고

다음 글에서는 KNN 분류 상세를 다룹니다.


PyCaret 머신러닝 마스터 시리즈 #033