본문 바로가기

Previous (20-22)/Development

R Programming - (3) kNN Model

그동안 머신러닝 - R Programming 관련하여 글이 많이 없었던 것 같습니다.


여러 가지 이유가 있겠습니다만,


1. 최근에 중국출장을 갔다왔다.

2. 업무적으로도 시간적 여유가 없었다.

3. 게을렀다.


아마 이 세가지 정도로 분석되는데, 역시 아무래도 3번이 가장 큰 비중을 차지하겠지요.

좀 더 부지런해져야 할 것 같습니다.


지난번에는 Machine Learning 부분에 kNN 모델에 관한 글을 쓴 적이 있었고, 이번에는 이를 R Programming으로 구현해 본 것입니다.

물론 제가 임의대로 구현했다기 보다는, CRAN에 있는 기본 예제를 가지고 매우 간단하게 실습한 내용이고,

이 내용을 토대로 kNN 모델을 R에서 어떻게 구현하는지를 응용할 수 있겠지요.


kNN Model이 무엇인지 궁금하신 분들은 아래 글 참고하시면 좋을 것 같습니다.


2016/11/23 - [Onik Lab./MachineLearning] - Machine Learning - (2) kNN 모델



CRAN에서는 kNN Model을 위한 기본 패키지를 제공하는데,

kNN 전용 패키지는 아니고, class라는 패키지 내에 kNN 함수를 제공합니다.


class 패키지란 무엇인지부터 봐야 되겠지요?


CRAN에서는 다음과 같이 소개를 하고 있습니다.



Various functions for classification, including k-nearest neighbour, Learning Vector Quantization and Self-Organizing Maps.


분류(Classification)를 위한 여러 가지 함수 및 k-nearest neighbour(kNN) 모델을 포함한 여러 함수를 제공한다 하였습니다.

그래서 내장된 함수도 knn, knn.cv, knn1 이렇게 3가지 함수를 제공하고 있고요.

class Package 외에도 kNN Model의 여러 변형 패키지도 CRAN에서는 제공하고 있습니다.



ESKNN: Ensemble of Subset of K-Nearest Neighbours Classifiers for Classification and Class Membership Probability Estimation


FastKNN: Fast k-Nearest Neighbors


FNN: Fast Nearest Neighbor Search Algorithms and Applications


KernelKNN: Kernel k Nearest Neighbors


kknn: Weighted k-Nearest Neighbors


knncat: Nearest-neighbor Classification with Categorical Variables


knnGarden: Multi-distance based k-Nearest Neighbors


knnIndep: Independence tests and benchmarks


nabor: Wraps 'libnabo', a Fast K Nearest Neighbour Library for Low Dimensions


bnnSurvival: Bagged k-Nearest Neighbors Survival Prediction




뭐.. 많습니다.

하지만 이 많은 패키지를 당연히 다 다룰 리는 없고요 (사실 저도 잘 모릅니다)


1. kNN에 대한 기본 패키지 및 함수를 통해서 어떤 식으로 R에서 구현되는지를 알고

2. 필요시 이를 응용을 할 수 있을 정도로 충분한 학습을 한 다음에

3. 다양한 kNN 패키지 및 함수를 사용할 수 있어야 한다


정도가 순서가 될 것 같습니다.


하지만 저는 kNN에 대한 기본 실습정도까지만 하겠습니다.

Machine Learning의 영역은 매우 넓기 때문에 다른 모델에 대한 이해도 당연히 필요하거든요.




그럼 kNN Model에 대한 실습 들어가겠습니다.



1
2
3
4
5
train <- rbind(iris3[1:25,,1], iris3[1:25,,2], iris3[1:25,,3])
test <- rbind(iris3[26:50,,1], iris3[26:50,,2], iris3[26:50,,3])
cl <- factor(c(rep("s",25), rep("c",25), rep("v",25)))
knn(train, test, cl, k = 3, prob=TRUE)
attributes(.Last.value)
cs



실습 코드입니다.

이 소스코드는 CRAN에서 kNN 함수 소개할 때 공식적으로 나와있는 예제 코드이고요.

이 코드에 대한 이해만 어느 정도 되더라도 kNN을 R에서 쉽게 구현할 수 있습니다.


그럼 하나씩 보도록 하겠습니다.



1. iris3 데이터 (3차원 배열 형태)


여기 실습으로 사용되는 내장 데이터인 iris3 데이터가 어떤 구조로 있는지부터 이해를 해야 합니다.

이 데이터 구조를 파악하지 못하면 kNN 실습 자체를 전혀 이해할 수 없기 때문입니다.



iris3 데이터는 다음과 같이 값이 구성되어 있습니다.


, , Setosa


      Sepal L. Sepal W. Petal L. Petal W.

 [1,]      5.1      3.5      1.4      0.2

 [2,]      4.9      3.0      1.4      0.2

 [3,]      4.7      3.2      1.3      0.2

...

[48,]      4.6      3.2      1.4      0.2

[49,]      5.3      3.7      1.5      0.2

[50,]      5.0      3.3      1.4      0.2


