Machine Learning/Coding

[실습]SVM(Support Vector Machine)

ju_young 2021. 5. 27. 18:10
728x90

먼저 csv파일을 불러오고 train 데이터와 test 데이터를 나눠주겠다.

 

  • 데이터 불러오기
import pandas as pd

df = pd.read_csv("./drive/MyDrive/basketball_stat.csv") #구글 드라이브 내에 있는 파일을 불러옴
df.head()

 

  • 데이터 분리
from sklearn.model_selection import train_test_split

#80%는 학습 데이터, 20%는 테스트 데이터로 분리
train, test = train_test_split(df, test_size=0.2)

#학습 데이터, 테스트 데이터 개수 확인
print(train.shape[0])
print(test.shape[0])

 

최적의 SVM 파라미터 찾기

이제 불러온 데이터를 RBF 커널을 사용하여 실습을 할 것인데 그 전에 최적의 비용(C)와 감마(gamma)값을 찾아야한다. 이 때 이 두개의 파라미터 값을 그리드 서치(grid search)를 사용하여 찾을 것이다.

from sklearn.model_selection import GridSearchCV # 그리드 서치 사용
from sklearn.metrics import classification_report, accuracy_score # 분류 실행 결과 report를 보여주는 classification_report, 정확도 점수(accuracy_score)
from sklearn.svm import SVC # SVM 모델
import numpy as np

def svc_param_selection(X, y, nfolds): #nfolds는 교차 검증 수를 의미한다
  svm_parameters = [
                    {'kernel' : ['rbf'],
                     'gamma' : [0.00001, 0.0001, 0.001, 0.01, 0.1, 1],
                    'C' : [0.01, 0.1, 1, 10, 100, 1000]}
  ]
  #사이킷런에서 제공하는 GridSearchCV를 사용해 최적의 파라미터를 구함
  clf = GridSearchCV(SVC(), svm_parameters, cv=nfolds, scoring='accuracy') # estimator, param_grid, cross-validation
  clf.fit(X_train, y_train.values.ravel())
  print(clf.best_params_) #최고 점수를 낸 파라미터 출력

  return clf

#3점숫과 블로킹 획수를 학습 데이터로 사용
X_train = train[['3P', 'BLK']]

#농구선수 포지션을 예측값으로 선정
y_train = train[['Pos']]

#최적의 파라미터로 학습된 모델을 clf로 저장
clf = svc_param_selection(X_train, y_train.values.ravel(), 10)

위 코드에서 주의깊게 봐야할 것이 GridSearchCV 함수이다. 인자 값으로 estimator, param_grid, cross-validation, scoring 등을 지정하는데 param_grid에는 비용, 감마 값이 될 후보들을 dictionary 형식으로 지정하고 cross-validation은 교차 검증을 수행하기 위한 숫자 값을 지정하는 것이다. estimator는 보듯이 사용할 모델을 지정하고 scoring는 어떤 점수를 기준으로 할 것이냐를 지정하는 것이다.

이렇게 인자 값을 지정하고 train 데이터를 학습하면 각 비용과 감마 값을 하나씩 집어 넣어보고 교차 검증까지 수행한다. 그리고 best_params_함수를 사용하여 가장 최적의 비용과 감마 값을 알아낼 수 있다.

 

[출력]

{'C': 1, 'gamma': 1, 'kernel': 'rbf'}

 

결정 경계선 시각화

import matplotlib.pyplot as plt

# 시각화할 비용 후보들을 저장
C_candidates = []
C_candidates.append(clf.best_params_['C'] * 0.01)
C_candidates.append(clf.best_params_['C'])
C_candidates.append(clf.best_params_['C'] * 100)

# 시각화할 감마 후보들을 저장
gamma_candidates = []
gamma_candidates.append(clf.best_params_['gamma'] * 0.01)
gamma_candidates.append(clf.best_params_['gamma'])
gamma_candidates.append(clf.best_params_['gamma'] * 100)

