We now review k-fold cross-validation.
Explain how k-fold cross-validation is implemented. Data is randomly split into k number of equal groups. One of the groups is treated as the validation set and the rest are treated as the training sets. This process is repeated k number of times with each time using a different group as the validation set. The results are averaged to provide a single estimation (MSE).
What are the advantages and disadvantages of k-fold cross- validation relative to:
glm(default ~ income + balance, family = "binomial", data = Default)
##
## Call: glm(formula = default ~ income + balance, family = "binomial",
## data = Default)
##
## Coefficients:
## (Intercept) income balance
## -1.154e+01 2.081e-05 5.647e-03
##
## Degrees of Freedom: 9999 Total (i.e. Null); 9997 Residual
## Null Deviance: 2921
## Residual Deviance: 1579 AIC: 1585
require(caTools)
## Loading required package: caTools
set.seed(42)
def <- Default
sample <- sample.split(def$default, SplitRatio = 0.50)
trainset <- subset(def, sample==TRUE)
testset <- subset(def, sample==FALSE)
testdef <- testset$default
logmodel = glm(default ~ income+balance, data=trainset, family=binomial)
logprob = predict(logmodel, testset, type="response")
logpreds = rep("No", length(testset$default))
logpreds[logprob>0.5] = "Yes"
table(logpreds, testdef)
## testdef
## logpreds No Yes
## No 4812 112
## Yes 21 55
round(mean(logpreds!=testset$default),4)
## [1] 0.0266
Validation error 0.0266.
set.seed(42)
def <- Default
sample <- sample.split(def$default, SplitRatio = 0.60)
trainset <- subset(def, sample==TRUE)
testset <- subset(def, sample==FALSE)
testdef <- testset$default
logmodel = glm(default ~ income+balance, data=trainset, family=binomial)
logprob = predict(logmodel, testset, type="response")
logpreds = rep("No", length(testset$default))
logpreds[logprob>0.5] = "Yes"
table(logpreds, testdef)
## testdef
## logpreds No Yes
## No 3852 88
## Yes 15 45
round(mean(logpreds!=testset$default),4)
## [1] 0.0257
60:40 split has validation error of 0.0257.
set.seed(42)
def <- Default
sample <- sample.split(def$default, SplitRatio = 0.70)
trainset <- subset(def, sample==TRUE)
testset <- subset(def, sample==FALSE)
testdef <- testset$default
logmodel = glm(default ~ income+balance, data=trainset, family=binomial)
logprob = predict(logmodel, testset, type="response")
logpreds = rep("No", length(testset$default))
logpreds[logprob>0.5] = "Yes"
table(logpreds, testdef)
## testdef
## logpreds No Yes
## No 2886 69
## Yes 14 31
round(mean(logpreds!=testset$default),4)
## [1] 0.0277
70:30 split has validation error of 0.0277.
set.seed(42)
def <- Default
sample <- sample.split(def$default, SplitRatio = 0.80)
trainset <- subset(def, sample==TRUE)
testset <- subset(def, sample==FALSE)
testdef <- testset$default
logmodel = glm(default ~ income+balance, data=trainset, family=binomial)
logprob = predict(logmodel, testset, type="response")
logpreds = rep("No", length(testset$default))
logpreds[logprob>0.5] = "Yes"
table(logpreds, testdef)
## testdef
## logpreds No Yes
## No 1922 44
## Yes 11 23
round(mean(logpreds!=testset$default),4)
## [1] 0.0275
80:20 split has validation error of 0.0275.
require(caTools)
set.seed(42)
def <- Default
sample <- sample.split(def$default, SplitRatio = 0.50)
trainset <- subset(def, sample==TRUE)
testset <- subset(def, sample==FALSE)
testdef <- testset$default
logmodel = glm(default ~ income+balance+student, data=trainset, family=binomial)
logprob = predict(logmodel, testset, type="response")
logpreds = rep("No", length(testset$default))
logpreds[logprob>0.5] = "Yes"
table(logpreds, testdef)
## testdef
## logpreds No Yes
## No 4809 114
## Yes 24 53
round(mean(logpreds!=testset$default),4)
## [1] 0.0276
Including the dummy variable “student” does not lead to reduction in the test error rate.
We continue to consider the use of a logistic regression model to predict the probability of default using income and balance on the Default data set. In particular, we will now compute estimates for the standard errors of the income and balance logistic regression coefficients in two different ways: (1) using the bootstrap, and (2) using the standard formula for computing the standard errors in the glm() function. Do not forget to set a random seed before beginning your analysis.
set.seed(42)
defmod<-glm(default ~ income+balance, family = binomial, data=Default)
summary(defmod)
##
## Call:
## glm(formula = default ~ income + balance, family = binomial,
## data = Default)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.154e+01 4.348e-01 -26.545 < 2e-16 ***
## income 2.081e-05 4.985e-06 4.174 2.99e-05 ***
## balance 5.647e-03 2.274e-04 24.836 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2920.6 on 9999 degrees of freedom
## Residual deviance: 1579.0 on 9997 degrees of freedom
## AIC: 1585
##
## Number of Fisher Scoring iterations: 8
Std. errors are in above table.
boot.fn = function(data, index)
{
logmod = glm(default ~ income+balance, data=data, family="binomial", subset=index)
return(coef(logmod))
}
library(boot)
boot(Default, boot.fn, 100)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = Default, statistic = boot.fn, R = 100)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* -1.154047e+01 8.325503e-04 4.106915e-01
## t2* 2.080898e-05 -3.709342e-07 5.320364e-06
## t3* 5.647103e-03 6.482769e-06 2.003151e-04
We will now consider the Boston housing data set, from the ISLR2 library.
attach(Boston)
mu = mean(medv)
mu
## [1] 22.53281
se = sd(medv)/sqrt(nrow(Boston))
se
## [1] 0.4088611
Estimate of standard error is 0.4089. Sample standard error shows how much the value of the statistic is expected to vary from sample to sample.
set.seed(42)
boot.fn = function(data,index)
{
mu = mean(data[index])
return(mu)
}
boot(medv, boot.fn, 100)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = medv, statistic = boot.fn, R = 100)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* 22.53281 0.01197233 0.3804984
Std. error from bootstapping is pretty closed to the Std. error obtained from (b).
t.test(medv)
##
## One Sample t-test
##
## data: medv
## t = 55.111, df = 505, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## 21.72953 23.33608
## sample estimates:
## mean of x
## 22.53281
conf.mu = c(mu-2*0.3804984, mu+2*0.3804984)
conf.mu
## [1] 21.77181 23.29380
Confidence interval from bootstrapped method is also very similar to the ones obtained from t.test.
mu.med = median(medv)
mu.med
## [1] 21.2
set.seed(42)
boot.fn<-function(data,index)
{
mu.med = median(data[index])
return(mu.med)
}
boot(medv, boot.fn, 100)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = medv, statistic = boot.fn, R = 100)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* 21.2 0.009 0.3735835
Above shows the std. error of median.
mu.quant = quantile(medv, c(0.1))
mu.quant
## 10%
## 12.75
boot.fn = function(data, index)
{
mu.quant <- quantile(data[index], c(0.1))
return (mu.quant)
}
boot(medv, boot.fn, 1000)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = medv, statistic = boot.fn, R = 1000)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* 12.75 0.01845 0.5034338
Bootstrapped method has lower std. error than 10th percentile. This means population is being represented more accurately.