Support Vector Machine (SVM)
선형(Linear) SVM
- 딥러닝 이전에 분류에서 뛰어난 성능으로 가장 활용도가 높았던 분류모델
- 하나의 분류 그룹을 다른 그룹과 분리하는 최적의 경계를 찾아내는 알고리즘
- 중간크기의 데이터셋과 특성(Feature)이 많은 복잡한 데이터셋에서 성능이 좋은 것으로 알려져있다.
선 (1)과 (2)중 어떤 선이 최적의 분류 선일까?
목표: support vector간의 가장 넓은 margin을 가지는 초평면(결정경계)를 찾는다.
초평면
- 데이터가 존재하는 공간보다 1차원 낮은 부분공간
- n차원의 초평면은 n-1차원
- 공간을 나누기 위해 초평면을 사용한다.
- 1차원-점, 2차원-선, 3차원-평면, 4차원이상 초평면
- Support Vector: 경계를 찾아내는데 기준이 되는 데이터포인트. 초평면(결정경계)에 가장 가까이 있는 vector(데이터포인트)를 말한다.
- margin : 두 support vector간의 너비
- margin이 넓은 결정경계를 만드는 함수를 찾는 것.
Hard Margin, Soft Margin
- Overfitting(과적합)을 방지하기 위해 어느정도 오차를 허용하는 방식을 Soft margin이라고 한다. 반대로 오차를 허용하지 않는 방식을 Hard Margin이라고 한다.
- 모든 데이터셋이 위 그림 처럼 완전히 분류 되는 것은 아니다.
- 노이즈가 있는 데이터나 선형적으로 분리 되지 않는 경우 하이퍼파마미터인 C 조정해 마진을 변경한다.
- C
- 기본값 1
- 파라미터값을 크게주면 마진폭이 좁아져 마진 오류가 작아지나 Overfitting이 일어날 가능성이 크다.
- 파라미터값을 작게 주면 마진폭이 넓어져 마진 오류가 크다. 훈련데이터에서는 성능이 안좋아지나 일반화(generalization)되어 테스트 데이터의 성능이 올라간다. 그러나 underfitting 이 날 가능성이 있다.
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.svm import SVC, LinearSVC
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test =\
train_test_split(cancer.data, cancer.target, stratify=cancer.target)
# Scaling
# scaler = MinMaxScaler()
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
svm = SVC(kernel='linear') #선형 SVM
# svm = LinearSVC()
svm.fit(X_train_scaled, y_train)
pred_train = svm.predict(X_train_scaled)
pred_test = svm.predict(X_test_scaled)
pred_test = svm.predict(X_test_scaled)
from sklearn.metrics import accuracy_score
print("train정확도:", accuracy_score(y_train, pred_train))
print('test정확도:', accuracy_score(y_test, pred_test))
train정확도: 0.9929577464788732
-
MinMaxScaler
train정확도: 0.9812206572769953
test정확도: 0.972027972027972 -
StandardScaler
train정확도: 0.9929577464788732
test정확도: 0.972027972027972
C 의 변화에 따른 성능 확인
# 클수록 Hard margin
C_list = [0.01, 0.05, 0.1, 0.5, 1, 10]
train_acc_list = []
test_acc_list = []
for C in C_list:
svc = SVC(kernel='linear', C=C)
svc.fit(X_train_scaled, y_train)
train_acc_list.\
append(accuracy_score(y_train, svc.predict(X_train_scaled)))
test_acc_list.\
append(accuracy_score(y_test, svc.predict(X_test_scaled)))
import pandas as pd
d = dict(C=C_list,
train_정확도=train_acc_list,
test_정확도=test_acc_list)
df = pd.DataFrame(d)
df
import matplotlib.pyplot as plt
df.set_index('C').plot(figsize=(7,6))
plt.xlim(0,1.5)
plt.show()
커널 서포트 벡터 머신
비선형데이터 셋에 SVM 적용
-
선형으로 분리가 안되는 경우는?
-
다항식 특성을 추가하여 차원을 늘려 선형 분리가 되도록 변환
[원래 공간으로 변환]
차원을 늘리는 경우의 문제
- 다항식 특성을 추가하는 방법은 낮은 차수의 다항식은 데이터의 패턴을 잘 표현하지 못해 과소적합이 너무 높은 차수의 다항식은 과대적합과 모델을 느리게 하는 문제가 있다.
커널 트릭(Kernel trick)
- 다항식을 만들기 위한 특성을 추가하지 않으면서 수학적 기교를 적용해 다항식 특성을 추가한 것과 같은 결과를 얻을 수있다.
- 이런 방식을 커널 트릭이라고 한다.
방사기저(radial base function-RBF) 함수
- 커널 서포트 벡터 머신의 기본 커널 함수
- 기준점들이 되는 위치를 지정하고 각 샘플이 그 기준점들과 얼마나 떨어졌는 지를 계산한다. => 유사도(거리)
- 기준점 별 유사도 계산한 값은 원래 값보다 차원이 커지고 선형적으로 구분될 가능성이 커진다.
- rbf(radial basis function) 하이퍼파라미터
- C
- 오차 허용기준. 작은 값일 수록 많이 허용한다.
- 과적합일 경우 값을 감소시키고, 과소적합일 경우 값을 증가 시킨다.
- gamma
- 방사기저함수의 $\gamma$로 규제의 역할을 한다.
- 모델이 과대적합일 경우 값을 감소시키고, 과소적합일 경우 값을 증가시킨다.
- C
Guide
- 커널 기법은 다항식 차수를 만드는 것이 아니라 각 샘플을 함수에 넣어 나오는 값으로 같은 효과를 가지게 한다.
- C는 과적합이면 훈련셋에 타이트하게 맞춘 것이므로 오차허용을 좀 늘려서 공간을 확보해야 하므로 값을 줄인다. (작은 값일 수록 많이 허용)
과소적합이면 너무 오차허용을크게 잡은 것이므로 오차허용을 줄여야 하므로 값을 늘린다. (큰값은 적게 허용) - gamma 방사 기저함수 공식상 감마가 크면 반환값은 작아지고 감마가 작으면 반환값은 커진다. ($-\gamma$ 를 곱하므로)
- 감마가 작을 수록 값들의 거리가 멀어지고(큰값이 결과로 나오므로) 클 수록 거리가 가까워진다. 그래서 gamma 가 크면 거리가 타이트해져 과적합이 일어날 수있다. (공간의 여유가 없므으로)
- svm - 비선형 분리와 rbf 테스트.ipynb 문서 확인
from sklearn.svm import SVC
rbf_model = SVC(kernel='rbf', random_state=12,
gamma='auto', probability=True) #auto: 1/컬럼수, scale: 1/(컬럼수*X분산값)
rbf_model.fit(X_train_scaled, y_train)
# 평가
from sklearn.metrics import accuracy_score, confusion_matrix, roc_auc_score
pred_train = rbf_model.predict(X_train_scaled)
pred_test = rbf_model.predict(X_test_scaled)
print("Train 정확도 : ", accuracy_score(y_train, pred_train))
print('Test 정확도 : ', accuracy_score(y_test, pred_test))
Train 정확도 : 0.9859154929577465
Test 정확도 : 0.958041958041958
confusion_matrix(y_train, pred_train)
#array([[153, 6],
# [ 0, 267]], dtype=int64)
confusion_matrix(y_test, pred_test)
#array([[52, 1],
# [ 5, 85]], dtype=int64)
GridSearch로 최적의 조합찾기
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
param_grid = {'kernel':['rbf','linear'],
'C':[0.001,0.01,0.1,1,10,100],
'gamma':[0.001,0.01,0.1,1,10,100]}
svm = SVC()
g_search = GridSearchCV(svm,
param_grid,
scoring='accuracy',
cv=3,
n_jobs=-1)
pred_train = g_search.predict(X_train_scaled)
pred_test = g_search.predict(X_test_scaled)
print(accuracy_score(y_train, pred_train), accuracy_score(y_test, pred_test))
0.9859154929577465, 0.972027972027972
교차검증
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
from sklearn.preprocessing import MinMaxScaler
X_scaled = MinMaxScaler().fit_transform(X)
scores = cross_val_score(SVC(kernel='linear') , X_scaled , y , scoring='accuracy',cv=5)
scores
#==> array([0.96521739, 0.9826087 , 0.98230088, 0.96460177, 0.98230088])
iris DataSet으로 분류
- 다중 클래스 분류
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import numpy as np
import pandas as pd
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y)
# scaler = StandardScaler()
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# svm = SVC(kernel='linear')
svm = SVC()
svm.fit(X_train_scaled, y_train)
pred_train = svm.predict(X_train_scaled)
pred_test = svm.predict(X_test_scaled)'
accuracy_score(y_train, pred_train), accuracy_score(y_test, pred_test)
# (0.9553571428571429, 0.9736842105263158)
728x90
반응형
'Data Analysis & ML > Machine Learning' 카테고리의 다른 글
[Machine Learning][머신러닝][앙상블] Voting (0) | 2020.09.02 |
---|---|
[Machine Learning][머신러닝] Decision Tree(결정트리)와 RandomForest(랜덤포레스트) (0) | 2020.09.02 |
[Machine Learning][머신러닝][지도학습] K-최근접 이웃(KNN) (0) | 2020.09.01 |
[Machine Learning][머신러닝] 과적합과 해결방법(그리드서치/파이프라인) (0) | 2020.08.31 |
[Machine Learning][머신러닝] Classification(분류) 평가지표 (0) | 2020.08.28 |