# 3점슛과 블로킹 횟수로 학습
X = train[['3P', 'BLK']]
#농구선수 포지션을 학습 모델의 분류값으로 사용
Y = train['Pos'].tolist()

#시각화를 위해 센터(c)와 슈팅가드(SG)를 숫자로 표현
position = []
for gt in Y:
  if gt == 'C':
    position.append(0)
  else:
    position.append(1)

classifiers = []

# 파라미터 후보들을 조합해서 학습된 모델들을 저장
for C in C_candidates:
  for gamma in gamma_candidates:
    clf = SVC(C=C, gamma=gamma)
    clf.fit(X, Y)
    classifiers.append((C, gamma, clf))

#각 모델을 시각화
plt.figure(figsize=(18, 18))
xx, yy = np.meshgrid(np.linspace(0, 4, 100), np.linspace(0, 4, 100))

for (k, (C, gamma, clf)) in enumerate(classifiers):
  Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) # np.c_[xx.ravel(), yy.ravel()]에 대한 신뢰도 예측 -> (10000,)
  Z = Z.reshape(xx.shape) # (100, 100)

  plt.subplot(len(C_candidates), len(gamma_candidates), k + 1)
  plt.title("gamma=10^%d, C=10^%d" % (np.log10(gamma), np.log10(C)),
            size='medium')

  plt.pcolormesh(xx, yy, Z, cmap=plt.cm.RdBu) # Z의 값을 RdBu colormap에 매핑됨
  plt.scatter(X['3P'], X['BLK'], c=position, cmap=plt.cm.RdBu_r, edgecolors='k')

여기서는 각 파라미터 후보들을 학습한 모델을 저장하고 시각화하는 부분만 조금 신경써서 보면 될 것 같다.

  1. np.linespace(0,4,100)는 0에서 4까지 100등분을 한다는 의미이다.
  2. clf.decision_function는 지정한 데이터에 대한 신뢰도를 예측한다. 간단히 말하면 X와 Y값을 양수와 음수로 판단하여 실수 값으로 반환한다는 것이다. 그리고 반환한 값의 shape은 (n,)으로 나온다.
  3. np.c_[xx.ravel(), yy.ravel()]에서 np.c_는 하나의 colmn으로 함치는 함수이다. 즉, (100,)와 (100,)이 (10000,)으로 합쳐진다는 것이다.
  4. pcolormesh에서 집어넣은 Z값은 RdBu라는 colormap에 매핑되어 나타난다. 예를 들어서 값이 [0.8, 1, 1.5]가 있다면 0.8은 red에 가깝게, 1은 white에 가깝게, 1.5는 blue에 가깝게 매핑될 것이다.

[출력]

 

모델 테스트

X_test = test[['3P', 'BLK']]
y_test = test[['Pos']]

# 최적의 파라미터로 학습된 모델로 테스트를 진행
y_true, y_pred = y_test, clf.predict(X_test)

print(classification_report(y_true, y_pred))
print("accuracy :", str(accuracy_score(y_true, y_pred))) # 실제 값과 예측 값에 대한 정확도 점수

classification_report를 사용하여 분류 결과에 대한 report를 출력하고 accuracy_score를 사용하여 정확도를 출력한다.


[출력]

              precision    recall  f1-score   support

           C       1.00      0.90      0.95        10
          SG       0.91      1.00      0.95        10

    accuracy                           0.95        20
   macro avg       0.95      0.95      0.95        20
weighted avg       0.95      0.95      0.95        20

accuracy : 0.95

comparison = pd.DataFrame({'prediction':y_pred,
                           'ground_truth':y_true.values.ravel()})
comparison

실제 예측한 값을 확인하면 다음과 같다.


[출력]

이렇게 [https://github.com/wikibook/machine-learning]에서 다운로드 받은 농구선수에 대한 데이터를 사용하여 SVM 알고리즘을 적용해보는 실습을 마친다.

728x90