### 2021.12.22

 

 

 

서포트 벡터 머신(Support Vector Machines)

  • 회귀, 분류, 이상치 탐지 등에 사용되는 지도학습 방법
  • 클래스 사이의 경계에 위치한 데이터 포인트를 서포트 벡터(support vector)라고 함
  • 각 지지 벡터가 클래스 사이의 결정 경계를 구분하는데 얼마나 중요한지를 학습
  • 각 지지 벡터 사이의 마진이 가장 큰 방향으로 학습
  • 지지 벡터 까지의 거리와 지지 벡터의 중요도를 기반으로 예측을 수행

  • H3은 두 클래스의 점들을 제대로 분류하고 있지 않음
  • H1과 H2는 두 클래스의 점들을 분류하는데, H2가 H1보다 더 큰 마진을 갖고 분류하는 것을 확인할 수 있음
import multiprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use(['seaborn-whitegrid'])

from sklearn.svm import SVR, SVC
from sklearn.datasets import load_boston, load_diabetes
from sklearn.datasets import load_breast_cancer, load_iris, load_wine
from sklearn.pipeline import make_pipeline, Pipeline
from sklearn.model_selection import train_test_split, cross_validate, GridSearchCV
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.manifold import TSNE

SVM을 이용한 회귀 모델과 분류 모델

SVM을 사용한 회귀 모델 (SVR)

#In[]
X, y = load_boston(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=123)

model = SVR()
model.fit(X_train, y_train)

print("학습 데이터 점수 : {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수 : {}".format(model.score(X_test, y_test)))

#Out[]
학습 데이터 점수 : 0.2177283706374875
평가 데이터 점수 : 0.13544178468518187

 

SVM을 사용한 분류 모델 (SVC)

#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=123)

model = SVC()
model.fit(X_train, y_train)

print("학습 데이터 점수 : {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수 : {}".format(model.score(X_test, y_test)))

#Out[]
학습 데이터 점수 : 0.9014084507042254
평가 데이터 점수 : 0.9230769230769231

 

커널 기법

  • 입력 데이터를 고차원 공간에 사상해서 비선형 특징을 학습할 수 있도록 확장하는 방법
  • scikit-learn에서는 Linear, Polynomial, RBF(Radial Basis Function)등 다양한 커널 기법을 지원

#In[]
X, y = load_boston(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=123)

linear_svr = SVR(kernel='linear')
linear_svr.fit(X_train, y_train)

print('Linear SVR 학습 데이터 점수 : {}'.format(linear_svr.score(X_train, y_train)))
print('Linear SVR 평가 데이터 점수 : {}'.format(linear_svr.score(X_test, y_test)))
print()

polynomial_svr = SVR(kernel='poly')
polynomial_svr.fit(X_train, y_train)

print('Polynomial SVR 학습 데이터 점수 : {}'.format(polynomial_svr.score(X_train, y_train)))
print('Polynomial SVR 평가 데이터 점수 : {}'.format(polynomial_svr.score(X_test, y_test)))
print()

rbf_svr = SVR(kernel='rbf')
rbf_svr.fit(X_train, y_train)

print('RBF SVR 학습 데이터 점수 : {}'.format(rbf_svr.score(X_train, y_train)))
print('RBF SVR 평가 데이터 점수 : {}'.format(rbf_svr.score(X_test, y_test)))

#Out[]
Linear SVR 학습 데이터 점수 : 0.715506620496448
Linear SVR 평가 데이터 점수 : 0.6380398541506058

Polynomial SVR 학습 데이터 점수 : 0.2024454261446289
Polynomial SVR 평가 데이터 점수 : 0.133668450367462

RBF SVR 학습 데이터 점수 : 0.2177283706374875
RBF SVR 평가 데이터 점수 : 0.13544178468518187
#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=123)

linear_svc = SVC(kernel='linear')
linear_svc.fit(X_train, y_train)

print('Linear SVC 학습 데이터 점수 : {}'.format(linear_svc.score(X_train, y_train)))
print('Linear SVC 평가 데이터 점수 : {}'.format(linear_svc.score(X_test, y_test)))
print()

polynomial_svc = SVC(kernel='poly')
polynomial_svc.fit(X_train, y_train)

print('Polynomial SVC 학습 데이터 점수 : {}'.format(polynomial_svc.score(X_train, y_train)))
print('Polynomial SVC 평가 데이터 점수 : {}'.format(polynomial_svc.score(X_test, y_test)))
print()

rbf_svc = SVC(kernel='rbf')
rbf_svc.fit(X_train, y_train)

print('RBF SVC 학습 데이터 점수 : {}'.format(rbf_svc.score(X_train, y_train)))
print('RBF SVC 평가 데이터 점수 : {}'.format(rbf_svc.score(X_test, y_test)))

