多元线性回归模型的特征压缩:岭回归和Lasso回归

多元线性回归模型中,如果所有特征一起上,容易造成过拟合使测试数据误差方差过大;因此减少不必要的特征,简化模型是减小方差的一个重要步骤。除了直接对特征筛选,来也可以进行特征压缩,减少某些不重要的特征系数,系数压缩趋近于0就可以认为舍弃该特征。

岭回归(Ridge Regression)和Lasso回归是在普通最小二乘线性回归的基础上加上正则项以对参数进行压缩惩罚。

首先,对于普通的最小二乘线性回归,它的代价函数是:

线性回归RSS

通过拟合系数β来使RSS最小。方法很简单,求偏导利用线性代数解方程组即可。

根据线性代数的理论可知,只要样本量合适,它就存在唯一解,也就是该模型的最优解。

这么做尽管使RSS达到了最小,它还是把所有的特征看作同样重要的程度来求解,并没有做任何特征选择,因此存在过拟合的可能。

岭回归在OLS回归模型的RSS上加上了惩罚项(l2范数),这样代价函数就成为:

岭回归的代价函数

λ是一个非负的调节参数,可以看到:当λ=0时,此时它与RSS一致,没有起到任何惩罚作用;当λ -> ∞时,它的惩罚项也就是无穷大,而为了使代价函数最小,只能压缩系数β趋近于0。

但是因为λ不可能为无穷大,二次项求偏导时总会保留变量本身,所以事实上它也不可能真正地将某个特征压缩为0。尽管系数较小可以有效减小方差,但依然留着一大长串特征会使模型不便于解释。这是岭回归的缺点。

lasso回归的正项则就把二次项改成了一次绝对值(l1范数),具体为:

lasso回归的代价函数

一次项求导可以抹去变量本身,因此lasso回归的系数可以为0。这样可以起来真正的特征筛选效果。

无论对于岭回归还是lasso回归,本质都是通过调节λ来实现模型误差vs方差的平衡调整。

训练构建岭回归模型

> library(ISLR)
> Hitters = na.omit(Hitters)
> x = model.matrix(Salary~., Hitters)[,-1] # 构建回归设计矩阵
> y = Hitters$Salary
> 
> library(glmnet)
> grid = 10^seq(10,-2,length = 100) # 生成100个λ值
> ridge.mod = glmnet(x,y,alpha = 0,lambda = grid) # alpha为0表示岭回归模型,为1表示lasso回归模型
> 
> dim(coef(ridge.mod)) # 20*100的系数矩阵。20是19个特征+截距项,100是λ值
[1]  20 100
> 
> # 显然可见l2范数越大,系数就越小
> ridge.mod$lambda[50]
[1] 11497.57
> coef(ridge.mod)[,50]
  (Intercept)         AtBat          Hits         HmRun          Runs 
407.356050200   0.036957182   0.138180344   0.524629976   0.230701523 
          RBI         Walks         Years        CAtBat         CHits 
  0.239841459   0.289618741   1.107702929   0.003131815   0.011653637 
       CHmRun         CRuns          CRBI        CWalks       LeagueN 
  0.087545670   0.023379882   0.024138320   0.025015421   0.085028114 
    DivisionW       PutOuts       Assists        Errors    NewLeagueN 
 -6.215440973   0.016482577   0.002612988  -0.020502690   0.301433531 
> ridge.mod$lambda[60]
[1] 705.4802
> coef(ridge.mod)[,60]
 (Intercept)        AtBat         Hits        HmRun         Runs 
 54.32519950   0.11211115   0.65622409   1.17980910   0.93769713 
         RBI        Walks        Years       CAtBat        CHits 
  0.84718546   1.31987948   2.59640425   0.01083413   0.04674557 
      CHmRun        CRuns         CRBI       CWalks      LeagueN 
  0.33777318   0.09355528   0.09780402   0.07189612  13.68370191 
   DivisionW      PutOuts      Assists       Errors   NewLeagueN 
-54.65877750   0.11852289   0.01606037  -0.70358655   8.61181213 
> 
> # 输入一个新的λ,比如50,来预测系数
> predict(ridge.mod,s=50,type="coefficients")[1:20,]
  (Intercept)         AtBat          Hits         HmRun          Runs 
 4.876610e+01 -3.580999e-01  1.969359e+00 -1.278248e+00  1.145892e+00 
          RBI         Walks         Years        CAtBat         CHits 
 8.038292e-01  2.716186e+00 -6.218319e+00  5.447837e-03  1.064895e-01 
       CHmRun         CRuns          CRBI        CWalks       LeagueN 
 6.244860e-01  2.214985e-01  2.186914e-01 -1.500245e-01  4.592589e+01 
    DivisionW       PutOuts       Assists        Errors    NewLeagueN 
