R语言lasso

  • 理论
  • 解释代码输出
  • 代码



理论

LASSO 回归的特点是在拟合广义线性模型的同时进行变量筛选(variable selection)和复杂度调整(regularization)。这里的变量筛选是指不把所有的变量都放入模型中进行拟合,而是有选择的把变量放入模型从而得到更好的性能参数。 复杂度调整是指通过一系列参数控制模型的复杂度,从而避免过度拟合(overfitting)
LASSO 回归复杂度调整的程度由参数 λ 来控制,λ 越大对变量较多的线性模型的惩罚力度就越大,从而最终获得一个变量较少的模型。
glmnet 只能接受数值矩阵作为模型输入,如果自变量中有离散变量的话,需要把这一列离散变量转化为几列只含有 0 和 1 的向量, 这个过程叫做 One Hot Encoding。也就是代码里这一句:X <- as.matrix(train_ds[,1:8])。

解释代码输出

R语言lasso回归cox r语言lasso回归glmnet_复杂度


由上图可以发现,随着参数lambda值的增加,Lasso回归使用的自变量数目在减少,同时模型的预测误差在增大。

R语言lasso回归cox r语言lasso回归glmnet_Lasso_02


上图中的每一条曲线代表了每一个自变量系数的变化轨迹,纵坐标是系数的值,下横坐标是 log(λ),上横坐标是此时模型中非零系数的个数。 我们可以看到,黑线代表的自变量1在 λ 值很大时就有非零的系数,然后随着 λ 值变小不断变大。

然后可通过lasso_model$lambda.min获取使模型均方误差最小的参数lambda,结果为lambda.min=0.007437476。在得到最优的参数lmbda后,使用全部的训练数据集重新训练新的Lasso回归模型,训练时使用glmnet()函数并指定alpha = 1和lambda = lambda.min。

通过coef函数输出lasso方程对各个变量的系数,如下图所示。对这个数据集各个变量系数都不为0,说明这些变量都对因变量有影响,lasso没进行筛选。

R语言lasso回归cox r语言lasso回归glmnet_复杂度_03


最后使用测试集来测试Lasso回归模型的预测能力,将预测值和原始数据比较,计算出平均绝对误差为0.69203,说明该方程对该数据集的预测效果较好,可以用于后续预测。

代码

library(readxl);library(caret);library(glmnet);library(corrplot)
library(Metrics);library(ggplot2)
## 读取数据
diabete <- read.csv("C:/Users/11817/Desktop/565high/assignment/diabetes.csv",sep = ",")
## 可视化相关系数
diabete_cor <- cor(diabete)
corrplot.mixed(diabete_cor,tl.col="black",tl.pos = "d",number.cex = 0.8)
set.seed(123)
#切分数据集
d_index <- createDataPartition(diabete$Outcome,p = 0.7)
train_d <- diabete[d_index$Resample1,]
test_d <- diabete[-d_index$Resample1,]
## 数据标准化
scal <- preProcess(train_d,method = c("center","scale"))
train_ds <- predict(scal,train_d)
test_ds <- predict(scal,test_d)
lambdas <- seq(0,2, length.out = 100)#或者在这里指定lambdas的取值范围
X <- as.matrix(train_ds[,1:8])
Y <- train_ds[,9]
set.seed(1004)
lasso_model <- cv.glmnet(X,Y,alpha = 1,nlambda = 200,nfolds =3)#通过修改lambada的数量
plot(lasso_model)
plot(lasso_model$glmnet.fit, "lambda", label = T)
lasso_model$lambda.min
lasso_min <- lasso_model$lambda.min
lasso_best <- glmnet(X,Y,alpha = 1,lambda = lasso_min)
coef(lasso_best)
#代入测试集
test_pre <- predict(lasso_best,as.matrix(test_ds[,1:8]))
sprintf("标准化后平均绝对误差为: %f",mae(test_ds$Outcome,test_pre))
## 将预测值逆标准化和原始数据进行比较
test_pre_o <- as.vector(test_pre[,1] * scal$std[9] + scal$mean[9])
sprintf("标准化前平均绝对误差为: %f",mae(test_d$Outcome,test_pre_o))

问题1:resample1是什么

R语言lasso回归cox r语言lasso回归glmnet_数据集_04


使用createDataPartition函数切分数据集后产生d_index和resample1这两个变量,和前面的函数搭配使用

问题2:标准化后比标准化前的方差还要大。。

R语言lasso回归cox r语言lasso回归glmnet_R语言lasso回归cox_05