#Out[]
Linear SVC 학습 데이터 점수 : 0.960093896713615
Linear SVC 평가 데이터 점수 : 0.986013986013986

Polynomial SVC 학습 데이터 점수 : 0.9014084507042254
Polynomial SVC 평가 데이터 점수 : 0.9230769230769231

RBF SVC 학습 데이터 점수 : 0.9014084507042254
RBF SVC 평가 데이터 점수 : 0.9230769230769231

 

매개변수 튜닝

  • SVM은 사용하는 커널에 따라 다양한 매개변수 설정 가능
  • 매개변수를 변경하면서 성능변화를 관찰
#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=123)

polynomial_svc = SVC(kernel='poly', degree=2, C=0.1, gamma='auto')
polynomial_svc.fit(X_train, y_train)

print("kernel=poly, degree={}, C={}, gamma={}".format(2, 0.1, 'auto'))
print('Polynomial SVC 학습 데이터 점수 : {}'.format(polynomial_svc.score(X_train, y_train)))
print('Polynomial SVC 평가 데이터 점수 : {}'.format(polynomial_svc.score(X_test, y_test)))

#Out[]
kernel=poly, degree=2, C=0.1, gamma=auto
Polynomial SVC 학습 데이터 점수 : 0.9835680751173709
Polynomial SVC 평가 데이터 점수 : 0.993006993006993
#In[]
rbf_svc = SVC(kernel='rbf', C=2.0, gamma='scale')
rbf_svc.fit(X_train, y_train)

print("kernel=poly, C={}, gamma={}".format(2.0, 'scale'))
print('RBF SVC 학습 데이터 점수 : {}'.format(rbf_svc.score(X_train, y_train)))
print('RBF SVC 평가 데이터 점수 : {}'.format(rbf_svc.score(X_test, y_test)))

#Out[]
kernel=poly, C=2.0, gamma=scale
RBF SVC 학습 데이터 점수 : 0.9154929577464789
RBF SVC 평가 데이터 점수 : 0.9370629370629371

 

데이터 전처리

  • SVM은 입력 데이터가 정규화 되어야 좋은 성능을 보임
  • 주로 모든 특성 값을 [0, 1] 범위로 맞추는 방법을 사용
  • scikit-learn의 StandardScaler 또는 MinMaxScaler를 사용해 정규화
#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=123)

model = SVC()
model.fit(X_train, y_train)

print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.9014084507042254
SVC 평가 데이터 점수 : 0.9230769230769231

전처리후 (StandardScaler)

#In[]
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

model = SVC()
model.fit(X_train, y_train)

print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.9835680751173709
SVC 평가 데이터 점수 : 0.986013986013986

전처리후 (MinMaxScaler)

#In[]
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

model = SVC()
model.fit(X_train, y_train)

print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.9812206572769953
SVC 평가 데이터 점수 : 0.986013986013986

 

Linear SVR

보스턴 주택 가격

#In[]
X, y = load_boston(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

model = SVR(kernel='linear')
model.fit(X_train, y_train)

#Out[]
SVR(kernel='linear')
#In[]
print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.7049306073822006
SVC 평가 데이터 점수 : 0.7305576277109267
#In[]
#저차원으로 단축
X_comp = TSNE(n_components=1).fit_transform(X)
plt.scatter(X_comp, y)

#Out[]

#In[]
model.fit(X_comp, y)
predict = model.predict(X_comp)
plt.scatter(X_comp, y)
plt.scatter(X_comp, predict, color='r')

#Out[]

#In[]
estimator = make_pipeline(StandardScaler(), SVR(kernel='linear'))

cross_validate(
    estimator=estimator,
    X=X, y=y,
    cv=5,
    n_jobs=multiprocessing.cpu_count(),
    verbose=True)
    
#Out[]
[Parallel(n_jobs=4)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=4)]: Done   5 out of   5 | elapsed:    1.8s finished
{'fit_time': array([0.02629495, 0.02607703, 0.02571988, 0.02510285, 0.02014399]),
 'score_time': array([0.00453615, 0.00336313, 0.00348997, 0.00344706, 0.00237799]),
 'test_score': array([0.76908568, 0.72180141, 0.56428426, 0.14083339, 0.07810211])}
#In[]
pipe = Pipeline([('scaler', StandardScaler()),
                ('model', SVR(kernel='linear'))])

param_grid = [{'model__gamma' : ['scale', 'auto'],
              'model__C' : [1.0, 0.1, 0.01],
              'model__epsilon' : [1.0, 0.1, 0.01]}]

gs = GridSearchCV(estimator=pipe,
                 param_grid=param_grid,
                 n_jobs=multiprocessing.cpu_count(),
                 cv=5,
                 verbose=True)

