지원 벡터 기계(SVM)의 직관적 이해와 코드 실습

이전 글에서 로지스틱 회귀를 통한 분류 문제 해결 방법을 설명했으며, 이번에는 더 강력한 분류 모델인 SVM을 탐구합니다. 이 글은 코드 중심의 실습 위주로 구성되어 데이터 처리 기술이 점점 다양해지는 과정을 경험할 수 있습니다.

SVM은 중소 규모의 복잡한 데이터 세트 분류에 특화된 인기 있는 머신러닝 모델입니다.

一、SVM의 기본 개념

SVM은 여러 데이터 포인트 중 최적의 분류 경계를 찾는 알고리즘입니다. 이 경계에 위치한 데이터 포인트를 '지원 벡터'라고 하며, 이들이 분리 초평면을 지지하기 때문에 이름이 붙었습니다.

최적 경계를 어떻게 판단할까요? 위 그림에서 세 개의 검은색 직선이 데이터를 완벽히 분리하는 것을 확인할 수 있습니다. 이 경우 단일 직선으로 무수한 해를 얻을 수 있습니다. 그렇다면 어떤 직선이 최적일까요?

위 그림에서 분류된 데이터 포인트까지의 거리를 계산해 보면, 데이터와의 거리를 최대화하는 직선이 유일한 해가 됩니다. 허용 오차 구간을 최대화하는 것이 목표이며, 이 구간 내에 위치한 데이터 포인트가 지원 벡터입니다.

이러한 원리를 바탕으로 SVM이 작동합니다.

二、코드를 통한 이론 적용

2.1 데이터 로드 및 준비

필요한 라이브러리 불러오기:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

데이터 세트 로드(링크는 중요하지 않음):

data = pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv')
data.head()
Med_1_mL Med_2_mL Virus Present
0 6.50823 8.58253 0
1 4.12612 3.07346 1
2 6.42787 6.36976 0
3 3.67295 4.90522 1
4 1.58032 2.44056 1

이 데이터 세트는 바이러스 감염 실험 결과를 시뮬레이션합니다. 두 가지 약물의 용량을 변화시켜 감염 여부를 관찰한 연구입니다.

  • 특성: 약물 1의 용량(Med_1_mL), 약물 2의 용량(Med_2_mL)
  • 레이블: 바이러스 감염 여부(1: 감염, 0: 비감염)

2.2 데이터 탐색

sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus Present',data=data)

Seaborn을 사용해 약물 용량과 감염 결과의 산포도를 시각화합니다.

sns.pairplot(data,hue='Virus Present')

특성 간 상관관계를 파악하기 위해 쌍별 그래프를 작성합니다.

약물 용량 증가가 감염 예방에 긍정적인 영향을 미친다는 결론을 도출할 수 있습니다.

2.3 SVM 모델 훈련

# SVC: Support Vector Classifier
from sklearn.svm import SVC

# 데이터 준비
labels = data['Virus Present']
features = data.drop('Virus Present',axis=1) 

# 모델 정의
classifier = SVC(kernel='linear', C=1000)

# 모델 훈련
classifier.fit(features, labels)

# 경계선 시각화 함수 정의
def visualize_svm_model(model,features,labels):
    
    features = features.values
    labels = labels.values
    
    # 산포도 출력
    plt.scatter(features[:, 0], features[:, 1], c=labels, s=30,cmap='coolwarm')

    
    # 결정 함수 시각화
    ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    # 격자 생성
    xx = np.linspace(xlim[0], xlim[1], 30)
    yy = np.linspace(ylim[0], ylim[1], 30)
    YY, XX = np.meshgrid(yy, xx)
    xy = np.vstack([XX.ravel(), YY.ravel()]).T
    Z = model.decision_function(xy).reshape(XX.shape)

    # 경계선 및 마진 시각화
    ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    # 지원 벡터 표시
    ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100,
               linewidth=1, facecolors='none', edgecolors='k')
    plt.show()
visualize_svm_model(classifier,features,labels)

sklearnSVC 분류기를 사용해 모델을 구현합니다.

2.4 C 매개변수 조정

