250x250
Link
나의 GitHub Contribution 그래프
Loading data ...
Notice
Recent Posts
Recent Comments
관리 메뉴

Data Science LAB

[Python] 서포트벡터머신(SVM) 본문

adp 실기/알고리즘 이론

[Python] 서포트벡터머신(SVM)

ㅅ ㅜ ㅔ ㅇ 2022. 8. 16. 17:09
728x90

SVM

서포트 벡터 머신은 새로운 데이터가 입력되었을 때 기존 데이터를 활용하여 분류, 회귀, 이상치 탐색에 사용 가능한 다목적 머신러닝 모델이다. 복잡한 분류 문제에 특히 유용하며 작거나 중간 크기의 데이터에 사용하기 적합하다. SVM은 최대 마진 분류기라고 불리는 단순한 분류기를 일반화한 것이며, 이러한 최대 마진 분류기의 단점을 극복하고 확장성을 넓힌 것이 서포트 벡터 분류기(SVC)이다. 또한 SVC를 더 확장하고 비선형 클래스 경계를 수용하기 위해 SVM이 고안되었다. 

 

장점

  • 분류와 예측에 모두 사용 가능하다.
  • 신경망 기법에 비해 과적합 정도가 낮다.
  • 예측의 정확도가 높다.
  • 저차원과 고차원의 데이터에 모두 잘 작동한다.
 
 
단점
  • 전처리와 파라미터에 따라 정확도가 달라진다.
  • 예측이 어떻게 이루어지는지에 대한 이해와 모델의 해석이 어렵다.
  • 대용량 데이터에 대한 모형 구축 시 속도가 느리며 메모리 할당량이 크다.
  • 모든 데이터가 초평면에 의해 두 영역으로 분류되지는 못하기 때문에, 최대 마진 분류기는 모든 데이터에 적용하기 어렵고, 과적합과 이상치에 민감하다.

 

- 초평면 : p차원 공간에서 차원이 (p-1)인 아핀 부분공간으로 각 그룹을 분리하는 분류자
- 서포트 벡터 : 각 그룹에 속한 데이터 중 초평면에 가장 가까운 최전방 데이터들
- 마진 : 관측치에서 초평면까지 가장 짧은 거리
 

 

-> SVM은 데이터들 간의 벡터 거리를 측정하였을 때 그 거리가 최대가 되는 분류자를 찾아나간다. 

- SVM은 특성의 스케일링에 민감하기 때문에 scaler를 활용할 경우 결정경계가 훨씬 좋아진다. 

모든 데이터가 경계선의 바깥에 올바르게 분류되어 있는 경우를 하드 마진 분류라고 한다. 하드 마진 분류에서는 두 가지 문제점이 존재한다.
 1. 데이터가 선형적으로 구분될 수 있어야 함
 2. 이상치에 민감함

이러한 문제를 피하려면 클래스 간의 결정선을 넓게 유지하는 것과 마진 오류(샘플이 결정선 중간이나 반대에 있는 경우) 사이에 적절한 균형을 잡아야 하는데 이를 소프트 마진 분류라고 한다.

SVM 모델은 C 파라미터를 사용해 이 균형을 조절한다. C값을 줄이면 결정선의 폭이 넓어지지만 마진 높 커진다.
C = 0 이면 마진을 위반할 여유가 없고, C > 0 이면 C 이하의 관측치들이 반대쪽에 존재하는 것을 허용한다.

모든 데이터가 선형으로 나뉠수는 없기 때문에, 클래스의 경계가 비선형인 상황에서는 SVC의 개념을 확장하고 커널을 활용해 두 관측치의 유사성을 수량화한다. 비선형 데이터를 다루는 방법은 다항 특성과 같은 특성을 추가하는 것이다.

다항식 특성을 추가하는 것은 간단하고 대부분 머신러닝 알고리즘에서 잘 작동하지만 낮은 차수는 복잡한 데이터를 잘 표현하지 못하고 높은 차수의 데이터는 과적합이나 속도를 느리게 만든다.

이때 SVM은 커널 트릭을 사용하여 실제로 특성을 추가하지는 않지만 특성을 추가한 것 같은 결과를 얻을 수 있다. 

비선형 특성을 다루는 또 다른 기법은 각 샘플이 특정 랜드마크와 얼마나 닮았는지 측정하는 유사도 함수로 계산한 특성을 추가하는 것이다.

다항 특성 방식과 마찬가지로 커널 트릭을 사용하여 유사도 특성을 추가할 수 있다. 

(대체적으로 LinearSVC가 SVC(kernel = 'linear') 보다 훨씬 빠르다. 훈련 데이터가 아주 크거나 특성 수가 많을 떄 그렇고, 훈련 데이터가 너무 크지 않다면 가우시안 RBF 커널을 시도하는 것도 좋다.)

SVM 알고리즘은 회귀분석에도 사용할 수 있는데, 일정한 마진 오류 안에 도로 안에 가능한 많은 샘플이 들어가도록 학습한다. 이때, 마진 오류는 도로 밖의 샘플을 의미한다. 

- SVR은 SVC의 회귀버전이고, linearSVR은 LinearSVC의 회귀버전이다.
- LinearSVR은 수행 시간이 훈련 시간에 비해 선형적으로 늘어나지만 SVR은 훈련 데이터가 커지면 훨씬 느려진다.

 

 