gs.fit(X,y)

#Out[]
Fitting 5 folds for each of 18 candidates, totalling 90 fits
GridSearchCV(cv=5,
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('model', SVR(kernel='linear'))]),
             n_jobs=4,
             param_grid=[{'model__C': [1.0, 0.1, 0.01],
                          'model__epsilon': [1.0, 0.1, 0.01],
                          'model__gamma': ['scale', 'auto']}],
             verbose=True)
#In[]
gs.best_estimator_

#Out[]
Pipeline(steps=[('scaler', StandardScaler()),
                ('model', SVR(C=0.1, epsilon=1.0, kernel='linear'))])

 

Kernel SVR

보스턴 주택 가격

#In[]
X, y = load_boston(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

model = SVR(kernel='rbf')
model.fit(X_train, y_train)

#Out[]
SVR()
#In[]
print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.6785031123396097
SVC 평가 데이터 점수 : 0.6548972350224054
#In[]
#저차원으로 단축
X_comp = TSNE(n_components=1).fit_transform(X)
plt.scatter(X_comp, y)

#Out[]

#In[]
model.fit(X_comp, y)
predict = model.predict(X_comp)
plt.scatter(X_comp, y)
plt.scatter(X_comp, predict, color='r')

#Out[]

#In[]
estimator = make_pipeline(StandardScaler(), SVR(kernel='rbf'))

cross_validate(
    estimator=estimator,
    X=X, y=y,
    cv=5,
    n_jobs=multiprocessing.cpu_count(),
    verbose=True)
    
#Out[]
[Parallel(n_jobs=4)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=4)]: Done   5 out of   5 | elapsed:    0.1s finished
{'fit_time': array([0.051826  , 0.04972219, 0.03561997, 0.03072095, 0.02156925]),
 'score_time': array([0.01787186, 0.02123976, 0.02434206, 0.01307511, 0.00709677]),
 'test_score': array([ 0.75781445,  0.50211018,  0.04310107,  0.33851703, -0.75997942])}
#In[]
pipe = Pipeline([('scaler', StandardScaler()),
                ('model', SVR(kernel='rbf'))])

param_grid = [{'model__kernel' : ['rbf', 'polynomial', 'sigmoid']}]

gs = GridSearchCV(estimator=pipe,
                 param_grid=param_grid,
                 n_jobs=multiprocessing.cpu_count(),
                 cv=5,
                 verbose=True)

gs.fit(X,y)

#Out[]
Fitting 5 folds for each of 3 candidates, totalling 15 fits
GridSearchCV(cv=5,
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('model', SVR())]),
             n_jobs=4,
             param_grid=[{'model__kernel': ['rbf', 'polynomial', 'sigmoid']}],
             verbose=True)
#In[]
print(gs.best_estimator_)
print(gs.best_score_)
print(gs.best_params_)

#Out[]
Pipeline(steps=[('scaler', StandardScaler()), ('model', SVR())])
0.17631266230186618
{'model__kernel': 'rbf'}
#In[]
pipe = Pipeline([('scaler', StandardScaler()),
                ('model', SVR(kernel='rbf'))])

param_grid = [{'model__gamma' : ['scale', 'auto'],
              'model__C' : [1.0, 0.1, 0.01],
              'model__epsilon' : [1.0, 0.1, 0.01]}]

gs = GridSearchCV(estimator=pipe,
                 param_grid=param_grid,
                 n_jobs=multiprocessing.cpu_count(),
                 cv=5,
                 verbose=True)

gs.fit(X,y)

#Out[]
Fitting 5 folds for each of 18 candidates, totalling 90 fits
GridSearchCV(cv=5,
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('model', SVR())]),
             n_jobs=4,
             param_grid=[{'model__C': [1.0, 0.1, 0.01],
                          'model__epsilon': [1.0, 0.1, 0.01],
                          'model__gamma': ['scale', 'auto']}],
             verbose=True)
#In[]
print(gs.best_estimator_)
print(gs.best_score_)
print(gs.best_params_)

#Out[]
Pipeline(steps=[('scaler', StandardScaler()), ('model', SVR(epsilon=0.01))])
0.1780747543330848
{'model__C': 1.0, 'model__epsilon': 0.01, 'model__gamma': 'scale'}

 

Linear SVC

유방암

#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

model = SVC(kernel='linear')
model.fit(X_train, y_train)

#Out[]
SVC(kernel='linear')
#In[]
print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.989010989010989
SVC 평가 데이터 점수 : 0.956140350877193
def make_meshgrid(x,y,h=0.02):
    x_min, x_max = x.min()-1, x.max()+1
    y_min, y_max = y.min()-1, y.max()+1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                        np.arange(y_min, y_max, h))
    
    return xx, yy
    
