R语言如何和何时使用glmnet岭回归
原文链接:http://tecdat.cn/?p=3373
这里向您展示如何在R中使用glmnet包进行岭回归(使用L2正则化的线性回归),并使用模拟来演示其相对于普通最小二乘回归的优势。
岭回归
当回归模型的参数被学习时,岭回归使用L2正则化来加权/惩罚残差。在线性回归的背景下,它可以与普通最小二乘法(OLS)进行比较。OLS定义了计算参数估计值(截距和斜率)的函数。它涉及最小化平方残差的总和。L2正则化是OLS函数的一个小增加,以特定的方式对残差进行加权以使参数更加稳定。结果通常是一种适合训练数据的模型,不如OLS更好,但由于它对数据中的极端变异(例如异常值)较不敏感,所以一般性更好。
包
我们将在这篇文章中使用以下软件包:
library(tidyverse)
library(broom)
library(glmnet)
与glmnet的岭回归
glmnet软件包提供了通过岭回归的功能glmnet()。重要的事情要知道:
它不需要接受公式和数据框架,而需要一个矢量输入和预测器矩阵。
您必须指定alpha = 0岭回归。
岭回归涉及调整超参数lambda。glmnet()会为你生成默认值。另外,通常的做法是用lambda参数来定义你自己(我们将这样做)。
以下是使用mtcars数据集的示例:
因为,与OLS回归不同lm(),岭回归涉及调整超参数,lambda,glmnet()为不同的lambda值多次运行模型。我们可以自动找到最适合的lambda值,cv.glmnet()如下所示:
cv_fit <- cv.glmnet(x, y, alpha =0, lambda = lambdas)
cv.glmnet() 使用交叉验证来计算每个模型的概括性,我们可以将其视为:
plot(cv_fit)
曲线中的最低点指示最佳的lambda:最好使交叉验证中的误差最小化的lambda的对数值。我们可以将这个值提取为:
opt_lambda <- cv_fit$lambda.minopt_lambda
#> [1] 3.162278
我们可以通过以下方式提取所有拟合的模型(如返回的对象glmnet()):
这是我们需要预测新数据的两件事情。例如,预测值并计算我们训练的数据的R 2值:
y_predicted <- predict(fit, s = opt_lambda, newx = x)
sst <- sum((y - mean(y))^2)
sse <- sum((y_predicted - y)^2)# R squared
rsq <-1- sse / sstrsq
#> [1] 0.9318896
最优模型已经在训练数据中占93%的方差。
Ridge v OLS模拟
通过产生比OLS更稳定的参数,岭回归应该不太容易过度拟合训练数据。因此,岭回归可能预测训练数据不如OLS好,但更好地推广到新数据。当训练数据的极端变化很大时尤其如此,当样本大小较低和/或特征的数量相对于观察次数较多时这趋向于发生。
下面是我创建的一个模拟实验,用于比较岭回归和OLS在训练和测试数据上的预测准确性。
我首先设置了运行模拟的功能:
现在针对不同数量的训练数据和特征的相对比例运行模拟(需要一些时间):
d <- purrr::cross_d(list(n_train = seq(20,200,20),p_features = seq(.55,.95,.05)))
d <- d %>%mutate(results = map2(n_train, p_features, repeated_comparisons))
可视化结果...
对于不同数量的训练数据(对多个特征进行平均),两种模型对训练和测试数据的预测效果如何?
根据假设,OLS更适合训练数据,但Ridge回归更好地归纳为新的测试数据。此外,当训练观察次数较少时,这些影响更为明显。
对于不同的相对特征比例(平均数量的训练数据),两种模型对训练和测试数据的预测效果如何?
再一次地,OLS在训练数据上表现稍好,但Ridge在测试数据上更好。当特征的数量相对于训练观察的数量相对较高时,效果更显着。
下面的图有助于将Ridge对OLS的相对优势(或劣势)可视化为观察值和特征的数量:
这显示了综合效应:当训练观察数量较低和/或特征数目相对于训练观察数目较高时,Ridge回归更好地转移到测试数据。OLS在类似条件下的训练数据上表现略好,表明它比使用脊线正则化时更容易过度训练数据。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【前端】:模块化 - 打包技术
- 代码详解——《无人驾驶车辆模型预测控制》3.3.3参考路径更改
- MySQL redo与undo日志解析
- 样本不平衡造成的影响和解决方案
- 代码详解——NMPC路径跟踪复杂参考路径设置
- 代码详解——NMPC之加入控制平顺性惩罚项
- 代码详解——采用控制增量作为控制输入的NMPC路径跟踪
- 程序员进阶系列:年少不懂爱家家,懂了已是猿中人。
- 代码详解——Simulink中的运动学模型
- Spring Boot 特性之 Failure Analysis
- 「周末福报」头铁的我,一头扎进了知识盲区 ThreadLocal
- 「周末福报」如何高效使用 Kryo
- 「刷题警告」递归算法
- 轻松学Pytorch – 构建生成对抗网络
- 「周末福报」你了解 SPI 吗?