Developer's Development
3.2.10 [머신러닝] 서포트 벡터 머신 본문
SVM 이론
SVM은 데이터를 분리하는 최적의 초평면(Hyperplane)을 찾는 분류 알고리즘이다. 초평면은 데이터 공간에서 두 클래스를 나누는 경계(Margin)를 의미한다. 이 때, SVM은 마진(Margin)을 최대화하도록 학습한다.
SVM은 결정 경계(Decision Boundary)를 정의하며, 클래스 간 거리가 가장 먼 경계를 찾는다.
이를 통해 최적의 분리를 달성할 수 있다.
- 초평면(Hyperplane) : 데이터를 나누는 기준 선(또는 면)으로, n차원 공간에서의 결정 경계를 의미한다.
- 마진(Margin) : 초평면과 데이터 포인트(서포트 벡터) 간의 거리로, SVM은 마진을 최대화하는 초평면을 선택한다.
- 서포트 벡터(Support Vector) : 결정 경계에 가장 가까운 데이터 포인트로, 마진을 결정하는 데 직접적으로 영향을 미친다.
- 커널 함수(Kernel Function) : 선형 분리가 불가능한 경우 데이터를 고차원으로 변환하여 선형 분리를 가능하게 하는 함수이다.
- 최적의 초평면
SVM은 다음 최적화 문제를 푼다.

선형 SVM 분류
선형 SVM은 데이터를 직선(또는 초평면)으로 나눌 수 있는 경우에 적용된다.
즉, 데이터가 선형적으로 구분 가능한 경우에 적합하다.
- 장점 : 간단하고 효율적이며, 고차원 데이터에서도 효과적이다.
- 단점 : 데이터가 선형적으로 분리되지 않는 경우 성능이 저하된다.
[참고] Kernel
커널(Kernel)은 SVM에서 비선형 데이터를 고차원 공간으로 변환하여 선형적으로 분리 가능하게 만드는 방법이다. 커널 함수는 입력 데이터를 더 높은 차원의 특징 공간으로 매핑하여, SVM이 복잡한 데이터의 패턴을 학습할 수 있게 해준다.
→ SVM의 핵심은 두 클래스를 최대한 잘 구분할 수 있는 초평면을 찾는 것이며, 커널 함수를 통해 이 작업을 고차원에서도 수행할 수 있게 된다.
- 커널이 필요한 이유
많은 경우 데이터는 선형적으로 분리할 수 없는 형태로 분포되어 있다. 즉, 2차원 공간에서 직선을 이용해 구분할 수 없는 경우가 많다.
커널 함수를 사용하면, 고차원으로 데이터를 변환하여 선형적으로 분리 가능하게 만든다. 이를 통해 더 복잡한 데이터 구조를 효과적으로 처리할 수 있다.
이 변환을 직접 계산하지 않고, 커널 트릭을 사용해 효율적으로 계산할 수 있다.
- 하이퍼 파라미터
👉🏻 C : 학습 데이터의 오류 허용도를 결정
- C 값이 크면 오류를 최소화하고, 결정 경계가 데이터에 더 민감해짐
(마진을 최대화하는 대신 오류를 허용하지 않으므로 과대적합 가능성)
- C 값이 작으면 오류를 허용하면서, 일반화에 더 집중
(마진을 최대화하려고 노력하면서 오류를 어느 정도 허용하나, 과소적합 가능성)
👉🏻 Kernel : 비선형 데이터의 변환을 위한 커널 함수 설정
- linear : 선형 커널 (데이터가 선형적으로 분리 가능한 경우)
- poly : 다항식 커널 (비선형 관계, 차수 degree로 지정)
- rbf : RBF(Radial Basis Function) 커널, 가우시안 커널로 비선형 데이터 처리
- sigmoid : 시그모이드 커널
- SVC (SupportVectorClassifier) 실습
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.inspection import DecisionBoundaryDisplay
iris_data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, random_state=42)
model = SVC(kernel="linear")
model.fit(X_train, y_train)
model.score(X_test, y_test)
df = pd.DataFrame(iris_data.data[:, :2], columns=iris_data.feature_names[:2])
df['target'] = iris_data.target
X = iris_data.data[:, :2]
y = iris_data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
svm_clf = SVC(kernel='linear', C=1.0)
svm_clf.fit(X_train, y_train)
svm_clf.score(X_train, y_train), svm_clf.score(X_test, y_test
dbd = DecisionBoundaryDisplay.from_estimator(svm_clf, X_train, alpha=0.7)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, edgecolors='k', label="Training Data")
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()

svm_clf = SVC(kernel="rbf", C=1.0, gamma=0.5)
svm_clf.fit(X_train, y_train)
dbd = DecisionBoundaryDisplay.from_estimator(svm_clf, X_train, alpha=0.7)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, edgecolors='k', label="Training Data")
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()

