回归分析是一种统计技术,可对因变量与一个或多个自变量之间的关系进行建模和近似。 本文将快速介绍三个使用R和Boston住房数据集的常用回归模型:Ridge,Lasso和Elastic Net。
首先,我们需要了解回归的基本知识以及使用特定模型时方程式的哪些参数会发生变化。 简单线性回归,也称为普通最小二乘(OLS),试图使误差平方和最小。 在这种情况下,误差是实际数据点与其预测值之间的差。
平方误差的可视化(来自Setosa.io)
该模型的方程式称为成本函数,是一种通过最小化和测量来找到最佳误差的方法。 梯度下降算法用于通过多次迭代来找到最佳成本函数。 但是,使用基本的OLS模型来表征和定义数据并非总是那么容易。
最小二乘方程
一种情况是数据显示多重共线性,这是当预测变量彼此相关且与响应变量相关时。 为了说明这一点,我们正在做一项研究,着眼于一个反应变量-患者体重,而我们的预测变量是身高,性别和饮食习惯。 这里的问题是身高和性别也相关,并且会夸大其系数的标准误差,这可能会使它们在统计学上显得无关紧要。
为了生成更精确的复杂数据模型,我们可以在OLS方程中添加一个惩罚项。 惩罚增加了偏见 对某些价值观。 这些被称为L1正则化(套索回归)和L2正则化(脊回归)。
我们希望提供的最佳模型可以最大程度地减少偏差 和方差 :
方差/偏差权衡(KDnuggets.com)
岭回归
Ridge回归使用L2正则化将以下惩罚项添加到OLS方程中。
L2正则化惩罚项
L2项等于系数幅度的平方。 在这种情况下,如果lambda( λ)为零,则该方程为基本OLS,但如果它大于零,则对系数添加约束。 该约束导致最小化的系数(又称收缩率),λ值越大,趋向于零。 缩小系数会导致较低的方差,进而导致较低的误差值。 因此,Ridge回归可降低模型的复杂性,但不会减少变量的数量,而只会缩小其影响。
套索回归
拉索回归使用L1惩罚项,代表最小绝对收缩和选择算符 。 对L2施加的惩罚等于系数幅度的绝对值:
L1正则化惩罚项
与脊回归类似,λ值为零时会吐出基本OLS方程,但是,给定合适的λ值lasso回归可以使某些系数变为零。 lambda的值越大,将更多的功能缩小为零。 这可以完全消除某些功能,并为我们提供一个预测子集,有助于减轻多重共线性和模型复杂性。 预测变量没有缩小到零表示它们很重要,因此L1正则化允许进行特征选择(稀疏选择)。
弹性网
第三种常用的回归模型是Elastic Net,它结合了L1和L2正则化的惩罚:
弹性净正则化
除了设置和选择lambda值外,弹性网还允许我们调整alpha参数,其中𝞪 = 0对应于岭,and = 1对应套索。 简而言之,如果您为alpha插入0,则惩罚函数将减少为L1(岭)项,如果将alpha设置为1,我们将得到L2(套索)项。 因此,我们可以在0到1之间选择一个alpha值来优化弹性网。 有效地,这将缩小一些系数并将稀疏选择的系数设置为0。
准备数据
我们将使用以下软件包:
library(tidyverse)
library(caret)
library(glmnet)
我们还将使用R内置的波士顿住房市场数据集,因为它具有许多预测变量
data(“Boston”, package = “MASS”)
#set a seed so you can reproduce the results
set.seed(1212)
#split the data into training and test data
sample_size <- floor(0.75 * nrow(Boston))
training_index <- sample(seq_len(nrow(Boston)), size = sample_size)
train <- Boston[training_index, ]
test <- Boston[-training_index, ]
我们还应该创建两个对象来存储预测变量(x)和响应变量(y,中值)
# Predictor
x <- model.matrix(medv~., train)[,-1]
# Response
y <- train$medv
执行Ridge回归
正如我们在前面的部分中提到的,λ值对系数有很大的影响,因此现在我们将计算并选择一个合适的值。
在这里,我们执行交叉验证,并在将数据拟合到模型并查看系数之前,先查看与最低预测误差对应的lambda值。
cv.r <- cv.glmnet(x, y, alpha = 0)
cv.r$lambda.min
model.ridge <- glmnet(x, y, alpha = 0, lambda = cv.r$lambda.min)
coef(model.ridge)
我们在这里可以看到某些系数已被推向零并最小化,而RM(房间数)的权重明显高于其余系数
岭回归系数
现在,我们通过使用模型上的测试数据来查看模型的性能。
x.test.ridge <- model.matrix(medv ~., test)[,-1]
predictions.ridge <- model.ridge
%>% predict(x.test.ridge)
%>% as.vector()
data.frame(
RMSE.r = RMSE(predictions.ridge, test$medv),
Rsquare.r = R2(predictions.ridge, test$medv))
RMSE = 4.8721和R²= 0.7205
执行套索回归
步骤将与我们对岭回归所做的相同。 alpha值是唯一的更改(请记住𝞪 = 1表示套索)
cv.l <- cv.glmnet(x, y, alpha = 1)
cv.l$lambda.min
model.lasso <- glmnet(x, y, alpha = 1, lambda = cv.l$lambda.min)
coef(model.lasso)
x.test.lasso <- model.matrix(medv ~., test)[,-1]
predictions.lasso <- model.lasso %>%
predict(x.test.lasso) %>%
as.vector()
data.frame(
RMSE.l = RMSE(predictions.lasso, test$medv),
Rsquare.l = R2(predictions.lasso, test$medv))
RMSE = 4.8494,R²= 0.7223
执行弹性净回归
执行Elastic Net要求我们调整参数以识别最佳的alpha和lambda值,为此,我们需要使用caret
包。 我们将通过迭代多个alpha和lambda对来调整模型,我们可以看到哪个对具有最低的相关误差。
model.net <- train(
medv ~., data = train, method = "glmnet",
trControl = trainControl("cv", number = 10),
tuneLength = 10)
model.net$bestTune
coef(model.net$finalModel, model.net$bestTune$lambda)
x.test.net <- model.matrix(medv ~., test)[,-1]
predictions.net <- model.net %>% predict(x.test.net)
data.frame(
RMSE.net = RMSE(predictions.net, test$medv),
Rsquare.net = R2(predictions.net, test$medv))
RMSE = 4.8523,R²= 0.7219
结论
我们可以看到,使用所有三个模型的R均方值都非常接近,但是两者的性能都比脊回归好一些(拉索表现最好)。 Lasso回归也显示出最高的R²值。