본문 바로가기
내가 하는 데이터분석/내가 하는 머신러닝

[서포트 벡터 머신, Support Vector Machine] SVM with Python

by Pymoon 2023. 2. 5.

새로운 데이터가 입력되었을 때, 기존 데이터를 활용해서 분류하는 방법인 서포트 벡터 머신(Support Vector Machine)에 대해서 다뤄보자.

 

 

 

이 전의 머신러닝에서는 로지스틱 회귀를 이용해서 이진 분류다중 분류를 진행해 보았다.

 

로지스틱 회귀(Logistic Regression Model) with Python

선형 회귀모델을 분류로 사용해서 샘플이 특정 클래스에 속할 확률을 추정하는 데 사용하는 기법인 로지스틱 회귀(Logistic Regression)에 대해서 다뤄보자. 이 전의 머신러닝에서는 다중 회귀(Multiple

py-moon.tistory.com

 

 

 

 

 

서포트 벡터 머신은 지도학습 모델로서 회귀와 분류 문제를 해결할 때 사용되는 알고리즘이다.

 

회귀와 분류에서 사용되는 알고리즘이 다른데 각각 SVR(Regression), SVC(Classification)을 사용한다.

 

 

 

서포트 벡터 머신은 기본적으로 비선형 클래스 경계를 지원하는 알고리즘으로, 그 원리는 초평면(Hyperplane)마진(Margin)의 개념이 들어간다.

 

이에 대한 내용은 방대하지만 요약하자면, 관측치들(데이터)에서 초평면까지의 가장 짧은 거리인 마진이 가장 큰 분리 초평면을 찾는다. 

 

그리고, 초평면에 가장 가까이에 붙어있는 최전방 데이터를 서포트 벡터(Support Vector)라고 한다.

 

 

 

이러한 이론적인 개념을 참고하고 실습을 통해서 눈으로 확인해 보자.

 

 

 


 

첫 번째로 서포트 벡터 머신을 이용한 분류 알고리즘인 SVC(Classification) 실습은 캐글에서 지원하는 classification 데이터셋을 활용한다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 분류
from sklearn.metrics import confusion_matrix,accuracy_score,precision_score,recall_score,f1_score
from sklearn.svm import LinearSVC
from sklearn.svm import SVC
 
# 회귀
from sklearn.metrics import mean_squared_error,mean_absolute_error
from sklearn.svm import SVR
 
# 공통
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings(action='ignore')
 
cls = pd.read_csv('data/classification.csv')
cs

 

> 분류에 사용할 라이브러리, 회귀에 사용할 라이브러리를 각각 불러와주고, 공통으로 필요한 코드도 함께 작성한다.

 

> 그리고, 실습에 필요한 데이터를 불러와준다.

 

 

 

cls.head()

> cls.head()를 통해서 데이터의 현황을 파악한다.

 

 

 

sns.pairplot(hue = 'success', data = cls)

> 산점도를 통해서 데이터의 클래스 분포를 확인한다.

 

> 실습용 데이터라 그런지 이미 분류가 되어있는 듯한 모습을 확인할 수 있다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
from sklearn.model_selection import train_test_split
 
= cls[['age''interest']]
= cls['success']
 
train_x, test_x, train_y, test_y = train_test_split(x, y, stratify = y, train_size = 0.7, random_state = 1)
print(train_x.shape, test_x.shape, train_y.shape, test_y.shape)
 
 
(2072) (902) (207,) (90,)
cs

 

> 산점도에서 알 수 있었듯이 종속변수는 success변수이고, 독립변수는 age변수와 interest변수이다.

 

> 모델 학습을 위해 데이터 셋을 train, test로 각각 7 : 3으로 분할한다.

 

 

 

 

1
2
3
4
from sklearn.preprocessing import StandardScaler
 
scaler = StandardScaler()
train_x = scaler.fit_transform(train_x)
cs

 

> 상이한 두 독립변수의 단위 때문에 StandardScaler를 활용해서 데이터를 스케일링해준다.

 

 

 

sns.pairplot(data = pd.concat([pd.DataFrame(train_x), train_y.reset_index(drop = True)], axis = 1), hue = 'success')

> 데이터 분할과 스케일링을 거친 데이터의 산포도이다.

 

> 분포의 차이는 대동소이하여 티가 잘 나진 않지만, 스케일링으로 인해 x축과 y축의 단위가 달라졌음은 분명하다.

 

 

 

 

1
2
3
4
from sklearn.svm import SVC
 
clf = SVC()
clf.fit(train_x, train_y)
cs

 

> 별 다른 하이퍼파라미터 없이 객체를 생성하고 모델을 학습해 준다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from sklearn.metrics import confusion_matrix,accuracy_score,precision_score,recall_score,f1_score
 
test_x_scal = scaler.transform(test_x)
pred = clf.predict(test_x_scal)
 
test_cm = confusion_matrix(test_y, pred)
test_acc = accuracy_score(test_y, pred)
test_prc = precision_score(test_y, pred)
test_rcll = recall_score(test_y, pred)
test_f1 = f1_score(test_y, pred)
 
print(test_cm)
print('\n')
print('정확도 : {:.2f}%'.format(test_acc*100))
print('정밀도 : {:.2f}%'.format(test_prc*100))
print('재현율 : {:.2f}%'.format(test_rcll*100))
print('F1-score : {:.2f}%'.format(test_f1*100))
 
 
[[38  1]
 [ 2 49]]
 
정확도 : 96.67%
정밀도 : 98.00%
재현율 : 96.08%
F1-score : 97.03%
cs

 

> 분류분석에서 주로 사용하는 성능평가지표를 가져와서 해당 모델이 얼마만큼의 성능을 가지는지 확인해 본다.

 

> 내 눈으로도 분류가 금방 되는 데이터였는데 역시나 하면서 훌륭한 성능을 가지는 모델임을 알 수 있었다.

 

> 정확도가 약 96%를 자랑하는 모델이라고 해석할 수 있다.

 

 

 

> sklearn.svm에서 LinearSCV의 하이퍼파라미터에는 C가 있다.

 

> C는 정규화 파라미터이고, 정규화의 강도는 C에 반비례한다. 따라서, C의 값이 커지면 분류에 있어서 옳지 않은 데이터의 허용치가 증가하게 된다는 뜻이다.

 

> 이를 시각적으로 표현해 본다.

 

 

> 결과를 보면 C가 1일 때보다 C가 500일 때 오분류된 데이터가 더 많은 것을 확인할 수 있다.

 

> 이를 통해서 좀 더 엄격한 분류의 기준을 원한다면 낮은 C의 값으로 조정하는 것을 추천한다. 

 

 

 


 

두 번째로 서포트 벡터 머신을 이용한 회귀 알고리즘인 SVR(Regression) 실습은 numpy를 이용해서 데이터를 생성하여 활용한다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
 
= np.sort(5 * np.random.rand(401), axis = 0)
= np.sin(X).ravel()
y[::5+= 3 * (0.5 - np.random.rand(8))
 
 
= [[0.10394618]
 [0.3810394 ]
 [0.55027059]
 [0.68861259]
 [0.86718142]]
 
= [1.38157842 0.37188552 0.5229179  0.63546654 0.76250841]
cs

 

> 회귀 알고리즘인 SVR 실습을 위해서 numpy를 활용해 생성한 난수를 활용한다.

 

> y값에는 추가적인 노이즈를 더해준다.

 

 

 

 

1
2
3
4
5
6
7
8
9
from sklearn.svm import SVR
 
svr_rf = 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_rf.fit(X, y)
svr_lin.fit(X, y)
svr_poly.fit(X, y)
cs

 

> SVR에서 세 가지의 커널함수를 통해서 비교분석하며 그 성능을 테스트해본다.

 

> 차례대로 랜덤 포레스트(Random Forest), 선형 회귀(Linear Regression), 다항 회귀(Polynomial Regression)를 사용한다.

 

> 그다음 생성한 각각의 모델객체를 통해서 학습을 진행한다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from sklearn.metrics import mean_squared_error, mean_absolute_error
import pandas as pd
import numpy as np
 
rf_pred = svr_rf.predict(X)
lin_pred = svr_lin.predict(X)
poly_pred = svr_poly.predict(X)
 
preds = [rf_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)
cs

 

> 학습된 모델에 대해서 회귀분석에 사용되는 성능평가지표를 활용해 그 성능을 비교해 보자.

 

 

 

results

> 결과를 보면 세 모델 중에서는 선형 회귀를 사용한 SVR이 가장 오차가 크다고 해석할 수 있다.

 

> 다른 나머지 두 모델은 성능이 좋게 비슷해 보인다.

 

> 이를 시각화해서 좀 더 직관적인 비교를 진행해 보며 글을 마친다.

 

 

 

 

 

 


 

OUTTRO.

 

 

서포트 벡터 머신은 분류의 개념인 초평면과 마진 때문에 분류에만 쓰인다고 생각했다. 그렇게 사용했었다.

 

회귀 알고리즘도 존재하는 것이 새로운 부분이었지만, 커널함수로 랜덤 포레스트, 선형회귀, 다항회귀를 사용할 수 있는 부분을 접하고는 차라리 커널함수로 사용되는 모델 자체를 사용하는 것이 더 좋겠다고 생각한다.

 

SVM의 분류 알고리즘은 지표를 통해서 확인했듯이, 훌륭한 알고리즘이다.

 

 

 

이렇듯 새롭게 접하는 지식과 실습을 진행할 수 있게 해주는 참고서적인 [파이썬 한 권으로 끝내기]를 유용하게 활용 중이다.

 

데이터 분석 분야는 언어별로 다르겠지만 파이썬으로 출간된 서적이 생각보다 그리 많지는 않다. 하지만 꼭 필요하다.