ikaros0427 2020. 2. 13. 08:51
반응형

서포트 벡터 머신(SVM, Support Vector Machine)은 서로 다른 분류에 속한 데이터 간에 간격이 최대가 되는 선(또는 평면)을 찾아 이를 기준으로 데이터를 분류하는 모델이다.

 

서포트 벡터 머신 모델

그림 10-10에 서포트 벡터 머신의 개념을 그림으로 나타냈다. 흰색 원과 검은색 원은 서로 다른 분류를 뜻한다. 서포트 벡터 머신은 각 분류에 속하는 데이터로부터 같은 간격으로, 그리고 최대로 멀리 떨어진 선 또는 평면을 찾는다. 이러한 선 또는 평면을 최대 여백 초평면(Maximum Margin Hyperplane)이라고 하고, 이 평면이 분류를 나누는 기준이 된다. 그림 10-10에서는 대각선 방향의 직선이 최대 여백 초평면에 해당한다. 그리고 이 직선과 가장 가까운 각 분류에 속한 점들을 서포트 벡터라고 한다.

그림 10-10

모든 데이터를 항상 초평면으로 나눌 수 있는 것은 아니다. 그림 10-11을 보자. 그림의 좌측에 보인 검은색 점과 흰색 점들은 X 축 위에 뒤섞여 있다. 이 두 분류를 구분할 수 있는 기준은 곡선이므로 ‘평면’을 찾는 서포트 벡터 머신을 사용할 수 없다.

 

이 문제는 커널 트릭(Kernel Trick)이라는 기법으로 해결한다. 커널 트릭의 기본 아이디어는 주어진 데이터를 적절한 고차원으로 옮긴 뒤 변환된 차원에서 서포트 벡터 머신을 사용해 초평면을 찾는 것이다. 예를 들어, 그림 10-11의 오른쪽에 보인 것처럼 데이터를 1차원에서 2차원으로 변환할 수 있다면 두 그룹을 나누는 직선을 찾을 수 있게 된다.

그림 10-11

 

서포트 벡터 머신 모델의 핵심 수식은 벡터 간 내적 계산이다. 커널 트릭에서는 실제로 데이터를 고차원으로 변환하는 대신 고차원에서 벡터 간 내적 계산을 했을 때와 같은 값을 반환하는 함수들을 사용한다. 이 함수들을 사용하면 마치 데이터를 고차원으로 옮긴 듯한 효과를 일으키면서도 데이터를 고차원으로 옮기는 데 따른 계산 비용 증가는 피할 수 있다. 이러한 함수들을 커널 함수(Kernel Function)라고 부른다.

 

커널 함수의 대표적인 예에는 다항 커널(Polynomial Kernel)과 가우시안 커널(Gaussian Kernel,레이디얼 베이스 함수 커널Radial Basis Function Kernel)이 있다. d차원 다항식에 대한 다항 커널을 식 10-8에 보였다.

식 10-8

다항 커널은 입력의 모든 차원의 조합인 공간에서 내적을 계산한 것과 같은 결과를 반환한다. 예를 들어, 2차원 입력 벡터 x=(x1 x2)T, y=(y1 y2)T에 d=2인 다항 커널을 사용하면 다음 결과를 얻는다.

결국 식 10-8은 (x1 x2)T을 다음에 보인 좌표로 옮긴 뒤 내적을 계산한 것과 같은 효과를 준다.

반면 가우시안 커널은 무한 차원으로 데이터를 옮긴 뒤 그곳에서 내적을 계산한 것과 같은 결과를 반환한다.

가우시안 커널을 식 10-9에 보였다.

식 10-9

 

서포트 벡터 머신 학습

SVM 모델을 위한 패키지에는 e1071, kernlab 등이 있다. e1071은 효율적인 SVM 구현체로 잘 알려진 libsvm을 R에서 사용할 수 있도록 한 패키지며, kernlab은 커널 기반의 기계 학습 알고리즘을 R에서 구현한 것으로 사용자가 C++ 코드의 수정 없이 기능을 손쉽게 확장할 수 있다. 표 10-9에 이 장에서 알아볼 kernlab, e1071 패키지의 함수들을 보였다.

 

  • kernlab::ksvm : 서포트 벡터 머신을 생성한다.

kernlab::ksvm(
  x,        # 모델 포뮬러
  data=NULL # 포뮬러를 적용할 데이터
)

kernlab::ksvm(
  x, y=NULL,  # 데이터
  # 데이터를 정규화할지 여부. 기본값인 TRUE는 평균 0, 분산 1이 되도록 데이터를 변환한다.
  scaled=TRUE,
  # 사용할 커널. 기본값은 rbfdot으로 Radial Basis Function이다. kernel에 지정할 수 있는
  # 함수의 목록은 help(kernlab::dots)에서 볼 수 있다.
  kernel="rbfdot",
  # 커널 파라미터를 리스트로 지정한다. kernel이 rbfdot인 경우 kpar를 automatic으로
  # 지정하면 데이터로부터 휴리스틱으로 적절한 파라미터를 찾는다.
  kpar="automatic"
)

 

  • ksvm::predict.ksvm : ksvm을 사용한 예측을 수행한다.

