0. 데이터 탐색

library(ISLR)
head(Default)
str(Default)
## 'data.frame':    10000 obs. of  4 variables:
##  $ default: Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ student: Factor w/ 2 levels "No","Yes": 1 2 1 1 1 2 1 2 1 1 ...
##  $ balance: num  730 817 1074 529 786 ...
##  $ income : num  44362 12106 31767 35704 38463 ...
dim(Default)
## [1] 10000     4
sum(is.na(Default))
## [1] 0

데이터 구조를 확인하였다. 총 변수 4개이고 각 변수당 10000개 관측치를 가진다. 변수 이름은 각각 default, student, balance, income으로 되어있고, 결측값은 존재하지 않았다. Predictor로 사용할 변수가 student, balance, income이고 response variable로 default를 사용한다. 여기서 중요한 것은 predictor 중에서 student(이산형, discrete variable)이고 나머지 balance, income(연속형, continuous variable)이 섞여있다는 점이다.

문제

1. Construct a Bayes’ classifier to predict “default” using “balance” and “income” variables. Estimate the test error rate using (1) VS approach, (2) LOOCV, and (3) 10-fold CV.

n=dim(Default)[1]
set.seed(20144607)
train<-sample(1:n,n/2)
default.train<-Default[train,]
default.test<-Default[-train,]
# VS approach
library(MASS)
nl<-nlevels(default.train[,1])

mu<-list()
S<-list()
pro<-list()
for (i in 1:nl){
    mu[[i]]<-apply(default.train[default.train$default==levels(default.train[,1])[i],3:4],2,mean)
    S[[i]]<-cov(default.train[default.train$default==levels(default.train[,1])[i],3:4])
    pro[[i]]<-dim(default.train[default.train$default==levels(default.train[,1])[i],3:4])[1]/dim(default.train[,3:4])[1]
}

dmvnorm<-function(x,mu,sigma){
    p<-length(mu)
    mu<-c(mu)
    x<-c(x)
    f=1/(2*pi)^(p/2)/(det(sigma))^(1/2)*exp(-0.5*t(x-mu)%*%solve(sigma)%*%(x-mu))
    return(f)
}

PP<-function(x,pro,mu,sigma){
    K<-length(pro)
    PP<-numeric(K)
    for (i in 1:K){
        PP[i]<-pro[[i]]*dmvnorm(x,mu[[i]],sigma[[i]])
    }
    PP<-PP/sum(PP)
    return(PP)
}

Y.pred<-numeric(dim(default.test)[1])
Pprob<-matrix(0,ncol=2,nrow=length(Y.pred))
for (i in 1:dim(default.test)[1]){
    Pprob[i,]<-PP(unlist(default.test[i,3:4]),pro,mu,S)
    Y.pred[i]<-which.max(Pprob[i,])
    }

Y.hat<-character(length(Y.pred))
Y.hat[Y.pred==1]<-"No"
Y.hat[Y.pred==2]<-"Yes"

table(pred=Y.hat,true=default.test[,1])
##      true
## pred    No  Yes
##   No  4814  130
##   Yes   12   44
sum(default.test[,1]!=Y.hat)
## [1] 142
sum(default.test[,1]!=Y.hat)/length(Y.hat)
## [1] 0.0284

Bayes classifier는 predictor로 이산형, 연속형 변수를 섞어서 예측할 수가 없다. 문제에서도 나와있듯이 연속형 변수인 balance, income만을 predictor로 사용하였다. Bayes classifier를 코드로 작성하고, 이를 바탕으로 Validation set approach로 error rate를 구하였다. MSE는 0.0284로 우수한 분류 성능을 보여주었다.

#LOOCV
default1 <- Default[,c(1,3,4)]
fitloocv<-lda(default~.,data=default1,cv=T)
predloocv<-predict(fitloocv,default1)$class
table(predloocv,default1[,1])
##          
## predloocv   No  Yes
##       No  9647  256
##       Yes   20   77
mean(predloocv!=default1[,1])
## [1] 0.0276
#10-fold CV
K<-10
ind<-(1:n)%%K+1
set.seed(20144607)
folds<-sample(ind,n)
kfoldcv<-character(n)
for (k in 1:K){
    fit<-lda(default~.,data=default1,subset=which(ind!=k))
    kfoldcv[ind==k]<-as.character(predict(fit,default1[ind==k,])$class)
}
table(kfoldcv,default1[,1])
##        
## kfoldcv   No  Yes
##     No  9647  255
##     Yes   20   78
mean(kfoldcv!=default1[,1])
## [1] 0.0275

