R语言 正则化示例
stepAIC
rm(list=ls())
data <- swiss
data[,1:5] <- scale(data[,1:5])
mdl <- lm(Infant.Mortality~., data = data) # 原本一共6个变量
require(MASS)
mdl_AIC <- stepAIC(mdl, direction = 'both',trace = FALSE )
length(mdl_AIC$coefficients) # 正则化后还剩3个变量
pred <- predict(mdl_AIC, data)
mean((pred-data$Infant.Mortality)**2 )
# [1] 6.396516
脊回归 Ridge regression
require(glmnet)
X <- as.matrix(data[,1:5])
Y <- as.matrix(data[,6])
md_RR <- glmnet(X, Y, alpha = 0, family = "gaussian")
plot(md_RR, xvar="lambda", label=TRUE)
# 这里的alpha如果是0则为脊回归,如果是1则为拉锁回归
拉锁回归 LASSO
mdl_LASSO <- glmnet(X, Y, alpha = 1, family = "gaussian")
plot(mdl_LASSO, xvar="lambda", label=TRUE)
用交叉验证选择拉锁回归中最优的 λ \lambda λ (也可以用于选择脊回归中的 λ \lambda λ)
cvfit=cv.glmnet(X, Y,family = "gaussian", alpha = 1, type.measure = "mse")
# min返回拥有最小MSE的lambda
# 1se返回在最小cv(MSE)附近变量最少的lambda
c(cvfit$lambda.min,cvfit$lambda.1se)
# [1] 0.2709156 1.2003245
p <- predict(cvfit, newx=X, s="lambda.1se")
mean((p-data$Infant.Mortality)^2 )
# [1] 8.303296
co <- coef(cvfit,s=cvfit$lambda.1se)
length(co@x) # 只剩1个变量,如果是lambda.min则是2个变量
# 图中最贴右边的虚线是lambda.1se
# 左边拥有最小cv(MSE)的是lambda.min
plot(cvfit, ylab="cv(MSE)")
hint:
- 可以发现,拉锁回归会不点减少变量数。实际上随着lambda的变大,拉锁回归会不断启动不同的变量,以达到最小的cv值。这与脊回归完全不同,因为脊回归随着lambda变大从不减少变量的数量。
- lambda越大,变量的权重越接近0。
- 拉锁回归中,越重要的变量会留到最后消失。
- 拉锁回归比AIC消变量消的更狠。