반응형

k-nn을 german credit data 에 적용하고 다음과 같은 내용을 수행해본다.


1. 여러 가지 k 값에 대하여 실험 적으로 분류를 실행하고 accuracy 가 최대가 되는 k 값을 선택한다. 

2. cross validation을 이용하고 cross validation의 결과를 평균한다.

3. 막대 그래프를 그려서 시각화 시킨다.

German Credit Data의 RESPONSE를 factor로 변경하여 RESPONSE에 대한 k-nn을 구하고자 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rm(list=ls())
library('caret')
df <- read.csv('C:/Users/kkw56/Documents/R/GermanCredit.csv', header = TRUE, stringsAsFactors = FALSE, na.strings="")
tmp <- factor()
for(i in 1:length(df$RESPONSE)){
    if(df$RESPONSE[i] == 1){
        tmp <- c(tmp, "YES")
    }
    else{
        tmp <- c(tmp, "NO")
    }
}
df$RESPONSE <- as.factor(tmp)
 
head(df)
cs



5개의 집단으로 나누고(createFolds 이용) 그리고 k는 1~31의 값을 이용한다.(홀수만)


1
2
3
4
5
6
7
8
9
10
 
k.fold <- 5
folds <- createFolds(df$RESPONSE, k = k.fold)
folds
 
kk.seq = seq(131, by = 2)
 
names(kk.seq) <- sapply(kk.seq, function(kk){
    paste("k = ", kk)
})
cs





xval.result에 5번의 cross validation한 값의 정확도가 저장되고 

kk.Result에는 1~31개의 k값을 이용하여 k에 대한 평균 값들이 저장된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kk.result <- sapply(kk.seq, function(kk){
    xval.result <- sapply(folds, function(idx){
        df.train.i <- df[-idx, ]
        df.test.i <- df[idx, ]
        model.i <- knn3(RESPONSE ~., data = df.train.i, k = kk)
        predict.i <- predict(model.i, df.test.i, type ="class")
        accuracy.i <- sum(predict.i == df.test.i$RESPONSE) / length(predict.i)
        return(accuracy.i)
    })
    print(xval.result)
    return(mean(xval.result))
})
 
print(kk.result)
 
cs




이때 위의 Fold1 ~ Fold5가 여러번 나오는 것의 의미는

 k = 1일때 Fold의 5번의 Cross Validation 값, 

k = 3일때 Fold의 5번의 Cross Validation 값, 

... k = 31일때 Fold의 5번의 Cross Validation 값이다.




K에 대한 값을 그래프로 나타내고 최적의 k는 27임을 파악 할 수 있다.


1
2
3
4
5
6
 
plot.data = data.frame(k = kk.seq, Accuracy = kk.result)
plot(formula = Accuracy ~ k, data = plot.data, type="o", pch = 20, main  = "validation - optimal k")
 
with(plot.data, text(Accuracy ~ k, labels = plot.data$k, pos = 1, cex = 0.7))
min(plot.data[plot.data$Accuracy %in% max(plot.data$Accuracy), "k"])
cs





이 과정에서 k 는 무조건 27이 최적이 아닐 수 있다.


createFold에 의해 집단이 나눠지고, training set, test set이 달라질 때 마다 최적의 k 값이 변경될 수 있음을 유의하자.






전체 코드는 다음과 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
rm(list=ls())
library('caret')
df <- read.csv('C:/Users/kkw56/Documents/R/GermanCredit.csv', header = TRUE, stringsAsFactors = FALSE, na.strings="")
tmp <- factor()
for(i in 1:length(df$RESPONSE)){
    if(df$RESPONSE[i] == 1){
        tmp <- c(tmp, "YES")
    }
    else{
        tmp <- c(tmp, "NO")
    }
}
df$RESPONSE <- as.factor(tmp)
 
head(df)
 
k.fold <- 5
folds <- createFolds(df$RESPONSE, k = k.fold)
folds
 
kk.seq = seq(131, by = 2)
 
names(kk.seq) <- sapply(kk.seq, function(kk){
    paste("k = ", kk)
})
 
kk.result <- sapply(kk.seq, function(kk){
    xval.result <- sapply(folds, function(idx){
        df.train.i <- df[-idx, ]
        df.test.i <- df[idx, ]
        model.i <- knn3(RESPONSE ~., data = df.train.i, k = kk)
        predict.i <- predict(model.i, df.test.i, type ="class")
        accuracy.i <- sum(predict.i == df.test.i$RESPONSE) / length(predict.i)
        return(accuracy.i)
    })
    print(xval.result)
    return(mean(xval.result))
})
 
print(kk.result)
 
plot.data = data.frame(k = kk.seq, Accuracy = kk.result)
plot(formula = Accuracy ~ k, data = plot.data, type="o", pch = 20, main  = "validation - optimal k")
 
with(plot.data, text(Accuracy ~ k, labels = plot.data$k, pos = 1, cex = 0.7))
min(plot.data[plot.data$Accuracy %in% max(plot.data$Accuracy), "k"])
cs

반응형