ksvm::predict.ksvm(
  object,   # ksvm 객체
  newdata,  # 예측을 수행할 데이터
  # 예측 결과의 유형. response는 예측값, probabilities는 확률을 반환한다.
  type="response"
)

 

  • e1071::svm : 서포트 벡터 머신을 생성한다.

e1071::svm(
  formula,     # 모델 포뮬러
  data=NULL,   # 데이터
)

e1071::svm(
  x, y=NULL,   # 데이터
  scale=TRUE,  # 변수를 정규화해야 하는지 여부
  # 분류, 회귀 등의 모델 중 만들 모델. y 값이 팩터인지 여부에 따라
  # 분류 또는 회귀 모델이 자동으로 지정되지만 type에 모델을 지정해 특정 모델을 강제할 수 있다.
  type = NULL,
  kernel ="radial",  # 커널 함수
  gamma=if(is.vector(x)) 1 else 1/ncol(x), # 커널 파라미터 gamma
  cost=1  # 커널 파라미터 cost
)

 

  • e1071::tune : 그리드 탐색(Grid Search; 인자로 주어진 모든 가능한 경우에 대해 테스트해보는 방식)을 사용한 파라미터 튜닝을 수행한다.

e1071::tune(
  method,   # 최적화할 함수
  train.x,  # 포뮬러 또는 독립 변수의 행렬을 지정
  train.y,  # 예측할 분류. 만약 train.x가 포뮬러면 무시
  data,     # 포뮬러를 적용할 데이터
  ...       # method에 추가로 전달할 인자
)

 

 

아이리스에 포뮬러를 사용하여 SVM 모델을 만들어보자.

> install.packages("kernlab")
> library(kernlab)
> (m <- ksvm(Species ~ ., data=iris))
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

Gaussian Radial Basis kernel function. 
 Hyperparameter : sigma =  0.476214318695748 

Number of Support Vectors : 70 

Objective Function Value : -5.611 -5.5261 -25.5803 
Training error : 0.02 

만들어진 모델로부터의 예측에는 predict( )를 사용한다.

> head(predict(m, newdata=iris))
[1] setosa setosa setosa setosa setosa setosa
Levels: setosa versicolor virginica

ksvm( ) 함수는 가우시안 커널을 기본으로 사용한다. 만약 커널 함수를 바꾸고 싶다면 kernel 파라미터에 원하는 함수를 지정한다. 다음은 vanilladot(특별한 변환 없이 내적을 계산함)을 지정한 예다.

> ksvm(Species ~., data=iris, kernel="vanilladot")
 Setting default kernel parameters  
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

Linear (vanilla) kernel function. 

Number of Support Vectors : 30 

Objective Function Value : -0.9559 -0.2781 -16.2753 
Training error : 0.02 

커널에 사용하는 파라미터는 kpar에 리스트 형태로 지정한다. 다음은 3차(degree=3) 다항 커널을 사용한 예다.

> (m <- ksvm(Species ~., data=iris, kernel="polydot", kpar=list(degree=3)))
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

Polynomial kernel function. 
 Hyperparameters : degree =  3  scale =  1  offset =  1 

Number of Support Vectors : 27 

Objective Function Value : -0.019 -0.0155 -4.817 
Training error : 0.006667 

 

SVM을 잘 사용하려면 파라미터 값을 잘 찾아야 한다. 파라미터를 정하는 한 가지 방법은 교차 검증이다. 또 다른 방법은 SVM 패키지가 제공하는 파라미터 튜닝을 사용하는 것이다.

 

e1071에서는 tune( ) 함수를 사용해 모델을 튜닝할 수 있다. help(tune)을 입력해 자세한 사용법을 알아보기 바란다. 다음은 가우시안 커널에서 gamma와 cost 파라미터를 찾는 example(tune)의 일부를 보여준다.

> install.packages("e1071")
> library(e1071)
> tune(svm, Species ~., data=iris, gamma=2^(-1:1), cost=2^(2:4))
Parameter tuning of `svm':
- sampling method: 10-fold cross validation
- best parameters:
  gamma cost
    0.5    4
- best performance: 0.05333333

tune( )의 반환 값은 객체며, 객체의 속성은 attributes( )로 살펴볼 수 있다. 다음은 최적 파라미터 값을 빼내는 코드의 예다.

> attributes(result)
$names
[1] "best.parameters" "best.performance" "method"       "nparcomb"
[5] "train.ind"       "sampling"         "performances" "best.model"

$class
[1] "tune"

> result$best.parameters           # 최적 파라미터
  gamma cost
1   0.5    4

> result$best.parameters["gamma"]  # 최적 파라미터 중 gamma
  gamma
1   0.5

> result$best.parameters["cost"]   # 최적 파라미터 중 cost
  cost
1    4

 

 

 

R을 이용한 데이터 처리&분석 실무 中

 

반응형