파라미터

 

C 정규화 파라미터로 정규화 강도는 C에 반비례하며 반드시 양수
kernel 'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'
degree 커널 함수가 'poly' 일 때 다항 함수의 차수
gamma 커널 함수가 'rbf', 'poly', 'sigmoid' 일 때 커널의 계수
coef() 커널 함수가 'poly', 'sigmoid' 일 때 독립항 지정
tol 중지 기준
class_weight 각 클래스에서 매개변수 C에 대해 가중치 부여
verbose 자세한 정보 수준
max_iter 최대 실행 반복 횟수
decision_function_shape  'ovo', 'ovr'

 

 

1. 분류(SVC)

data1 = pd.DataFrame(load_breast_cancer().data, columns=load_breast_cancer().feature_names)
data1['target'] = load_breast_cancer().target
data1.head()

 

X1 = data1.iloc[:,:-1]
y1 = np.array(data1.target)

# 스케일링
scaler = StandardScaler()
X1_scaled = scaler.fit_transform(X1)


#train/test split
X1_train, X1_test, y1_train, y1_test = train_test_split(X1_scaled, y1, test_size=0.2, random_state=42)

lsvc = LinearSVC(random_state=42)
lsvc.fit(X1_train, y1_train)
pred = lsvc.predict(X1_test)

acc = accuracy_score(y1_test, pred)
acc # 0.956140350877193

 

## 변수 중요도 (coef_)

f_imp = pd.DataFrame({'feature' : X1.columns.tolist(), 'importance' : lsvc.coef_.tolist()[0]})

plt.figure(figsize=(10,6))
sns.barplot(y = f_imp.feature, x = f_imp.importance, edgecolor=(0,0,0))
plt.show()

svc = SVC(random_state=42, kernel='poly')
svc.fit(X1_train, y1_train)

pred = svc.predict(X1_test)
accuracy_score(y1_test, pred) #0.868421052631579

 

 

 

2. 회귀(SVR)

from random import seed
import numpy as np

#샘플데이터 생성
X = np.sort(5*np.random.rand(40,1), axis=0)
y = np.sin(X).ravel()

# 타깃 데이터에 노이즈 추가
y[::5] += 3*(0.5 -np.random.rand(8))
print(y[:10])

from sklearn.svm import SVR

svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)
svr_lin = SVR(kernel='linear', C=100, gamma='auto')
svr_poly = SVR(kernel='poly', C=100, gamma='auto', degree=3, epsilon=0.1, coef0=1)

svr_rbf.fit(X,y)
svr_lin.fit(X,y)
svr_poly.fit(X,y)

rbf_pred = svr_rbf.predict(X)
lin_pred = svr_lin.predict(X)
poly_pred = svr_poly.predict(X)

from sklearn.metrics import mean_squared_error, mean_absolute_error
import pandas as pd

preds = [rbf_pred, lin_pred, poly_pred]
kernel = ['Random_Forest','Linear','Polynomial']
evls = ['mse','rmse','mae']

results = pd.DataFrame(index=kernel, columns=evls)

for pred, nm in zip(preds, kernel):
    mse = mean_squared_error(y,pred)
    mae = mean_absolute_error(y, pred)
    rmse = np.sqrt(mse)
    
    results.loc[nm]['mse'] = round(mse,2)
    results.loc[nm]['rmse'] = round(rmse, 2)
    results.loc[nm]['mae'] = round(mae, 2)
    
results

lw = 2

svrs = [svr_rbf, svr_lin, svr_poly]
kernel_label = ['RBF', 'Linear','Polynomial']
model_color = ['m','c','g']

fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15,10), sharey=True)
for ix, svr in enumerate(svrs):
    axes[ix].plot(X,
                  svr.fit(X,y).predict(X),
                  color=model_color[ix],
                  lw=lw,
                  label='{} model'.format(kernel_label[ix]))
    
    axes[ix].scatter(X[svr.support_],
                     y[svr.support_],
                     facecolor='none',
                     edgecolor=model_color[ix],
                     s=50,
                     label = '{} support vectors'.format(kernel_label[ix]))
    
    axes[ix].scatter(X[np.setdiff1d(np.arange(len(X)), svr.support_)],
                     y[np.setdiff1d(np.arange(len(X)), svr.support_)],
                     facecolor='none',
                     edgecolor=model_color[ix],
                     s=50,
                     label='other training data')
    
    axes[ix].legend(
        loc='upper center',
        bbox_to_anchor=(0.5, 1.1),
        ncol=1,
        fancybox=True,
        shadow=True
    )
    
fig.text(0.5, 0.04, 'data', ha='center', va='center')
fig.text(0.06, 0.5, 'target', ha='center', va='center', rotation='vertical')
fig.suptitle('Support Vector Regression', fontsize=14)
plt.show()

728x90

'adp 실기 > 알고리즘 이론' 카테고리의 다른 글

[Python] XGBoost  (0) 2022.08.19
[Python] RandomForest  (0) 2022.08.18
[Python] DecisionTree (의사결정나무)  (0) 2022.08.17
Comments