SVM 회귀 (Support Vector Regression, SVR)
SVM은 분류 문제뿐 아니라 회귀 문제에도 적용할 수 있다. SVM 회귀는 마진 내 오차를 허용하면서 결정 경계를 통해 데이터를 예측한다. 두 개의 경계를 설정하고, 경계 내의 오차는 무시하며 경계 바깥에 있는 오차에만 패널티를 부여하는 방법이다. 이는 SVR의 손실 함수에서 볼 수 있으며, 최적화 목표는 마진 내에 최대한 많은 데이터 포인트를 포함하는 것이다.
SVR은 회귀 문제를 해결하면서 입력 데이터의 마진 내에서 목표 변수와의 거리를 최소화하는 특징을 갖는다. 이를 통해 모델은 노이즈의 영향을 줄이고, 일반화 성능을 높일 수 있다.
| 특징 | SVC | SVR |
| 목적 | 이진 분류 문제 해결 | 연속적인 값 예측 |
| 결정 경계 | 서포트 벡터와의 거리를 최대화하여 생성 | 데이터 포인트와의 오차를 최소화하여 생성 |
| 마진/허용 오차 | 마진을 최대화하여 일반화 성능 향상 | ε 매개변수로 허용 오차 범위 설정 |
| 결과 | 클래스 예측 (이진 분류) | 연속적인 값 예측 |
👉🏻 ϵ-튜브(앱실론 튜브) : 값을 기준으로 오차가 범위 내에 있으면 무시, 범위를 벗어나면 벌칙(Penalty)을 부여한다.
👉🏻 커널 트릭 : SVR은 선형 관계 뿐만 아니라, 비선형 관계도 커널 함수를 사용하여 표현할 수 있다.
👉🏻 일반화 성능 : SVR은 노이즈에 강하며, 과적합을 방지하는 데 효과적이다.
from sklearn.svm import SVR
np.random.seed(0)
X = np.sort(np.random.rand(40, 1) * 5, axis=0)
y = np.sin(X).ravel() + np.random.randn(40) * 0.1 # 노이즈를 살짝 걸어줌
svr_rbf = SVR(kernel='rbf')
svr_lin = SVR(kernel='linear')
svr_poly = SVR(kernel='poly')
# 학습
svr_rbf.fit(X, y)
svr_lin.fit(X, y)
svr_poly.fit(X, y)
# 예측
pred_rbf = svr_rbf.predict(X_test)
pred_lin = svr_lin.predict(X_test)
pred_poly = svr_poly.predict(X_test)
# 시각화
plt.scatter(X, y, color='darkorange', label='data')
plt.plot(X_test, pred_rbf, color='navy', label='rbf_pred')
plt.plot(X_test, pred_lin, color='c', label="lin_pred")
plt.plot(X_test, pred_poly, color='cornflowerblue', label='poly_pred')
svr_rbf_epsilon = svr_rbf.epsilon
print(svr_rbf_epsilon) # 0.1
epsilon_upper = pred_rbf + svr_rbf_epsilon
epsilon_lower = pred_rbf - svr_rbf_epsilon
plt.fill_between(X_test.ravel(), epsilon_lower, epsilon_upper, color="skyblue", alpha=0.3)
plt.xlabel('Data')
plt.ylabel('Target')
plt.legend()
plt.show()

- 캘리포니아 주택 가격 예측
# 데이터 로드
from sklearn.datasets import fetch_california_housing
housing_data = fetch_california_housing()
# 데이터 분리 및 스케일링
from sklearn.preprocessing import StandardScaler
X_train, X_test, y_train, y_test = train_test_split(housing_data.data, housing_data.target, random_state=0)
scaler_x = StandardScaler()
X_train_scaled = scaler_x.fit_transform(X_train)
X_test_scaled = scaler_x.transform(X_test)
# SVR은 y 값도 스케일링을 해줘야 안정적
scaler_y = StandardScaler()
y_train_scaled = scaler_y.fit_transform(y_train.reshape(-1, 1))
y_test_scaled = scaler_y.transform(y_test.reshape(-1, 1))
# SVR 모델 훈련 및 평가 (스케일링된 X 데이터와 y 데이터)
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error
svr = SVR(kernel='rbf', C=1.0, epsilon=0.1)
svr.fit(X_train_scaled, y_train_scaled)
y_pred_scaled = svr.predict(X_test_scaled)
y_pred = scaler_y.inverse_transform(y_pred_scaled.reshape(-1, 1))
mean_squared_error(y_test, y_pred)'데이터 분석과 머신러닝, 딥러닝 > 머신러닝' 카테고리의 다른 글
| 3.2.12 [머신러닝] 차원 축소 (3) | 2025.08.03 |
|---|---|
| 3.2.11 [머신러닝] 앙상블 (2) | 2025.08.03 |
| 3.2.9 [머신러닝] 결정 트리 (6) | 2025.07.24 |
| 3.2.8 [머신러닝] 분류 (1) | 2025.07.24 |
| 3.2.7 [머신러닝] 회귀 (5) | 2025.07.21 |