이번에 알아볼 machine learning 알고리즘은 K-nearest Neighbors라고 불리는 알고리즘입니다. 컨셉은 간단합니다. 새로운 데이터가 들어왔을 때, 기존에 우리가 가지고 있던 데이터를 기준으로 $K$개의 가장 가까운 점을 찾아서 그들의 평균값(regression의 경우)이나 majority votes(가장 빈번한 class로 분류하는 것. classification의 경우)로 새로운 데이터를 분류하는 방식입니다. 이름 그대로 $K$개의 가장 가까운 이웃인 것이죠 ^^
이 방법은 컨셉이 간단하고, 특별한 수학적인 모델이 없습니다. 따라서 해석이 거의 불가능하다는 단점은 있지만, 말 그대로 간단하고, 또한 굉장히 비선형적인 움직임이 강했을 때에 오히려 linear model보다 더 잘 데이터를 예측할 수 있기도 합니다.
이제 어떻게 동작하는지 원리를 파악해 봅시다. Logistic regression 시간에 사용했던 주식 시장 데이터를 다시 사용하겠습니다. 그리고 KNN을 사용하기 위해 class
라이브러리를 추가로 불러줍니다. 여기서는 시각화를 위해서 Lag1
과 Lag2
의 두 가지 변수만 사용하겠습니다.
library(ISLR)
library(class)
attach(Smarket) #Smarket dataset을 사용할 것입니다.
## The following objects are masked from Smarket (pos = 4):
##
## Direction, Lag1, Lag2, Lag3, Lag4, Lag5, Today, Volume, Year
##
## The following objects are masked from Smarket (pos = 7):
##
## Direction, Lag1, Lag2, Lag3, Lag4, Lag5, Today, Volume, Year
##
## The following objects are masked from Smarket (pos = 9):
##
## Direction, Lag1, Lag2, Lag3, Lag4, Lag5, Today, Volume, Year
Xlag=cbind(Lag1,Lag2) #두 변수만 사용하여 새로운 x 데이터를 추출합니다.
train=Year<2005 #training set은 2005년 이전 데이터로 하겠습니다.
plot(Xlag[train,], col=Direction[train]) #일단 데이터가 어떻게 분포되어 있는지 확인해 보겠습니다.
역시 주식시장의 복잡성을 알 수 있듯이, 데이터가 굉장히 불규칙한 랜덤 형태를 보이네요. 그럼 이제 $K=1$인 1-NN model을 만들어 보겠습니다. 먼저 어느 영역에서 어떻게 분류가 되는지 눈으로 쉽게 보기 위해서 각 x축들의 최소 최대값들을 grid로 잘게 나눠서 확인해 보겠습니다.
grid = expand.grid(seq(min(Lag1[train]),max(Lag1[train]), by=0.1), seq(min(Lag2[train]), max(Lag2[train]), by=0.1)) #각 축의 최소 최대값을 0.1단위로 쪼개서 grid를 만듭니다.
grid.pred = knn(Xlag[train,], grid, Direction[train], k=1) #1-NN model을 만듭니다.
plot(grid, col=grid.pred, pch=20) #예측이 어떻게 되는지 영역 표시를 합니다.
예상대로 굉장히 불규칙하고 랜덤한 형태의 decision boundary가 형성이 되네요. 결국 데이터를 분류하는 데에 일정한 규칙이 없다는 얘기겠죠? 그럼 $K=5$으로 5-NN model을 만들어 보면 어떨까요?
grid.pred = knn(Xlag[train,], grid, Direction[train], k=5) #5-NN model을 만듭니다.
plot(grid, col=grid.pred, pch=20) #예측이 어떻게 되는지 영역 표시를 합니다.
여전히 굉장히 불안정하고 불규칙적인 영역이 나오죠? 그래도 이런 엄청나게 혼재되고 섞여 있는 데이터가 아니라면, 일반적으로 K의 값이 커질수록 더 완만한 모습의 decision boundary를 얻으실 수 있습니다. 그 이유는 많은 점을 포함할수록 평균을 냈을 때나 다수결로 했을 때 더 consistent한 결과를 가져오기 때문입니다.
그럼 이제 모델을 만들었으니 얼마나 잘 예측하는지 확인해 봅시다.
#1-NN모델의 성능과
knn.pred=knn(Xlag[train,],Xlag[!train,],Direction[train],k=1)
table(knn.pred,Direction[!train])
##
## knn.pred Down Up
## Down 43 58
## Up 68 83
mean(knn.pred==Direction[!train])
## [1] 0.5
#5-NN모델의 성능을 각각 확인합니다.
knn.pred=knn(Xlag[train,],Xlag[!train,],Direction[train],k=5)
table(knn.pred,Direction[!train])
##
## knn.pred Down Up
## Down 40 59
## Up 71 82
mean(knn.pred==Direction[!train])
## [1] 0.484127
둘 다 만족할만한 성능이 아니네요 ㅠㅠ 특히나 1-NN의 성능이 5-NN의 성능보다 나은걸 보니 data가 매우 복잡한 decision boundary를 가질 것이라는 예측을 해 봅니다. 하지만 비록 좋은 성능은 얻지 못했지만, KNN이 어떻게 동작하는지 살펴볼 수 있는 좋은 기회였습니다 ^^