-1.182011e+02  2.502322e-01  1.215665e-01 -3.278600e+00 -9.496680e+00 
> 
> # 划分训练集和测试集
> set.seed(1)
> train = sample(1:nrow(x),nrow(x)/2)
> test = (-train)
> y.test = y[test]
> 
> # 训练模型,并计算λ=4时的MSE
> ridge.mod = glmnet(x[train,],y[train],alpha = 0,lambda = grid,thresh = 1e-12)
> ridge.pred = predict(ridge.mod,s=4,newx = x[test,])
> mean((ridge.pred - y.test)^2)
[1] 101036.8
> 
> # 增大λ为10的10^10,此时可视为各个特征都被压缩趋近为0,基本只剩截距项起作用
> ridge.pred = predict(ridge.mod,s=1e10,newx = x[test,])
> mean((ridge.pred - y.test)^2) # MSE更大
[1] 193253.1
> 
> # 计算当λ=0也就是不加惩罚的最小二乘回归
> ridge.pred = predict(ridge.mod,s=0,newx = x[test,])
> mean((ridge.pred - y.test)^2) # MSE减小
[1] 114723.6
> 
> ## 以上结果说明,如果λ选得不合适,结果不一定就比最小二乘回归模型更优。至于怎么选择λ,就用交叉验证法。
> 
> set.seed(1)
> cv.out = cv.glmnet(x[train,],y[train],alpha=0)
> plot(cv.out)
> bestlam = cv.out$lambda.min
> bestlam # MSE最小的λ约为212
[1] 211.7416
> 
> ridge.pred = predict(ridge.mod,s=bestlam,newx = x[test,])
> mean((ridge.pred - y.test)^2) # MSE减小
[1] 96015.51
> 
> # 基于整个数据集构建岭回归模型
> out = glmnet(x,y,alpha = 0)
> predict(out,type = "coefficients",s=bestlam)[1:20,]
 (Intercept)        AtBat         Hits        HmRun         Runs 
  9.88487157   0.03143991   1.00882875   0.13927624   1.11320781 
         RBI        Walks        Years       CAtBat        CHits 
  0.87318990   1.80410229   0.13074381   0.01113978   0.06489843 
      CHmRun        CRuns         CRBI       CWalks      LeagueN 
  0.45158546   0.12900049   0.13737712   0.02908572  27.18227535 
   DivisionW      PutOuts      Assists       Errors   NewLeagueN 
-91.63411299   0.19149252   0.04254536  -1.81244470   7.21208390 
> 
> ## 可见岭回归模型还是19个特征,没有舍弃任何特征!

cv.out的图如下:

cv.out

当log(λ)为5.+时(log(bestlam)=5.3),MSE最小。

训练构建lasso回归模型

> lasso.mod = glmnet(x[train,],y[train],alpha = 1,lambda = grid)
> plot(lasso.mod) # 可见有些特征的系数确实可以为0
> 
> set.seed(1)
> cv.out = cv.glmnet(x[train,],y[train],alpha =1)
> plot(cv.out)
> bestlam = cv.out$lambda.min
> bestlam # MSE最小的λ约为16
[1] 16.78016
> lasso.pred = predict(lasso.mod,s=bestlam,newx = x[test,])
> mean((lasso.pred-y.test)^2)
[1] 100743.4
> 
> ## 可见lasso回归模型与岭回归模型MSE差不多,甚至岭回归模型的MSE更小一些。
> 
> out = glmnet(x,y,alpha = 1,lambda = grid)
> lasso.coef = predict(out,type="coefficients",s=bestlam)[1:20,]
> lasso.coef
 (Intercept)        AtBat         Hits        HmRun         Runs 
  18.5394844    0.0000000    1.8735390    0.0000000    0.0000000 
         RBI        Walks        Years       CAtBat        CHits 
   0.0000000    2.2178444    0.0000000    0.0000000    0.0000000 
      CHmRun        CRuns         CRBI       CWalks      LeagueN 
   0.0000000    0.2071252    0.4130132    0.0000000    3.2666677 
   DivisionW      PutOuts      Assists       Errors   NewLeagueN 
-103.4845458    0.2204284    0.0000000    0.0000000    0.0000000 
> 
> ## 可见lasso回归模型中,有12个特征系数被压缩至0。相对于岭回归模型,这里的lasso回归模型以牺牲一部分的准确度为代价,换取更简洁的模型,增加模型的可解释性。这是lasso回归的优势。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容