딥러닝 파이토치 강좌, 서포트 벡터 머신

이번 글에서는 머신러닝의 중요한 기법인 서포트 벡터 머신(Support Vector Machine, SVM)에 대해 자세히 알아보고, 이를 파이토치를 이용해서 구현해보도록 하겠습니다. 서포트 벡터 머신은 특히 분류 문제에서 뛰어난 성능을 발휘합니다. SVM은 최대 마진 원칙(maximum margin principle)을 기반으로 하는 분류 알고리즘으로, 주로 선형 분류기(linear classifier)로 사용되지만, 커널 기법(kernel trick)을 통해 비선형 데이터에 대해서도 효과적으로 적용할 수 있습니다.

1. 서포트 벡터 머신(SVM)이란?

서포트 벡터 머신은 두 개의 클래스 사이를 분리하는 최적의 초평면(hyperplane)을 찾는 알고리즘입니다. 여기서 ‘최적’이라는 것은 마진(margin)을 최대화하는 것을 의미하는데, 마진은 초평면에서 가장 가까운 데이터 포인트(서포트 벡터)까지의 거리를 말합니다. SVM은 이러한 마진을 최대화하여, 주어진 데이터에 대해 일반화 능력을 높이도록 설계되었습니다.

1.1. SVM의 기본 원리

SVM의 기본 동작 원리는 다음과 같습니다:

  1. 서포트 벡터: 데이터 포인트 중에서 초평면에 가장 가까운 데이터 포인트를 서포트 벡터라고 합니다.
  2. 초평면: 주어진 두 클래스 데이터를 분리하는 선형 결정 경계를 생성합니다.
  3. 마진: 초평면과 서포트 벡터 간의 최대 거리를 최적화하여 분류 능력을 향상시킵니다.
  4. 커널 트릭: SVM에서 비선형 분리 문제를 해결하기 위해 고안된 기법입니다. 이를 통해 고차원 데이터로 매핑하여 선형 분리를 가능하게 합니다.

2. SVM의 수학적 배경

SVM의 기본 목표는 다음과 같은 최적화 문제를 해결하는 것입니다:

2.1. 최적화 문제 설정

주어진 데이터가 (x_i, y_i) 형태로 있을 때, 여기서 x_i는 입력 데이터이고 y_i는 클래스 레이블(1 또는 -1)입니다. SVM은 다음과 같은 최적화 문제를 설정합니다:

minimize (1/2) ||w||^2
subject to y_i (w * x_i + b) >= 1

여기서 w는 초평면의 기울기 벡터, b는 절편(bias)을 의미합니다. 위의 식은 최적의 경계를 정의하고 마진을 최대화하는 것입니다.

2.2. 커널 기법

비선형 데이터를 다루기 위해 SVM은 커널 함수를 사용합니다. 커널 함수는 데이터를 고차원 공간으로 매핑하여 서로 분리 가능한 형태로 변환하는 함수입니다. 자주 사용되는 커널 함수는 다음과 같습니다:

  • 선형 커널: K(x, x') = x * x'
  • 다항식 커널: K(x, x') = (alpha * (x * x') + c)^d
  • 가우시안 RBF 커널: K(x, x') = exp(-gamma * ||x - x'||^2)

3. PyTorch로 SVM 구현하기

이제 PyTorch를 사용하여 SVM을 구현해보겠습니다. PyTorch는 딥러닝 프레임워크이지만, 수치 계산이 가능하기 때문에 SVM과 같은 알고리즘도 쉽게 구현할 수 있습니다. 다음 단계로 진행하겠습니다:

3.1. 패키지 설치 및 데이터 준비

먼저 필요한 패키지를 설치하고, 사용할 데이터를 생성합니다.

import torch
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split

# 데이터 생성
X, y = make_moons(n_samples=100, noise=0.1, random_state=42)
y = np.where(y == 0, -1, 1)  # 레이블을 -1과 1로 변환

# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 데이터 텐서 변환
X_train_tensor = torch.FloatTensor(X_train)
y_train_tensor = torch.FloatTensor(y_train)
X_test_tensor = torch.FloatTensor(X_test)
y_test_tensor = torch.FloatTensor(y_test)

3.2. SVM 모델 구축

이제 SVM 모델을 구축하겠습니다. 모델은 입력 데이터와 레이블을 이용하여 가중치 w와 절편 b를 학습합니다.

class SVM(torch.nn.Module):
    def __init__(self):
        super(SVM, self).__init__()
        self.w = torch.nn.Parameter(torch.randn(2, requires_grad=True))
        self.b = torch.nn.Parameter(torch.randn(1, requires_grad=True))
    
    def forward(self, x):
        return torch.matmul(x, self.w) + self.b
    
    def hinge_loss(self, y, output):
        return torch.mean(torch.clamp(1 - y * output, min=0))

3.3. 트레이닝 및 테스트

모델을 학습하기 전에 옵티마이저와 학습률을 설정합니다.

# 하이퍼파라미터 설정
learning_rate = 0.01
num_epochs = 1000

model = SVM()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

# 학습 과정
for epoch in range(num_epochs):
    optimizer.zero_grad()
    
    # 모델 예측
    output = model(X_train_tensor)
    
    # 손실 계산 (Hinge Loss)
    loss = model.hinge_loss(y_train_tensor, output)
    
    # 역전파
    loss.backward()
    optimizer.step()

    if (epoch+1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

3.4. 결과 시각화

모델 학습이 완료되면, 결정 경계를 시각화하여 모델의 성능을 평가할 수 있습니다.

# 결정 경계 시각화
def plot_decision_boundary(model, X, y):
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np.linspace(y_min, y_max, 100))
    grid = torch.FloatTensor(np.c_[xx.ravel(), yy.ravel()])
    
    with torch.no_grad():
        model.eval()
        Z = model(grid)
        Z = Z.view(xx.shape)
        plt.contourf(xx, yy, Z.data.numpy(), levels=50, alpha=0.5)
    
    plt.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k')
    plt.title("SVM Decision Boundary")
    plt.xlabel("Feature 1")
    plt.ylabel("Feature 2")
    plt.show()

plot_decision_boundary(model, X, y)

4. SVM의 장단점

SVM은 놀라운 성능을 발휘하지만, 모든 알고리즘과 마찬가지로 장단점이 존재합니다.

4.1. 장점

  • 고차원 데이터에 대해 효과적입니다.
  • 마진 최적화로 인해 일반화 성능이 우수합니다.
  • 비선형 분류를 위한 다양한 커널 방법이 존재합니다.

4.2. 단점

  • 큰 데이터셋에 대해서는 학습 시간이 길어질 수 있습니다.
  • C와 γ를 잘 조절해야 성능이 좋아집니다.
  • 메모리 및 계산 복잡도가 높아질 수 있습니다.

5. 결론

서포트 벡터 머신은 강력한 성능을 가진 분류 알고리즘으로, 특히 회귀가 아닌 분류 문제에서 매우 유용하게 사용될 수 있습니다. PyTorch를 활용하여 SVM을 구현해보며, 기계 학습의 기초적인 개념을 다시 한번 되새기는 기회가 되었기를 바랍니다. 더 나아가 SVM을 활용한 실전 프로젝트나 연구로 나아갈 수 있는 발판이 되었으면 좋겠습니다.

6. References

  • Vapnik, V. (1998). Statistical Learning Theory. John Wiley & Sons.
  • Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer.
  • Russell, S. & Norvig, P. (2010). Artificial Intelligence: A Modern Approach. Prentice Hall.