glmnet:Lasso and Elastic-Net Regularized Generalized Linear Models ,套索和弹性网络正则化广义线性模型
正则化技术
正则化是一种常用的技术,用于解决过拟合问题。在机器学习中,当模型的复杂度较高时,容易出现过拟合的情况,即模型在训练数据上的表现较好,但在新数据上的表现较差。正则化就是通过限制模型的复杂度,对模型参数进行调整(数量和大小),使得模型在训练数据上表现与在新数据上的表现相差较小,从而避免过拟合的问题。
正则化是机器学习中的一种叫法,其它领域内叫法各不相同,统计学领域叫惩罚项,数学领域叫范数。而正则项又包括两种,即一范数和二范数,就是L1和L2范数。采用L1范数则是lasso 回归,L2范数则是岭回归。
Lasso回归是一种正则化技术,全称最小绝对收缩和选择算子(least absolute shrinkage and selection operator),它通过在目标函数中加入L1正则项来减少系数的大小,在保证最佳拟合误差的同时,使得参数尽可能的“简单”,使得模型的泛化能力强。
L1正则项的式子:L1 = λ*∑|β|,其中,λ是正则化系数,β是模型中的系数。
Lasso回归的目标函数:min(∑(y - Xβ)^2 + L1)
岭回归(Ridge)是另一项正则化技术,它通过在目标函数中加入L2正则项来减少系数的大小。
L2正则项的式子:L1 = λ*∑β^2
岭回归的目标函数:min(∑(y - Xβ)^2 + L2)
弹性网络是一种正则化技术,它通过在目标函数中加入L1和L2正则项来减少系数的大小。
弹性网络的目标函数:min(∑(y - Xβ)^2 + α * L1 + (1 - α) * L2),其中α是权衡L1和L2正则项的参数,当α = 1时,弹性网络退化成Lasso回归;当α = 0时,弹性网络退化成岭回归。
Glmnet主要用于拟合广义线性模型。筛选可以使loss达到最小的正则化参数lambda。该算法非常快,并且可以使用稀疏矩阵作为输入。主要有线性模型用于回归,logistic回归进行分类以及cox模型进行生存分析。可以从拟合模型中做出各种预测。它也可以拟合多响应线性回归。LASSO回归
什么是Lasso回归
Tibshirani(1996) 引入了 LASSO (Least Absolute Shrinkage and Selection Operator)模型,用于参数的选择和收缩。当我们分析大数据时,这个模型非常有用。可以用R包 glmnet 包建立 LASSO 模型。
Lasso回归是一种线性回归模型,也被称为正则化或惩罚回归模型,它使用L1正则化项来限制变量的系数。这意味着 Lasso 回归可以用来选择最重要的变量,并且可以让不重要的变量的系数收缩到0。因此 Lasso 可以用于变量数量较多的大数据集。而传统的线性回归模型无法处理这类大数据。
Lasso回归复杂度调整的程度由参数lambda来控制,lambda越大模型复杂度的惩罚力度越大,从而获得一个较少变量的模型。Lasso回归和bridge回归都是Elastic Net广义线性模型的特例。除了参数lambda,还有参数alpha,控制对高相关性数据时建模的形状。Lasso回归,alpha=1(R语言glmnet的默认值),brigde回归,alpha=0,一般的elastic net 0<alpha<1.
为了选择最重要的变量,Lasso 回归使用了贪心算法。它会从所有变量中选择一个变量,然后计算使用这个变量时模型的误差。然后,它会继续从剩余的变量中选择一个变量,并计算使用这个变量时模型的误差。这个过程会不断重复,知道找到最优的变量子集为止。
虽然线性回归估计器 (linear regression estimator)在偏-方差权衡关系方面是无偏估计器,但正则化或惩罚回归,如Lasso
,Ridge
承认一些减少方差的偏倚。这意味着后者的最小化问题有两个组成部分:均方误差(linear regression estimator)和惩罚参数。Lasso 的L1惩罚使变量选择和收缩成为可能,而Ridge
的L2惩罚使变量收缩成为可能。
由上式可知,Lasso 回归公式的第一部分是残差平方和(Residual Sum of Squares,RSS),第二部分是惩罚项。该罚项由超参数 λ 调整,λ 由用户通过人工搜索或交叉验证的方式外源性给出。
当Lasso 中包含了某些变量,但RSS
值的降低很小,可以忽略不计时,收缩惩罚的影响就会增加。这意味着这个变量的系数是零(Lasso)或接近零(Ridge)。
Lasso回归使用L1正则化项来限制系数,可以帮助减少变量数量,避免模型过度拟合,并提高模型的泛化能力。
Lasso回归与岭回归的区别
Lasso回归和岭回归都是常用的正则化技术,他们都可以用来减少系数的大小,但他们使用的正则项不同。Lasso回归使用L1正则项,岭回归使用L2正则项。L1正则项的特点是,它可以完全移除某些系数,使得模型中的变量更加稀疏,即变量较少。这对于特征选择非常有用。而岭回归不具有变量的筛选功能,它只能让变量之间的差异变得更小。但L1正则项也有一些缺点,由于L1正则项对所有变量的惩罚都是绝对值,所以对于变量之间的大小没有影响。因此,L1正则项会使得变量之间存在较大的差异,导致模型的可解释性降低。
Lasso回归的优点
Lasso回归的优点在于能够选择出最重要的特征,并且能够有效地防止过拟合。在实际应用中,Lasso回归常用于预测和特征选择。
Lasso回归的缺点
Lasso回归的缺点在于当特征之间存在线性关系时,它的表现不够优秀,以及当特征的数量较多时,计算目标函数的值会变得困难。
比起岭回归,Lasso所带的L1正则项对于系数的惩罚要重得多,并且它会将系数压缩至0,由此选择那些系数不为0的那些特征,以供后续线性回归建模使用。Lasso的正则化系数λ系数更加敏感,因此将其控制在很小的空间范围内变动,以此来寻找最佳的正则化系数。
相比于岭回归,Lasso可以解决现在高维数据一个普遍问题——稀疏性。高维数据即n>m的情况,现在随着数据采集能力的提高,特征数采集的多,但是其中可能有很多特征是不重要的,实际系数很小,如果用岭回归可能估计出相反的结果,即系数很大。而用Lasso可以把这些不重要变量的系数压缩为0,既实现了较为准确的参数估计,也实现了特征选择即降维。
与岭回归(Ridge Regression)相比,Lasso回归亦可解决多重共线性问题,但是不一样的是Lasso回归针对不同的自变量,会使其收敛的速度不一样。有的变量就很快趋于0了,有的却会很慢。因此一定程度上Lasso回归非常适合于做特征选择。但Lasso不是从根本上解决多重共线性问题,而是限制多重共线性带来的影响。
asso回归在建立广义线型模型的时候,可以包含一维连续因变量、多维连续因变量、非负次数因变量、二元离散因变量、多元离散因变,除此之外,无论因变量是连续的还是离散的,lasso都能处理,总的来说,lasso对于数据的要求是极其低的,所以应用程度较广。
lasso的复杂程度由λ来控制,λ越大对变量较多的线性模型的惩罚力度就越大,从而最终获得一个变量较少的模型。
R包 Glmnet
Glmnet主要用于拟合广义线性模型。筛选可以使loss达到最小的正则化参数lambda。该算法非常快,并且可以使用稀疏矩阵作为输入。主要有线性模型用于回归,logistic回归进行分类以及cox模型进行生存分析。可以从拟合模型中做出各种预测。它也可以拟合多响应线性回归。 公式: 根据Hastie(斯坦福统计学家), Tibshirani和Wainwright的Statistical Learning with Sparsity(The Lasso and Generalizations),如下五类模型的变量选择可采用R语言的glmnet包来解决。这五类模型分别是:1. 二分类logistic回归模型,2. 多分类logistic回归模型,3.Possion模型,4.Cox比例风险模型,5.SVM。 其中l(y,η)
是观测i的负对数似然,样本不同的分布具有不同的形式,对于高斯分布可以写为 1/2(y−η)^2,后一项是elastic-net正则化项,beta是需要学习的参数,alpha指定使用Lasso回归(alpha = 1)还是岭回归(alpha = 0)。当我们具有较多的特征时,我们希望进行特征的筛选,Lasso回归会使特征稀疏化,保留部分特征用于构建模型,如果我们不希望舍去任何一个特征,那么便可以使用岭回归。
对于每种模型Glmnet都提供了glmnet
用于拟合模型, cv.glmnet
使用k折交叉验证拟合模型, predict
对数据进行预测(分类/回归),coef
用于提取指定lambda时特征的系数。
线性回归Glmnet主要包含两类模型。包括gaussian (the Gaussian family)和mgaussian (the multiresponse Gaussian family)。
参数family
参数family规定了回归模型的类型:family = "gaussian"适用于一维连续因变量,family = mgaussian"适用于多维连续因变量,family = "poisson"适用于非负次数因变量(count),family = "binomial"适用于二元离散因变量(binary),family = "multinomial"适用于多元离散因变量(category),family = "cox"适用于cox回归。
Gaussian Family
适用于因变量y只有一维的时候:
如:100例样本,20个特征,1个输出值(如生存状态)
(1)首先使用glmnet
拟合线性模型,使用alpha = 0.2
和20个lambda
进行搜索,并给予后50个样本更高的权重:
fit = glmnet(x, y, alpha = 0.2, weights = c(rep(1,50),rep(2,50)), nlambda = 20) print(fit) # 其中%Dev表示模型的可解释偏差,值越大表明该模型包括了越多样本的信息,Lambda则表示20个Lambda对应的值。 plot(fit, xvar = "lambda", label = TRUE) # 可以绘图展示根据lambda变化情况每一个特征的系数变化 plot(fit, xvar = "dev", label = TRUE) # 也可以对%dev绘图
(2)如果我们在构建模型的过程中想要使用交叉验证,则可以使用cv.glmnet
函数,type.measure
表示模型的损失函数,默认为均方误差,nfolds
指定k的大小,默认是20折交叉验证。
cvfit = cv.glmnet(x, y, type.measure = "mse", nfolds = 20) plot(cvfit) # 对模型绘图展示不同的结果
x轴代表经过log以后的lambda值,y轴代表模型的误差,cv.glmnet
会自动选择使误差最小的lambda(左侧的虚线),最小的lambda值保存在cvfit$lambda.min
中
同时我们也可以使用coef
提取每一个特征在指定lambda下的系数,一旦模型训练完成,我们也可以使用predict
对新数据进行预测。
coef.apprx = coef(fit, s = 0.5) # 提取lambda = 0.5时的输入特征的系数,.代表经过L1正则化后这些特征已经被消掉了。 predict(fit, newx = x[1:5,], type = "response", s = 0.05) # 输出新数据的预测值,type参数允许选择预测的类型并提供预测值
Multiresponse Gaussian Family
当我们需要预测多个值时,简单的高斯模型已经不能满足了,这时候我们需要使用family = "mgaussian"
拟合模型,即所谓的“多任务学习”问题。
如:100例样本,20个特征,4个输出值
mfit = glmnet(x, y, family = "mgaussian") # 参数几乎与普通高斯模型相同,例如alpha、weights、nlambda、standard
同样我们可以plot模型的系数
plot(mfit, xvar = "lambda", label = TRUE, type.coef = "2norm") # type.coef=“2norm”时每个变量绘制一条曲线,等同于L2正则化。默认设置为type.coef=“coef”,为每一个因变量绘制一张系数图
其余操作与上边没有差别,使用cv.glmnet
进行交叉验证,使用predict
进行预测以及coef
提取系数,不要忘了family = "mgaussian"
Logistic Regression
对于连续变量我们可以拟合GLM并对新样本进行预测,但当输出值为离散变量表示样本的分类情况时,我们就需要使用一种激活函数将输出值限定在0-1之间,用以代表模型输出该样本属于某一类别的概率。
Binomial Models
当y仅包含两种分类时可以使用二分类模型,
fit = glmnet(x, y, family = "binomial") # 使用family = "binomial"拟合二分类模型
对于logistic回归,cv.glmnet具有与高斯模型相似的参数和用法。nfold、weights、lambda、parallel都可以使用。在type.measure
中有一些差异:“deviance”代表实际偏差, “mae”代表平均绝对误差,“class”代表错配误差,“auc”(仅适用于二分类逻辑回归)并给出ROC曲线下的面积。
cvfit = cv.glmnet(x, y, family = "binomial", type.measure = "class") # 交叉验证 predict(fit, newx = x[1:5,], type = "class", s = c(0.05, 0.01)) # 指定lambda在0.05和0.01时预测新样本的类别,type = "class"指定输出值为类别 plot(cvfit)
Multinomial Models
对于多分类问题,其用法类似于二分类logistic回归。fit = glmnet(x, y, family = "multinomial", type.multinomial = "grouped") # 拟合模型 cvfit=cv.glmnet(x, y, family="multinomial", type.multinomial = "grouped", parallel = TRUE) #交叉验证 plot(fit, xvar = "lambda", label = TRUE, type.coef = "2norm") #绘图展示 plot(cvfit) #绘图展示 predict(cvfit, newx = x[1:10,], s = "lambda.min", type = "class") #预测模型请注意,虽然
type.multinomal
不是cv.glmnet
中的参数,但实际上,可以传递给glmnet
的任何参数在cv.glmnet
的参数列表中都是有效的。我们还使用并行计算来加速计算。在预测过程中,我们只需要在predict
中指定type = "class"
。
Cox回归
在Glmnet中还可以使用Cox风险比例模型,常用于研究预测变量与生存时间的关系。在通常的生存分析框架中,我们有生存时间以及生存状态(0=alive,1=dead)。
fit = glmnet(x, y, family = "cox") #拟合模型,指定family = "cox" plot(fit) cvfit = cv.glmnet(x, y, family = "cox") #交叉验证构建模型 plot(cvfit)
总结一下:
当我们构建回归模型时,y为连续变量,指定family = "gaussian/mgaussian"
构建广义线性模型,在使用交叉验证cv.glmnet
时损失函数选用type.measure = "mse"
使用均方误差,使用predict
预测新样本时指定type = "response"
输出预测值。
当我们构建分类模型时,y为离散变量代表分类数据,指定family = "binomial/multinomial"
以及type.multinomial = "grouped"
构建逻辑回归模型,在使用交叉验证cv.glmnet
时损失函数选用type.measure = "class/auc"
使用错配误差或auc(二分类),使用predict
预测新样本时指定type = "class"
输出预测的类。
当我们构建Cox回归模型时,y为离散变量代表分类数据,指定family = "cox"
构建Cox回归模型