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)이 섞여있다는 점이다.
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로 우수하다.
#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)로 사용할 수 있다는 점이 우수하므로 이산형 변수가 예측 변수로 사용해야하는 경우에는 유용할 것이다.