As we did in Ch2-Lab.
library(MASS) # install.packages("MASS")
head(Boston) # data is already there
dim(Boston) # (num of row, num of col)
names(Boston) # column names
?Boston # see explanation for variables
# 1 crim per capita crime rate by town.
# 2 zn proportion of residential land zoned for lots over 25,000 sq.ft.
# 3 indus proportion of non-retail business acres per town.
# 4 chas Charles River dummy variable (= 1 if tract bounds river; 0 otherwise).
# 5 nox nitrogen oxides concentration (parts per 10 million).
# 6 rm average number of rooms per dwelling.
# 7 age proportion of owner-occupied units built prior to 1940.
# 8 dis weighted mean of distances to five Boston employment centres.
# 9 rad index of accessibility to radial highways.
# 10 tax full-value property-tax rate per $10,000.
# 11 ptratio pupil-teacher ratio by town.
# 12 black 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town.
# 13 lstat lower status of the population (percent).
# 14 medv (response Y) median value of owner-occupied homes in $1000s.I’ve written a function and posed on my website. You can load the function using single line with sourse() command.
The function is called CreateCV(). The dataframe you feed into the funciton must contain the “resp” column.
# Turn Boston into Tibble
library(tidyverse) # install.packages(tidyverse")
Boston <- as_tibble(Boston)
Boston
# Rename "medv" column as "resp" and move "resp" columnm to 1st
Boston = Boston %>% rename(resp=medv) %>% relocate(resp)
Boston
# Check if there's NA in data
sum(is.na(Boston))
Boston = Boston %>% na.omit() # remove rows with NA (if applicable)
Boston# Load the file from my website
source("https://nmimoto.github.io/R/ML-00.txt") # load CreateCV()
# Use this function to create CV dataset
CreateCV(Boston, numFolds=5, seed=5480)##
## number of folds: 5
## number of obs: 506
## training data: 84 x 5 = 420
## size of test data: 86
##
## Global variables created:
## Train.set Train.resp
## Test.set Test.resp
## CV.train[[k]] CV.train.resp[[k]]
## CV.valid[[k]] CV.valid.resp[[k]]
# Output (all data.frame):
# Train.set Train.resp
# Test.set Test.resp
# CV.train[[[[k]]]] CV.train.resp[[[[k]]]]
# CV.valid[[[[k]]]] CV.valid.resp[[[[k]]]]
Train.set## # A tibble: 420 × 14
## resp crim zn indus chas nox rm age dis rad tax ptratio
## <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl>
## 1 24 0.00632 18 2.31 0 0.538 6.58 65.2 4.09 1 296 15.3
## 2 21.6 0.0273 0 7.07 0 0.469 6.42 78.9 4.97 2 242 17.8
## 3 34.7 0.0273 0 7.07 0 0.469 7.18 61.1 4.97 2 242 17.8
## 4 33.4 0.0324 0 2.18 0 0.458 7.00 45.8 6.06 3 222 18.7
## 5 28.7 0.0298 0 2.18 0 0.458 6.43 58.7 6.06 3 222 18.7
## 6 22.9 0.0883 12.5 7.87 0 0.524 6.01 66.6 5.56 5 311 15.2
## 7 27.1 0.145 12.5 7.87 0 0.524 6.17 96.1 5.95 5 311 15.2
## 8 16.5 0.211 12.5 7.87 0 0.524 5.63 100 6.08 5 311 15.2
## 9 18.9 0.170 12.5 7.87 0 0.524 6.00 85.9 6.59 5 311 15.2
## 10 21.7 0.0938 12.5 7.87 0 0.524 5.89 39 5.45 5 311 15.2
## # ℹ 410 more rows
## # ℹ 2 more variables: black <dbl>, lstat <dbl>
## # A tibble: 86 × 14
## resp crim zn indus chas nox rm age dis rad tax ptratio
## <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl>
## 1 36.2 0.0690 0 2.18 0 0.458 7.15 54.2 6.06 3 222 18.7
## 2 15 0.225 12.5 7.87 0 0.524 6.38 94.3 6.35 5 311 15.2
## 3 18.9 0.117 12.5 7.87 0 0.524 6.01 82.9 6.23 5 311 15.2
## 4 20.4 0.630 0 8.14 0 0.538 5.95 61.8 4.71 4 307 21
## 5 19.6 0.852 0 8.14 0 0.538 5.96 89.2 4.01 4 307 21
## 6 18.9 0.0642 0 5.96 0 0.499 5.93 68.2 3.36 5 279 19.2
## 7 34.9 0.0336 75 2.95 0 0.428 7.02 15.8 5.40 3 252 18.3
## 8 26.6 0.127 0 6.91 0 0.448 6.77 2.9 5.72 3 233 17.9
## 9 25.3 0.142 0 6.91 0 0.448 6.17 6.6 5.72 3 233 17.9
## 10 19.3 0.171 0 6.91 0 0.448 5.68 33.8 5.10 3 233 17.9
## # ℹ 76 more rows
## # ℹ 2 more variables: black <dbl>, lstat <dbl>
## # A tibble: 336 × 14
## resp crim zn indus chas nox rm age dis rad tax ptratio
## <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl>
## 1 24 0.00632 18 2.31 0 0.538 6.58 65.2 4.09 1 296 15.3
## 2 33.4 0.0324 0 2.18 0 0.458 7.00 45.8 6.06 3 222 18.7
## 3 28.7 0.0298 0 2.18 0 0.458 6.43 58.7 6.06 3 222 18.7
## 4 22.9 0.0883 12.5 7.87 0 0.524 6.01 66.6 5.56 5 311 15.2
## 5 27.1 0.145 12.5 7.87 0 0.524 6.17 96.1 5.95 5 311 15.2
## 6 21.7 0.0938 12.5 7.87 0 0.524 5.89 39 5.45 5 311 15.2
## 7 18.2 0.638 0 8.14 0 0.538 6.10 84.5 4.46 4 307 21
## 8 19.9 0.627 0 8.14 0 0.538 5.83 56.5 4.50 4 307 21
## 9 23.1 1.05 0 8.14 0 0.538 5.94 29.3 4.50 4 307 21
## 10 17.5 0.784 0 8.14 0 0.538 5.99 81.7 4.26 4 307 21
## # ℹ 326 more rows
## # ℹ 2 more variables: black <dbl>, lstat <dbl>
## # A tibble: 84 × 14
## resp crim zn indus chas nox rm age dis rad tax ptratio
## <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl>
## 1 21.6 0.0273 0 7.07 0 0.469 6.42 78.9 4.97 2 242 17.8
## 2 34.7 0.0273 0 7.07 0 0.469 7.18 61.1 4.97 2 242 17.8
## 3 16.5 0.211 12.5 7.87 0 0.524 5.63 100 6.08 5 311 15.2
## 4 18.9 0.170 12.5 7.87 0 0.524 6.00 85.9 6.59 5 311 15.2
## 5 13.9 0.841 0 8.14 0 0.538 5.60 85.7 4.45 4 307 21
## 6 12.7 1.13 0 8.14 0 0.538 5.71 94.1 4.23 4 307 21
## 7 13.1 1.15 0 8.14 0 0.538 5.70 95 3.79 4 307 21
## 8 21 0.0801 0 5.96 0 0.499 5.85 41.5 3.93 5 279 19.2
## 9 16.6 0.229 0 6.91 0 0.448 6.03 85.5 5.69 3 233 17.9
## 10 23.3 0.154 25 5.13 0 0.453 6.14 29.2 7.81 8 284 19.7
## # ℹ 74 more rows
## # ℹ 2 more variables: black <dbl>, lstat <dbl>
# If all data is used
deg.poly = 3
Fit00 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=Boston)
# you need raw=TRUE option, otherwise the polynomial will be transformed
summary(Fit00)##
## Call:
## lm(formula = resp ~ poly(lstat, deg.poly, raw = TRUE), data = Boston)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.5441 -3.7122 -0.5145 2.4846 26.4153
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 48.6496253 1.4347240 33.909 < 2e-16 ***
## poly(lstat, deg.poly, raw = TRUE)1 -3.8655928 0.3287861 -11.757 < 2e-16 ***
## poly(lstat, deg.poly, raw = TRUE)2 0.1487385 0.0212987 6.983 9.18e-12 ***
## poly(lstat, deg.poly, raw = TRUE)3 -0.0020039 0.0003997 -5.013 7.43e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.396 on 502 degrees of freedom
## Multiple R-squared: 0.6578, Adjusted R-squared: 0.6558
## F-statistic: 321.7 on 3 and 502 DF, p-value: < 2.2e-16
plot(Boston$lstat, Boston$resp, xlab="X", ylab="Y")
ix = sort(Boston$lstat, index.return=TRUE)$ix
lines(Boston$lstat[ix], Fit00$fitted[ix], lwd=2, col="black" )
# fold 1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
deg.poly = 3
k=5
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]] )
summary(Fit01)##
## Call:
## lm(formula = resp ~ poly(lstat, deg.poly, raw = TRUE), data = CV.train[[k]])
##
## Residuals:
## Min 1Q Median 3Q Max
## -13.0501 -3.4933 -0.4797 2.6795 22.5574
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 51.7159242 1.6942811 30.524 < 2e-16 ***
## poly(lstat, deg.poly, raw = TRUE)1 -4.4918795 0.4040236 -11.118 < 2e-16 ***
## poly(lstat, deg.poly, raw = TRUE)2 0.1847999 0.0270514 6.831 4.03e-11 ***
## poly(lstat, deg.poly, raw = TRUE)3 -0.0026298 0.0005222 -5.036 7.81e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.08 on 332 degrees of freedom
## Multiple R-squared: 0.7156, Adjusted R-squared: 0.713
## F-statistic: 278.5 on 3 and 332 DF, p-value: < 2.2e-16
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
c(MSE.train, MSE.valid)## [1] 25.49821 28.58537
# Plot the fit
plot(CV.train[[k]]$lstat, CV.train[[k]]$resp, xlab="X", ylab="Y")
lines(CV.valid[[k]]$lstat, CV.valid[[k]]$resp, col="red", type="p", pch=19)
ix = sort(CV.train[[k]]$lstat, index.return=TRUE)$ix
lines(CV.train[[k]]$lstat[ix], Fit01$fitted[ix], lwd=2, col="black" )
text(30,49, paste("d=",deg.poly,": MSE.tr=",round(MSE.train,2)))
text(30,46, paste("k=",k, ": MSE.va=",round(MSE.valid,2)), col="red")# fold 1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
deg.poly = 3
layout(matrix(1:6, 2, 3, byrow=TRUE)) # to plot 5 plots on 1 page
MSE.train <- MSE.valid <- matrix(0, 5, 1)
for (k in 1:5) {
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]])
# summary(Fit01)
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train[k,1] <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid[k,1] <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
# Plot the fit
plot(CV.train[[k]]$lstat, CV.train[[k]]$resp, xlab="X", ylab="Y")
lines(CV.valid[[k]]$lstat, CV.valid[[k]]$resp, col="red", type="p", pch=19)
ix = sort(CV.train[[k]]$lstat, index.return=TRUE)$ix
lines(CV.train[[k]]$lstat[ix], Fit01$fitted[ix], lwd=2, col="black" )
}
MSE.train## [,1]
## [1,] 25.84182
## [2,] 24.65327
## [3,] 26.71601
## [4,] 27.05489
## [5,] 25.49821
## [,1]
## [1,] 27.09155
## [2,] 32.01973
## [3,] 23.61148
## [4,] 22.12401
## [5,] 28.58537
## [1] 25.95284
## [1] 26.68643
# k=1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
MSE.train <- MSE.valid <- matrix(0, 5, 10)
for (deg.poly in 1:10) {
for (k in 1:5) {
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]])
summary(Fit01)
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train[k, deg.poly] <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid[k, deg.poly] <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
}
}
MSE.train## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 36.24899 27.08953 25.84182 24.21842 23.55096 23.43695 23.43695 23.43062
## [2,] 34.56513 26.53025 24.65327 23.08652 22.44040 22.36687 22.23037 22.20459
## [3,] 38.52559 28.92240 26.71601 24.79355 24.29306 24.06215 24.02984 24.02645
## [4,] 36.78962 28.76672 27.05489 25.50835 24.91792 24.70608 24.64202 24.60266
## [5,] 37.76581 27.44607 25.49821 23.50494 23.02862 22.86241 22.74223 22.69809
## [,9] [,10]
## [1,] 23.21270 23.11963
## [2,] 21.91391 21.91374
## [3,] 23.77189 23.70269
## [4,] 24.35297 24.35027
## [5,] 22.57818 22.54991
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 39.08241 30.64301 27.09155 24.81139 24.75677 24.44796 24.45193 24.52577
## [2,] 46.13266 33.26572 32.01973 29.49029 29.35147 28.87407 29.12594 29.55401
## [3,] 30.00595 23.35932 23.61148 22.78120 22.05074 22.35141 22.16244 22.14949
## [4,] 36.99215 24.09156 22.12401 19.49744 18.99647 19.12167 19.06789 19.33934
## [5,] 33.47810 29.78657 28.58537 27.88259 26.87975 26.76655 26.98511 27.27634
## [,9] [,10]
## [1,] 24.36412 24.63450
## [2,] 31.35284 31.46868
## [3,] 22.14141 22.24910
## [4,] 19.70460 19.62039
## [5,] 26.78139 26.70438
Av.MSE.train = apply(MSE.train, 2, mean)
Av.MSE.valid = apply(MSE.valid, 2, mean)
# Plot Average MSE
plot(Av.MSE.train, type="o", ylab="MSE")
lines(Av.MSE.valid, type="o", col="red")
legend(2, 40, lty=1, c("Av. Train MSE","Av. Valid MSE"), col=c("black", "red"))# Using Av MSE plot, I choose d=5 is the best
deg.poly = 5
# Train Test
# [ 420 ] [ 86 ]
Fit05 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=Train.set)
summary(Fit05)##
## Call:
## lm(formula = resp ~ poly(lstat, deg.poly, raw = TRUE), data = Train.set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.0360 -2.9462 -0.7869 2.1442 24.4587
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.174e+01 4.088e+00 17.550 < 2e-16 ***
## poly(lstat, deg.poly, raw = TRUE)1 -1.351e+01 1.805e+00 -7.488 4.26e-13 ***
## poly(lstat, deg.poly, raw = TRUE)2 1.475e+00 2.763e-01 5.340 1.54e-07 ***
## poly(lstat, deg.poly, raw = TRUE)3 -8.068e-02 1.869e-02 -4.317 1.98e-05 ***
## poly(lstat, deg.poly, raw = TRUE)4 2.082e-03 5.703e-04 3.650 0.000295 ***
## poly(lstat, deg.poly, raw = TRUE)5 -2.015e-05 6.397e-06 -3.150 0.001750 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.905 on 414 degrees of freedom
## Multiple R-squared: 0.7186, Adjusted R-squared: 0.7152
## F-statistic: 211.5 on 5 and 414 DF, p-value: < 2.2e-16
#- CV Training MSE
MSE.train <- mean(Fit05$residuals^2)
#- CV Validation MSE
pred<- predict(Fit05, newdata=Test.set)
MSE.test <- mean((Test.set$resp - pred)^2)
c(MSE.train, MSE.test) # Final Fit Result## [1] 23.72002 43.09228
## [1] 23.64619 24.40704
# Plot the fit
plot(Train.set$lstat, Train.set$resp, xlab="lstat", ylab="resp", main="Final Model")
lines(Test.set$lstat, Test.set$resp, col="red", type="p", pch=19)
ix = sort(Train.set$lstat, index.return=TRUE)$ix
lines(Train.set$lstat[ix], Fit05$fitted[ix], lwd=2, col="blue" )
text(30,49, paste("d=",deg.poly,": MSE.train=",round(MSE.train,2)))
text(30,46, paste(" MSE.test=",round(MSE.test,2)), col="red")##----------------------------------------
## 1. Load Boston data from package MASS
library(MASS) # install.packages("MASS")
head(Boston) # data is already there
dim(Boston) # (num of row, num of col)
names(Boston) # column names
?Boston # see explanation for variables
# 1 crim per capita crime rate by town.
# 2 zn proportion of residential land zoned for lots over 25,000 sq.ft.
# 3 indus proportion of non-retail business acres per town.
# 4 chas Charles River dummy variable (= 1 if tract bounds river; 0 otherwise).
# 5 nox nitrogen oxides concentration (parts per 10 million).
# 6 rm average number of rooms per dwelling.
# 7 age proportion of owner-occupied units built prior to 1940.
# 8 dis weighted mean of distances to five Boston employment centres.
# 9 rad index of accessibility to radial highways.
# 10 tax full-value property-tax rate per $10,000.
# 11 ptratio pupil-teacher ratio by town.
# 12 black 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town.
# 13 lstat lower status of the population (percent).
# 14 medv (response Y) median value of owner-occupied homes in $1000s.
##----------------------------------------
## 2. Create Cross Validation Data Set
# I've written a function and posed on my website.
# You can load the function using single line with sourse() command.
# The function is called CreateCV().
# The dataframe you feed into the funciton must contain the "resp" column.
# Turn Boston into Tibble
library(tidyverse) # install.packages(tidyverse")
Boston <- as_tibble(Boston)
Boston
# Rename "medv" column as "resp" and move "resp" columnm to 1st
Boston = Boston %>% rename(resp=medv) %>% relocate(resp)
Boston
# Check if there's NA in data
sum(is.na(Boston))
Boston = Boston %>% na.omit() # remove rows with NA (if applicable)
Boston
# Load the file from my website
source("https://nmimoto.github.io/R/ML-00.txt") # load CreateCV()
# Use this function to create CV dataset
CreateCV(Boston, numFolds=5, seed=5480)
# Output (all data.frame):
# Train.set Train.resp
# Test.set Test.resp
# CV.train[[[[k]]]] CV.train.resp[[[[k]]]]
# CV.valid[[[[k]]]] CV.valid.resp[[[[k]]]]
Train.set
Test.set
CV.train[[1]]
CV.valid[[1]]
##----------------------------------------
## 3. Polynomial Regression w 5-fold CV
# If all data is used
deg.poly = 3
Fit00 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=Boston)
# you need raw=TRUE option, otherwise the polynomial will be transformed
summary(Fit00)
plot(Boston$lstat, Boston$resp, xlab="X", ylab="Y")
ix = sort(Boston$lstat, index.return=TRUE)$ix
lines(Boston$lstat[ix], Fit00$fitted[ix], lwd=2, col="black" )
##----------
### 3a. For d=3 and k=5
# fold 1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
deg.poly = 3
k=5
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]] )
summary(Fit01)
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
c(MSE.train, MSE.valid)
# Plot the fit
plot(CV.train[[k]]$lstat, CV.train[[k]]$resp, xlab="X", ylab="Y")
lines(CV.valid[[k]]$lstat, CV.valid[[k]]$resp, col="red", type="p", pch=19)
ix = sort(CV.train[[k]]$lstat, index.return=TRUE)$ix
lines(CV.train[[k]]$lstat[ix], Fit01$fitted[ix], lwd=2, col="black" )
text(30,49, paste("d=",deg.poly,": MSE.tr=",round(MSE.train,2)))
text(30,46, paste("k=",k, ": MSE.va=",round(MSE.valid,2)), col="red")
# run this section for different d, and different k.
##----------
### 3b. For d=3 and k=1:5
# fold 1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
deg.poly = 3
layout(matrix(1:6, 2, 3, byrow=TRUE)) # to plot 5 plots on 1 page
MSE.train <- MSE.valid <- matrix(0, 5, 1)
for (k in 1:5) {
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]])
# summary(Fit01)
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train[k,1] <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid[k,1] <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
# Plot the fit
plot(CV.train[[k]]$lstat, CV.train[[k]]$resp, xlab="X", ylab="Y")
lines(CV.valid[[k]]$lstat, CV.valid[[k]]$resp, col="red", type="p", pch=19)
ix = sort(CV.train[[k]]$lstat, index.return=TRUE)$ix
lines(CV.train[[k]]$lstat[ix], Fit01$fitted[ix], lwd=2, col="black" )
}
MSE.train
MSE.valid
Av.MSE.train = mean(MSE.train)
Av.MSE.train
Av.MSE.valid = mean(MSE.valid)
Av.MSE.valid
layout(1)
##----------
### 3c. For d=1:10 and k=1:5
# k=1 2 3 4 5 Test
# [84][84][84][84][84] x[86]
MSE.train <- MSE.valid <- matrix(0, 5, 10)
for (deg.poly in 1:10) {
for (k in 1:5) {
Fit01 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=CV.train[[k]])
summary(Fit01)
# Get training / validation fit
Train.fitted = predict(Fit01, newdata=CV.train[[k]])
Valid.pred = predict(Fit01, newdata=CV.valid[[k]])
# CV Training MSE
MSE.train[k, deg.poly] <- mean(Fit01$residuals^2)
# CV Validation MSE
MSE.valid[k, deg.poly] <- mean((CV.valid[[k]]$resp - Valid.pred)^2)
}
}
MSE.train
MSE.valid
Av.MSE.train = apply(MSE.train, 2, mean)
Av.MSE.valid = apply(MSE.valid, 2, mean)
# Plot Average MSE
plot(Av.MSE.train, type="o", ylab="MSE")
lines(Av.MSE.valid, type="o", col="red")
legend(2, 40, lty=1, c("Av. Train MSE","Av. Valid MSE"), col=c("black", "red"))
###--- Make decision about best deg.poly to use from the Av MSE plot
##----------------------------------------
## 4. Final Fit with Best hyperparameter
# Using Av MSE plot, I choose d=5 is the best
deg.poly = 5
# Train Test
# [ 420 ] [ 86 ]
Fit05 <- lm( resp ~ poly(lstat, deg.poly, raw=TRUE), data=Train.set)
summary(Fit05)
#- CV Training MSE
MSE.train <- mean(Fit05$residuals^2)
#- CV Validation MSE
pred<- predict(Fit05, newdata=Test.set)
MSE.test <- mean((Test.set$resp - pred)^2)
c(MSE.train, MSE.test) # Final Fit Result
c(Av.MSE.train[5], Av.MSE.valid[5]) # Recall from CV section
# Plot the fit
plot(Train.set$lstat, Train.set$resp, xlab="lstat", ylab="resp", main="Final Model")
lines(Test.set$lstat, Test.set$resp, col="red", type="p", pch=19)
ix = sort(Train.set$lstat, index.return=TRUE)$ix
lines(Train.set$lstat[ix], Fit05$fitted[ix], lwd=2, col="blue" )
text(30,49, paste("d=",deg.poly,": MSE.train=",round(MSE.train,2)))
text(30,46, paste(" MSE.test=",round(MSE.test,2)), col="red")