오늘은 KNN에 대해 알아보도록 하겠습니다.
코드는 맨 마지막에 있습니다.
이론
KNN은 K-Nearest Neighborhood의 약자로, 우리말로 최근접이웃이라고 합니다.
knn 알고리즘은 이름에 그 뜻이 다 담겨 있습니다.
말그대로, k개의 이웃을 통해, 새로 들어온 데이터에 대한 라벨을 정하겠다는 뜻입니다.
예를들어, 아래와 같은 상황이 되었다고 가정해보겠습니다.
새로운 데이터(허스키)는 KNN알고리즘에 의해 어느 쪽으로 분류가 될까요??
만약, K를 1로 정했다면,(가장 가까운 이웃 1개를 보고 라벨을 결정한다면)
새로 들어온 허스키 데이터의 변수의 값과 가장 가까운 이웃 1개를 선택하게 됩니다.
그 결과 가장 가까운 라벨은 고양이네요!!
그럼, 이번에는 보는 이웃의 개수를 더 늘려볼까요?
가장 가까운 이웃의 수 3개를 보고 라벨을 정하도록 하겠습니다.
이웃의 수가 3으로 설정하면,
가장 가까운 이웃은 노랑색(강아지) 2개와 파란색(고양이)로 되어있네요.
노란색 이웃이 더 많으니 새로 들어온 허스키 데이터는 노란색(강아지)로 분류됩니다.
위에서 본 예시와 같이, KNN은 이웃의 수 K를 잘 정해주는 것이 좋습니다.
만약 K의 수가 1이라면, 새로 들어온 데이터는 가장 가까운 훈련 데이터의 값을 따를 것 입니다.
만약 K가 1000000이라면, 새로 들어온 데이터는 훈련데이터의 1000000개를 살펴보고 라벨을 정할 것 입니다.
K가 1이라면, 가장 가까운 이웃 1개만 보기 때문에 매우 비선형적인 결정경계가 생길 것 입니다.
이는 오버피팅 할 가능성이 높아지겠죠.
반면, K가 무수히 큰 수라면, 아주 많은 데이터를 보기 때문에 매우 선형적인 결정경계가 생길 것 입니다.
하지만, 데이터를 잘 맞추지 못하겠죠.
따라서, 적절한 이웃의 수 K를 정하는 것이 매우 중요합니다.
이K의 값은 어떻게 정할까요?? 보통은 분석자의 주관에 따라 초기값을 지정하거나
자료의 제곱근을 취하는 경우가 있습니다. k = n^1/2
혹은 그리드 서치를 통해 k의 개수를 늘리므로써 적절한 k의 값을 찾기도 합니다.
knn의 장단점을 살펴보면 다음과 같습니다.
또한, knn은 lazy알고리즘입니다.
lazy알고리즘이란 학습 데이터를 가지고 있다가 새로운 데이터가 투입되면 해당 데이터에 대한 분류가 이뤄지는 알고리즘을 뜻합니다.
정리를 하면,
knn은 학습을 하지 않습니다.
새로운 데이터가 들어오면, 가지고 있는 데이터(훈련데이터)에서 가장 가까운 k개의 데이터를 찾고(=거리계산)
그 데이터의 라벨 값을 보고 가장 많은 라벨값을 새로운 데이터의 라벨값으로 분류해줄 뿐입니다.
따라서 학습 비용이 0이라는 장점을 가지고 있지만, 모델이 없으므로 결과에 대한 해석이 제약될 수 있습니다.
또한, 만약, 데이터가 커진다면, 데이터에대해 일일히 계산을 해야 하므로, 계산 효율성이 떨어질 수 있습니다.
그리고 차원의 저주에도 민감합니다.
만약, 데이터의 수는 적은데 차원이 크다면, 그 데이터는 매우 sparse한 데이터 입니다.(0이 많은 데이터=비어있는 데이터)
가장 가까운 이웃이 저 멀리에 있다는 뜻이므로 knn의 성능이 좋지 않게됩니다.
차원의 저주와 관련된 내용은 이전 포스팅을 참고해주세요:)
마지막으로 knn은 거리 기반 알고리즘이기 때문에 거리에 민감합니다.
따라서 꼭!!! scale을 맞춰 주는 것이 중요합니다.
knn의 keypoint를 정리하면 다음과 같습니다.
코드
이제 코드를 통해 KNN을 구현해보고 모델을 평가해보도록 하겠습니다.
#############
# # K N N # #
#############
data("iris")
str(iris)
library(caret) #R에서 데이터 분석 할 때 많이 쓰는 패키지
library(class) #KNN 패키지
#데이터 7:3으로 나누기
idx = createDataPartition(y=iris$Species, p=0.7, list = F)
train = iris[idx,]
test = iris[-idx,]
#KNN 써보자(비교를 위해 아무것도 안함), 임의로 K는 5로 지정
model.knn <- knn(train[-5],test[-5], train$Species, k=5)
confusionMatrix(model.knn, test$Species) #Accuracy : 0.9556
#######다듬고 KNN 써보자! - 거리 기반임으로 scale이 중요!
## min-max 스케일링: r에서는 따로 패키지를 제공하지 않고, 직접 함수로 만들어야 함
normalize <- function(x){
return( (x-min(x))/(max(x)-min(x)) )
}
iris_normal <- as.data.frame(lapply(iris[-5], normalize))
summary(iris_normal)
iris_normal$Species <- iris$Species
#다시 나누기
train_n = iris_normal[idx,]
test_n = iris_normal[-idx,]
#최적의 k 찾기
# ks = 실험할 k, 일부러 홀수로 지정하였다. leave one out 방법
install.packages("kknn"); library(kknn)
cv <- train.kknn(Species ~., train_n,
ks = seq(1, 50, by=2), scale = F); cv
best_k <- cv$best.parameters$k; best_k #5
pred_cv <- kknn(Species ~., train = train_n, test = test_n, k = best_k, scale = F)
pred_cv <- pred_cv$fitted.values
confusionMatrix(pred_cv, test_n$Species) #0.9556
#그리드 서치 cv
cv <- trainControl(method = "cv", number = 5, verbose = T)
knn.grid = expand.grid(
.k = c(1,3,5,7,9)
)
train.knn <- train(Species~.,train_n, method = "knn",trControl = cv,
tuneGrid = knn.grid)
train.knn$results
train.knn$bestTune #9
predict.knn <- predict(train.knn, test_n)
confusionMatrix(predict.knn, test_n$Species) #0.9778
iris데이터에 대해 knn은 약 98%의 정확성을 보이는 것을 알 수 있습니다.
'R' 카테고리의 다른 글
[딥러닝] 케라스로 해보는 딥러닝 (keras in R) (0) | 2019.06.17 |
---|---|
[R] R Studio가 갑자기 느려질 때 (0) | 2019.06.11 |
[R] 데이터 불러오기 (0) | 2019.05.29 |
[R]ggplot2에 대해 파헤쳐 보자!!(feat.실전편) (0) | 2019.05.24 |
[R]ggplot2에 대해 파헤쳐 보자!!(feat.심화편) (0) | 2019.05.23 |