50. SVM(Support Vector Machine)
in Study on R Programming
Overview
지도 학습 알고리즘의 하나인 SVM에 대해 알아본다.
SVM(Support Vector Machine)
SVM은 서로 다른 분류에 속한 데이터 간에 간격이 최대가 되는 선(또는 평면)을 찾아 이를 기준으로 데이터를 분류하는 모델이다.
즉, 선을 구성하는 매개 변수를 조정하여 요소들을 구분 짓는 선을 찾고, 이것을 기반으로 pattern을 인식하는 기법이다.
식별 선이나 평면에서 패턴들과의 거리(마진)를 최대로 만들어 내는 것이 목표이다.
기본적으로 지도 학습 알고리즘이며, HyperPlane(초평면)을 이용하여 카테고리를 나눈다.
SVM을 사용하게 되면 알 수 없는 패턴도 제대로 분류할 확률이 굉장히 높다.(일반화 능력)
사용처
유전자 데이터의 분류(classification)
텍스트 분류(주제별 분류, 언어의 식별)
회귀 분석(regression)
제한/참고 사항
SVM 학습기가 처리하는 모든 속성은 수치 값이어야 한다.
모든 속성들의 수치 값의 분포가 너무 크지 않아야 하고, 이런 경우에는 반드시 정규화나 표준화를 수행할 필요가 있다.
선형 분리
선형 분리란 임의의 공간에 직선을 그어서 서로 다른 분류를 분리시키는 것을 말한다.
다음 그림에서 좌측 예시는 선형 분리가 가능한 경우이고, 우측 예시는 선형 분리가 불가능한 예시이다.
최적화된 분리선 조건
SVM은 가장 큰 마진을 가져가는 방향으로 분류를 수행(최대 마진화 방침)해야 한다.
그 이유는 차후에 새로운 데이터가 들어오더라도 잘 분류될 가능성이 커지기 때문이다.
초평면과 지지 벡터
다음 그림에서 분리를 할 수 있는 직선은 많지만 두 개의 분류에서 가장 멀리 떨어진 구분선을 최적 선형 구분자 라고 할 수 있다.
녹색 선, 또는 평면을 최대 여백 초평면이라고 부른다.
또한 녹색 점선으로 되어 있는 부분을 Support Vector라고 한다.
용어 정리
항목 | 설명 |
---|---|
최대 여백 초평면 | Maximum Margin Hyperplane 한쪽면으로 동일한 데이터가 놓이게 하는 선형 경계면 각 분류에 속하는 데이터로부터 같은 간격으로 가장 멀리 떨어진 선(2차원) 또는 평면(3차원) 이 평면(또는 직선)이 분류를 나누는 기준이 됨 |
Support Vector | 최대 여백 초평면과 가장 가까운 각 분류에 속한 점 margin을 구할때 supporting하는 support vector |
Kernel Trick | 저차원에서 선형적으로 구분이 안되지만, mapping(사상)을 통해 고차원적으로 변형시키면 선형 구분이 가능하도록 하는 기법 |
Kernel Function | Kernel trick에 사용되는 함수 커널 함수의 예는 다항(Polynomial) kernel과 가우시안(Gaussian) kernel이 있음 |
Convex hull | 각 그룹의 데이터 점들의 가장 외곽 경계 두 Convex hull의 거리가 가장 짧은 지점을 수직 이등분 |
Kernel Trick
비선형적인 데이터를 구분하고자 할 때 특성을 추가하면 선형적으로 구분할 수 있다.
하지만 낮은 차수의 다항식은 매우 복잡한 데이터 셋을 잘 표현하지 못하고, 높은 차수의 다항식은 굉장히 많은 특성을 추가하므로 모델을 느리게 만든다.
특성을 추가하지 않고, 마치 특성을 추가한 듯한 효과를 낼수 있는 기법이 커널 트릭(kernel trick)이다.
선형적으로 구분이 되지 않는 데이터를 분류하기 위해서는 커널 트릭을 사용한다.
주어진 데이터를 고차원으로 옮긴 뒤 변환한 차원에서 서포트 벡터 머신을 이용하여 초평면을 찾는 것이다.
다음 그림과 같이 1차원의 데이터를 2차원으로 옮기면 최적의 직선을 찾을 수 있다.
Kernel Trick의 Mapping(사상)
저차원에서는 선형적으로 구분이 불가능하지만, mapping(사상) 이라는 개념을 통하여 고차원으로 변형 시켜 선형적으로 구분이 가능하도록 하는 기법이다.
이때 사용되는 함수를 커널 함수라고 부른다.
커널 함수의 대표적인 예시는 다항 커널과 가우시안 커널 방식이 있다.
R에서 사용하는 SVM 패키지
R로 SVM 모델을 적합화하려 할 때, 선택할 수 있는 몇 개의 패키지가 있다.
- e12071
- 비엔나 기술 대학 통계학과
- 효율적인 SVM 구현체로 잘 알려진 LIBSVM을 R에서 사용
- C++로 작성된 오픈 소스 SVM 프로그램
- klaR
- 도르트문트 기술 대학의 SVMlight 알고리즘
- kernlab
- 커널 기반의 기계 학습 알고리즘을 R에서 구현
- C++ 코드의 수정 없이 손쉽게 기능을 확장
- SVM 모델의 여러 가지 자동화된 기법을 사용해 훈련할 수 있는 catet 패키지와 같이 사용 가능
Support Vector Machine 사용
서포트 벡터 머신 알고리즘을 수행하려면 kernlab 패키지의 ksvm()
함수를 사용한다.
항목 | 설명 |
---|---|
사용 형식 | letter_classifier <- ksvm(target ~ predictors, data, kernel, C, scaled = TRUE, kpar = "automatic") |
target | 모델링하고자 하는 데이터 종속 변수 |
predictors | 예측에 사용하고자 하는 독립 변수의 모음 |
data | 학습을 수행하기 위한 훈련용 데이터 셋 |
kernel | 학습과 예측에 사용할 커널 함수 명시 vanilladot(Linear kernel) : 커널 트릭 없이 단순히 벡터의 내적만을 이용하는 방식 rbfdot(Radial Basis kernel “Gaussian”) : 가우시안 커널(기본 값) polydot(Polynomial kernel) : 다항 커널을 사용 tanhdot(Hyperbolic tangent kernel) 등과 같은 알고리즘 등 |
C | Cost : 과적합을 막기 위한 정도를 지칭하는 파라미터 적절한 C를 구하기 위해 tune() 함수를 사용하여 조정 |
scaled | 데이터를 정규화할 지의 여부를 결정 기본 값인 T는 평균 0, 분산 1이 되도록 데이터를 변경 이것은 표준화, z-score 정규화라고 함 |
kpar | 커널 파라미터를 list 형식으로 작성 |
predict() 함수
예측하기 위한 함수
- 사용 형식
letter_predictions <- predict(model, testing, type)
- model
ksvm()
함수를 사용하여 훈련된 모델을 의미
- testing
- 예측을 수행할 검증용(testing) 데이터 셋을 의미
- type
- 예측이 ‘response’(예측된 범주)인지, ‘probabilities’(예측된 확률)인지 명시
svm() 함수
e1071 패키지의 svm()
함수는 서포트 벡터 머신 알고리즘을 수행해준다.
- 사용 형식
svm( formula, data=NULL, scale = TRUE, type=NULL, kernel='radial', gamma, cost=1)
- formula
- 모델을 위한 포률러
- data
- 데이터
- scale
- 정규화를 수행할것지의 여부
- type
- 분류 회귀 등의 모델 중에서 만들 모델을 지정
- 다음과 같은 항목들이 존재
- C-classification, nu-classification, one-classification (for novelty detection), eps-regression, nu-regression
- kernel
- 커널 함수를 명시
- gamma
- 커널 파라미터 gamma
- cost
- 커널 파라미터 cost
tune() 함수
그리드 탐색을 사용한 파라미터 튜닝을 수행한다.
- 사용 형식
tune(method, train.x , train.y, data)
- method
- 최적화할 함수를 지정
- train.x
- 포뮬러 또는 독립 변수의 행렬을 지정
- train.y
- 예측할 분류, 만일 train.x가 포뮬러이면 무시
- data
- 포뮬러를 적용하고자 하는 데이터 셋
- gamma
- 최적화하고자 하는 gamma 값
- cost
- 최적화하고자 하는 cost 값을 의미
- cost는 과적합을 막는 정도를 지정하는 파라미터
예제
library(kernlab)
data <- read.csv('likelyhood.csv')
head(data)
str(data)
summary(data)
dim(data)
colnames(data)
idx <- sample(1:nrow(data), 0.1 * nrow(data))
training <- data[idx, ]
testing <- data[-idx, ]
model <- ksvm(likelyhood ~ ., data = training, kernel = 'rbfdot')
pred <- predict(model, testing)
table(pred, testing$likelyhood)
prop.table(table(pred == testing$likelyhood))