def plot_contours(clf, xx, yy, **params):
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    out = plt.contourf(xx, yy, Z, **params)
    
    return out
#In[]
#저차원으로 단축
X_comp = TSNE(n_components=2).fit_transform(X)
X0, X1 = X_comp[:,0], X_comp[:,1]
xx, yy = make_meshgrid(X0,X1)

model.fit(X_comp, y)

plot_contours(model, xx, yy, cmap=plt.cm.coolwarm, alpha=0.7)
plt.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k')

#Out[]

#In[]
estimator = make_pipeline(StandardScaler(), SVC(kernel='linear'))

cross_validate(
    estimator=estimator,
    X=X, y=y,
    cv=5,
    n_jobs=multiprocessing.cpu_count(),
    verbose=True)
    
#Out[]
{'fit_time': array([0.00987267, 0.00888181, 0.01295686, 0.01195097, 0.01462102]),
 'score_time': array([0.00420117, 0.00178409, 0.00421095, 0.01408386, 0.00151491]),
 'test_score': array([0.96491228, 0.98245614, 0.96491228, 0.96491228, 0.98230088])}
#In[]
pipe = Pipeline([('scaler', StandardScaler()),
                ('model', SVC(kernel='linear'))])

param_grid = [{'model__gamma' : ['scale', 'auto'],
              'model__C' : [1.0, 0.1, 0.01]}]

gs = GridSearchCV(estimator=pipe,
                 param_grid=param_grid,
                 n_jobs=multiprocessing.cpu_count(),
                 cv=5,
                 verbose=True)

gs.fit(X,y)

#Out[]
GridSearchCV(cv=5,
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('model', SVC(kernel='linear'))]),
             n_jobs=4,
             param_grid=[{'model__C': [1.0, 0.1, 0.01],
                          'model__gamma': ['scale', 'auto']}],
             verbose=True)
#In[]
print(gs.best_estimator_)
print(gs.best_score_)
print(gs.best_params_)

#Out[]
Pipeline(steps=[('scaler', StandardScaler()),
                ('model', SVC(C=0.1, kernel='linear'))])
0.9736531594472908
{'model__C': 0.1, 'model__gamma': 'scale'}

 

Kernel SVC

유방암

#In[]
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)

scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

model = SVC(kernel='rbf')
model.fit(X_train, y_train)

#Out[]
SVC()
#In[]
print('SVC 학습 데이터 점수 : {}'.format(model.score(X_train, y_train)))
print('SVC 평가 데이터 점수 : {}'.format(model.score(X_test, y_test)))

#Out[]
SVC 학습 데이터 점수 : 0.989010989010989
SVC 평가 데이터 점수 : 0.9473684210526315
#In[]
#저차원으로 단축
X_comp = TSNE(n_components=2).fit_transform(X)
X0, X1 = X_comp[:,0], X_comp[:,1]
xx, yy = make_meshgrid(X0,X1)

model.fit(X_comp, y)

plot_contours(model, xx, yy, cmap=plt.cm.coolwarm, alpha=0.7)
plt.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k')

#Out[]

#In[]
estimator = make_pipeline(StandardScaler(), SVC(kernel='rbf'))

cross_validate(
    estimator=estimator,
    X=X, y=y,
    cv=5,
    n_jobs=multiprocessing.cpu_count(),
    verbose=True)
    
#Out[]
{'fit_time': array([0.01440001, 0.01281619, 0.01279497, 0.01421213, 0.01107621]),
 'score_time': array([0.00482988, 0.00510478, 0.0063343 , 0.00894904, 0.00442004]),
 'test_score': array([0.97368421, 0.95614035, 1.        , 0.96491228, 0.97345133])}
#In[]
pipe = Pipeline([('scaler', StandardScaler()),
                ('model', SVC(kernel='rbf'))])

param_grid = [{'model__gamma' : ['scale', 'auto'],
              'model__C' : [1.0, 0.1, 0.01]}]

gs = GridSearchCV(estimator=pipe,
                 param_grid=param_grid,
                 n_jobs=multiprocessing.cpu_count(),
                 cv=5,
                 verbose=True)

gs.fit(X,y)

#OUt[]
GridSearchCV(cv=5,
             estimator=Pipeline(steps=[('scaler', StandardScaler()),
                                       ('model', SVC())]),
             n_jobs=4,
             param_grid=[{'model__C': [1.0, 0.1, 0.01],
                          'model__gamma': ['scale', 'auto']}],
             verbose=True)
#In[]
print(gs.best_estimator_)
print(gs.best_score_)
print(gs.best_params_)

#Out[]
Pipeline(steps=[('scaler', StandardScaler()), ('model', SVC())])
0.9736376339077782
{'model__C': 1.0, 'model__gamma': 'scale'}

 

 

+ Recent posts