C 매개변수는 L2 정규화 강도를 제어합니다. C 값이 클수록 정규화가 약해집니다.

classifier = SVC(kernel='linear', C=0.05)
classifier.fit(features, labels)
visualize_svm_model(classifier,features,labels)

C 값을 감소시키면 모델이 데이터에 적응하는 정도가 줄어듭니다.

2.5 커널 함수 선택

kernel 매개변수는 {'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'} 중 선택 가능합니다. 선형 분류에 사용된 linear를 기준으로 비선형 분류 방법을 탐구합니다.

2.5.1 다항식 커널

다항식 커널(kernel='poly')은 단일 특성을 다중 특성으로 확장해 곡선을 근사합니다. 예를 들어, 특성 확장을 다음과 같이 수행할 수 있습니다:

X X^2 X^3 y
0 6.50823 6.50823² 6.50823³ 0
1 4.12612 4.12612² 4.12612³ 1
2 6.42787 6.42787² 6.42787³ 0
3 3.67295 3.67295² 3.67295³ 1
4 1.58032 1.58032² 1.58032³ 1
classifier = SVC(kernel='poly', C=0.05,degree=5)
classifier.fit(features, labels)
visualize_svm_model(classifier,features,labels)

다항식 커널을 사용하고 degree=5로 최고 차수를 설정합니다. 분류 경계가 곡선 형태로 나타납니다.

2.5.2 가우시안 RBF 커널

기본 커널은 가우시안 RBF입니다. gamma 매개변수는 커널의 모양을 조절합니다. gamma 값을 증가시키면 커널이 좁아져 각 데이터 포인트의 영향 범위가 줄어듭니다. 반대로 gamma 값을 감소시키면 커널이 넓어져 영향 범위가 확대됩니다.

classifier = SVC(kernel='rbf', C=1,gamma=0.01)
classifier.fit(features, labels)
visualize_svm_model(classifier,features,labels)

2.6 하이퍼파라미터 튜닝: 격자 탐색

from sklearn.model_selection import GridSearchCV
model = SVC()
param_grid = {'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]}
grid = GridSearchCV(model,param_grid)
grid.fit(features,labels)
print("최적 파라미터 =",grid.best_params_,"최고 점수 =",grid.best_score_)

GridSearchCV를 사용해 하이퍼파라미터 조합을 탐색해 최적 값을 찾습니다. 이 방법은 계산 자원을 활용한 강력한 튜닝 기법입니다. 그러나 파라미터 범위를 사전에 정의해야 합니다.

데이터 세트가 간단한 경우, 첫 번째 조합에서 100% 정확도를 달성할 수 있습니다. 출력 결과는 다음과 같습니다:

최적 파라미터 = {'C': 0.01, 'gamma': 0.01, 'kernel': 'rbf'}, 최고 점수 = 1.0

요약

선형 분리 가능한 데이터 세트에는 SVC(kernel='linear')를 사용할 수 있으며, 데이터량이 많거나 특성 수가 많은 경우 LinearSVC를 대체로 활용할 수 있습니다. 비선형 분류에는 가우시안 RBF, 다항식, 시그모이드 커널을 사용해 모델을 구축할 수 있습니다. GridSearchCV를 활용해 최적 파라미터를 탐색할 수 있습니다.

관련 글:

  • 머신러닝(3): 로지스틱 회귀 이해 및 이진/다중 분류 코드 실습
  • 머신러닝(2): 선형 회귀와 경사 하강법 이해 및 간단한 예측
  • 머신러닝(1): 5분 안에 머신러닝 이해 및 실습 시작
  • 사전 머신러닝(5): Matplotlib 기본 사용법 30분 정리
  • 사전 머신러닝(4): Pandas 사용법 총체적 정리
  • 사전 머신러닝(3): NumPy 기본 사용법 30분 정리
  • 사전 머신러닝(2): Jupyter Notebook 기본 사용법 30분 정리
  • 사전 머신러닝(1): 수학 기호 및 그리스 문자

태그: SVM 선형 커널 다항식 커널 RBF 커널 그리드 서치

7월 18일 21:41에 게시됨