, , Versicolor


      Sepal L. Sepal W. Petal L. Petal W.

 [1,]      7.0      3.2      4.7      1.4

 [2,]      6.4      3.2      4.5      1.5

 [3,]      6.9      3.1      4.9      1.5

...

[48,]      6.2      2.9      4.3      1.3

[49,]      5.1      2.5      3.0      1.1

[50,]      5.7      2.8      4.1      1.3


, , Virginica


      Sepal L. Sepal W. Petal L. Petal W.

 [1,]      6.3      3.3      6.0      2.5

 [2,]      5.8      2.7      5.1      1.9

 [3,]      7.1      3.0      5.9      2.1

...

[48,]      6.5      3.0      5.2      2.0

[49,]      6.2      3.4      5.4      2.3

[50,]      5.9      3.0      5.1      1.8 



1
2
> dim(iris3)
[150  4  3
cs



배열은 위와 같이 50행 4열 3개체의 3차원 배열이며, 3개체는 Setosa, Versicolor, Virginica입니다.


그럼 이해가 쉽도록 명칭과 데이터값을 설명하겠습니다.


배열명: iris3  - 아이리스 꽃(붓꽃)

Column명: Sepal Length - Width(꽃받침 길이-너비), Petal Length - Width(꽃잎 길이-너비)

3차원배열명: Setosa, Versicolor, Virginica (아이리스꽃 품명)


즉 품명별로 50개씩 꽃받침 및 꽃잎의 사이즈를 가지고 있다고 보시면 됩니다.

그렇기 때문에 꽃은 총 150송이로 보시면 됩니다.


출처: kr.best-wallpaper.net





이제 R 코드의 1행부터 보겠습니다.


train <- rbind(iris3[1:25,,1], iris3[1:25,,2], iris3[1:25,,3])


rbind는 배열의 여러 값을 묶어서 Dataset으로 만드는 작업입니다.

train 데이터에 들어가는 값은


Setosa(이하 "ST")에 1~25번째 꽃

Versicolor(이하 "VC")에 1~25번째 꽃

Virginica(이하 "VG")에 1~25번째 꽃입니다.


train 데이터는 학습된 데이터로, 각 품종별 1~25번째 꽃, 총 75송이의 꽃을 학습된 데이터로 하는 것입니다.





다음은 2행입니다.


test <- rbind(iris3[26:50,,1], iris3[26:50,,2], iris3[26:50,,3])


train과 마찬가지로 rbind로 묶어줍니다.

다만 test 데이터에 들어가는 꽃은 품종별 26~50번째 꽃으로 보시면 됩니다.


test 데이터는 새로운 데이터로, 기존 학습된 데이터 분포를 토대로 어느 그룹에 들어가는지를 결정하는 것으로 보면 됩니다.





3행 보도록 할게요.


cl <- factor(c(rep("s",25), rep("c",25), rep("v",25)))


factor 함수는 범주형 카테고리를 나타내는 함수이며, rep 함수로 s,c,v 값을 25번씩 반복합니다.


1
2
3
4
5
> cl
 [1] s s s s s s s s s s s s s s s s s s s s s s s s s c c c c
[30] c c c c c c c c c c c c c c c c c c c c c v v v v v v v v
[59] v v v v v v v v v v v v v v v v v
Levels: c s v
cs


이 부분이 무엇을 의미하는지 사실 처음에는 잘 이해가 되지 않았습니다.

그래서 knn 관련하여 영문자료를 뒤지고 뒤지다보니 나온 내용은 다음과 같습니다.


"Test Set에 대한 분류(Classification) 결과에 대한 기대값"


위 2행에서도 보셨듯이 Test 데이터의 값은 ST, VC, VG의 26~50번째 꽃이 그 값입니다.

이는 즉, Test 데이터를 가지고 kNN을 실행했을 때 기대하는 분류를 "s","c","v"로 잡은 것이죠.


위 Factor에서도 보다시피 1~25번째 값은 "s", 26~50번째 값은 "c", 51~75번째 값은 "v"로 구성되어있습니다.

즉 knn분류 시 ST의 꽃은 "s"로 기대하고, VC의 꽃은 "c"로 기대하고, VG의 꽃은 "v"로 기대하는 것이죠.


물론 knn을 실행했을 때 기대값처럼 나오는 것은 아닙니다. 

기대값은 사람이 설정해 놓은 값인 반면, knn 분류값은 알고리즘에 의해서 실행된 결과값이기 때문입니다.


그래서 기대값과 결과값의 차이를 확인하면서 어떻게 분류하는 것이 옳은것인가를 검증하는 것이 

knn을 사용하는 이유이자 머신러닝의 하나의 분류 모델이 되는 것입니다.





이제 제일 중요한 4행입니다. knn함수를 실제로 사용하는 부분이기 때문입니다.


knn(train, test, cl, k = 3, prob=TRUE)


knn 함수의

첫번째 인자는 학습된 데이터

두번째 인자는 새로운 테스트데이터

세번째 인자는 기대값을 나타내는 Factor

네번째 인자는 k값

다섯번째 인자는 테스트 데이터 별 분류 형성 비율 표시여부 입니다.




다섯번째 인자 부분이 잘 이해가 안되시죠?

그래서 전에 제가 썼던 글의 일부분을 예제로 보면서 설명하겠습니다.



출처: ResearchGate.net



빨간색과 녹색은 학습된 데이터이며, 빨간색 분류와 녹색 분류로 나눠져 있습니다.

k=1로 할 경우, 파란색은 빨간색 분류로 들어갑니다.

k=3으로 할 경우, 파란색은 역시 빨간색 분류로 들어갑니다.

k=5로 할 경우, 파란색은 녹색 분류로 들어갑니다.



이를 다시 풀어서 쓰면,

k=1 : 인접 학습값이 빨간색 1개입니다. 100%의 확률을 가진 빨간색 분류로 편입됩니다.

k=3 : 인접 학습값이 빨간색 2개, 녹색 1개 입니다. 66.7%의 확률을 가진 빨간색 분류로 편입됩니다.

k=5 : 인접 학습값이 녹색 3개, 빨간색 2개입니다. 60%의 확률을 가진 녹색 분류로 편입됩니다.


다섯번째 인자인 prob는 TRUE와 FALSE로 있으며,

FALSE일 경우 아무런 값도 나타나지 않습니다.


그러나 TRUE로 할 경우에는 상기 언급된 상위 확률 분류의 퍼센트를 모두 표시합니다.




knn(train, test, cl, k = 3, prob=TRUE)


를 실행했을 때 결과는 다음과 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> knn(train,test,cl,k=3,prob=TRUE)
 [1] s s s s s s s s s s s s s s s s s s s s s s s s s c c v c
[30] c c c c v c c c c c c c c c c c c c c c c v c c v v v v v
[59] c v v v v c v v v v v v v v v v v
attr(,"prob")
 [11.0000000 1.0000000 1.0000000 1.0000000 1.0000000
 [61.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[111.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[161.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[211.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[261.0000000 1.0000000 0.6666667 1.0000000 1.0000000
[311.0000000 1.0000000 1.0000000 0.6666667 1.0000000
[361.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[411.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[461.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[511.0000000 0.6666667 0.7500000 1.0000000 1.0000000
[561.0000000 1.0000000 1.0000000 0.5000000 1.0000000
[611.0000000 1.0000000 1.0000000 0.6666667 1.0000000
[661.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[711.0000000 0.6666667 1.0000000 1.0000000 0.6666667
Levels: c s v
cs


75개의 테스트 데이터에 대한 분류 결과를 표시해줍니다.

Factor에서는 1~25번째 값은 s, 26~50번째 값은 c, 51~75번째 값은 v인 반면,

knn 분류에서는 28,34번째 값이 v로 나오고, 52,53,59,64번째 값이 c로 나옵니다.


그리고 prob를 TRUE로 하였기 때문에 가장 높은 비율의 분류에 대한 퍼센테이지도 출력이 됩니다.

(FALSE일 경우 attr(,"prob") 하단 부분은 전부 출력되지 않습니다)


신규 편입 값

28,34번째 - 66.7%로 v 분류 편입

52,64번째 - 66.,7%로 c 분류 편입

53번째 - 75%로 c 분류 편입

59번째 - 50%로 c 분류 편입


기존 기대값 중 100%가 아닌 값

72,75번째 - 66.7%로 원래 기대값인 v 분류 유지





마지막 5행입니다. 이 부분은 중요도가 그리 높은 내용은 아닙니다.


attributes(.Last.value)


이것은 가장 최근에 출력한 내용을 객체 속성별로 보기 좋게 나타내는 함수입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> attributes(.Last.value)
$levels
[1"c" "s" "v"
 
$class
[1"factor"
 
$prob
 [11.0000000 1.0000000 1.0000000 1.0000000 1.0000000
 [61.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[111.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[161.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[211.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[261.0000000 1.0000000 0.6666667 1.0000000 1.0000000
[311.0000000 1.0000000 1.0000000 0.6666667 1.0000000
[361.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[411.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[461.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[511.0000000 0.6666667 0.7500000 1.0000000 1.0000000
[561.0000000 1.0000000 1.0000000 0.5000000 1.0000000
[611.0000000 1.0000000 1.0000000 0.6666667 1.0000000
[661.0000000 1.0000000 1.0000000 1.0000000 1.0000000
[711.0000000 0.6666667 1.0000000 1.0000000 0.6666667
cs



여기서 특별히 설명할 부분은 없습니다.





kNN Model에 대한 R Programming 실습은 여기까지로 하겠습니다.

사실 예제 구문이여봤자 다섯 줄밖에 안되어서 굉장히 짧은 소스코드이지만,

kNN Model에 대한 이해와 이를 기반으로 설명을 하다 보니 굉장히 글이 길어진 것 같습니다.


다섯 줄밖에 되지 않는 예제 코드이지만, kNN Model을 어떻게 R로 구현했는가를 가장 잘 나타내었다 보고요.

이에 대한 이해가 이루어졌다면, 다른 kNN Model에 대해서도 응용 및 학습이 충분히 가능할 것으로 생각됩니다.


다음 머신러닝 글에서 뵙겠습니다.