LOOCV, 10-fold CV로도 error rate를 구하였는데, 이 때에는 lda를 활용하였다. 에러 비율이 0.3 미만으로 우수한 분류 performance를 보여주었다. qda도 활용하였으나 lda와 error rate가 그렇게 큰 차이가 나지 않았다.(0.01미만) 따라서, covariance matrix가 다르며 많은 변수가 필요하여 복잡한 모델이 되는 qda를 쓰지 않기로 했다. Law of parsimony에 따라 lda만을 사용하였다. 정리하면, Bayes classifier의 MSE는 0.0284, 0.0276, 0.0275로 우수하다.

문제

2. Construct a naive Bayes’s classifier to predict “default” using “student”, “balance”, and “income” variables. Estimate the test error rate using (1) VS approach, (2) LOOCV, and (3) 10-fold CV

#VS approach
library(e1071)
fit<-naiveBayes(default~.,data=default.train)
pred.default<-predict(fit,default.test)
table(pred=pred.default,true=default.test[,1])
##      true
## pred    No  Yes
##   No  4802  124
##   Yes   24   50
mean(pred.default!=default.test[,1])
## [1] 0.0296
#LOOCV
fitloocv<-naiveBayes(default~.,data=Default,cv=T)
fitloocv
## 
## Naive Bayes Classifier for Discrete Predictors
## 
## Call:
## naiveBayes.default(x = X, y = Y, laplace = laplace, cv = ..1)
## 
## A-priori probabilities:
## Y
##     No    Yes 
## 0.9667 0.0333 
## 
## Conditional probabilities:
##      student
## Y            No       Yes
##   No  0.7085963 0.2914037
##   Yes 0.6186186 0.3813814
## 
##      balance
## Y          [,1]     [,2]
##   No   803.9438 456.4762
##   Yes 1747.8217 341.2668
## 
##      income
## Y         [,1]     [,2]
##   No  33566.17 13318.25
##   Yes 32089.15 13804.22
predloocv<-predict(fitloocv,Default)
table(predloocv,Default[,1])
##          
## predloocv   No  Yes
##       No  9615  241
##       Yes   52   92
mean(predloocv!=Default[,1])
## [1] 0.0293
#10-fold CV
K<-10
ind<-(1:n)%%K+1
set.seed(20144607)
folds<-sample(ind,n)
predcv<-character(n)
for (k in 1:K){
    fit<-naiveBayes(default~.,data=Default,subset=which(ind!=k))
    predcv[ind==k]<-as.character(predict(fit,Default[ind==k,]))
}
table(predcv,Default[,1])
##       
## predcv   No  Yes
##    No  9615  244
##    Yes   52   89
mean(predcv!=Default[,1])
## [1] 0.0296

이번에는 이산형과 연속형 변수가 섞인 상태에서도 활용이 가능한 naive bayes를 적용하였다. discrete 변수인 student와 continuous predictor인 balance, income을 섞어서 분류 예측을 진행하였다. 세가지 MSE는 각각 0.0296, 0.0293, 0.0296으로 모두 비슷한 error rate를 보여주었다.

(1)과 (2)에서 각각 classifier의 error rate를 비교해보면, 아주 약간이나마 Bayes classifier가 높은 분류 예측 성능을 보여준다. 아무래도 naiveBayes에서 이산형 변수(student)가 섞이면서 약하게나마 과대적합이 발생했을 것이라고 추측하고 있다. 물론 naiveBayes 모델은 이산형과 연속형 변수 모두를 예측변수(predictor)로 사용할 수 있다는 점이 우수하므로 이산형 변수가 예측 변수로 사용해야하는 경우에는 유용할 것이다.