[关闭]
@Macux 2016-01-28T09:32:57.000000Z 字数 4189 阅读 2219

LASSO

Feature_Selection



1、用Lasso进行特征选择

1.1 写在前言

  • 针对OLS(最小二乘法问题),变量选择主要有以下三种思路:
  • “逐步回归”和“最优子集选择”:
    • 原理是利用判别准则(如AIC、BIC、Cp、调整R^2 等)决定最优的模型;
    • 缺点逐步回归,有可能在下一步挑选变量的时候去掉和Xi相关但本身却很重要的解释变量(从业务的角度)。这是因为它每次找到变量,前进的步伐都太大了,侵略性太强。
  • “收缩方法”(shrinkage method),又称为“正则化”(regularization):
    • 主要是岭回归(正则化L2范数)和lasso(正则化L1范数);
    • 岭回归和Lasso的直观区别:
      此处输入图片的描述
      (1)、LASSO比岭回归惩罚更重,对应蓝色的参数可行域面积更小;
      (2)、红色的是最小二乘误差函数的“等高线”,一圈代表一个目标函数值
      (3)、圆心就是样本观测值,半径就是误差值,蓝色区域为约束条件,相交处为当前限制条件下的最优解(最优参数)。
      (4)、从图形来理解正则化,就是不能只通过保证拟合函数在训练集上的RSS最小来确定参数系数,这样做很容易导致过拟合。
      (5)、当使用LASSO正则化时,目标函数的最优解更可能出现在坐标轴上,此时就会出现0权重参数,使得模型稀疏。(Why:“更有可能”源自于一种概率,当可行域图形是菱形或者多边形时,等高线就更有可能与可行域的顶点相交,达到稀疏效果。)
    • 通过对最小二乘估计加入L1惩罚系数,使某些系数的估计为0;
    • elastic net融合了L1和L2两种正则化的方法,是岭回归和lasso的很好的折中。
    • 优点防止过拟合,保证拟合函数不要走向“极端”!!!
      (1)、过拟合,从本质上讲是“拟合函数需要顾忌每一个点,最终形成的拟合函数波动很大。即在某些很小的区间里,函数值的变化很剧烈。由于自变量值可大可小,所以只有系数足够大,才能保证函数值的变化很大。”
      (2)、正则化,是通过约束参数的范数使其不要太大,从而保证在一定程度上减少过拟合情况。
      (3)、用Python实现LR时,默认是用L1正则化来防止过拟合。
  • “维数缩减”,借助PCA对特征集进行收缩:
    • 把p个预测变量投影到m维空间(m < p),利用投影得到的不相关的组合建立线性模型;
    • 缺点造成了信息缺失。

1.2 理论支撑

  • 关于“正则化(Regularization)”:
    • 正则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项。
    • 正则化项是模型复杂度的单调递增函数。
    • 贝叶斯的角度来理解就是,正则化项对应于模型的先验概率,复杂的模型有较小的先验概率,简单的模型有较大的先验概率。
  • 为什么LASSO(L1正则化)可以稀疏化特征集,数学本质在于:
    • 当在Wi=0的地方不可微,且可以将其分解为一个“求和”的形式,那么这个规则化算子就可以实现稀疏。其中,Wi是参数矩阵。LASSO符合这一条件。
  • 基本思想:在回归系数的绝对值之和小于一个常数的约束条件下(规则项),使残差平方和最小(loss function)。
    • 具体而言,就是在最小二乘法的基础上施加L1惩罚,以限制参数长度;
    • 此处输入图片的描述
    • “某些系数”就是那些相对不重要的系数就会变为0,实现特征选择。
    • LASSO的目标函数就是Loss Function,包括loss item(RSS) 和 regularization item
      此处输入图片的描述
      (1)、优化方向是最小化;
      (2)、lambda是一个超参数(hyper parameter),用来平衡loss function 和 规则项之间的权重分配。lambda越大,表示相比模型拟合数据,我们更希望模型能满足设定的约束特性。
      (3)、惩罚项中lambda大于等于0,是个调整参数。lambda越大,惩罚越强;
      (4)、各个待估系数越小,则惩罚项越小,因此惩罚项的加入有利于缩减待估参数接近于0。
  • 参数lambda的确定:
    • 通过交叉验证,选取交叉验证误差最小的lambda值。(可以根据具体需要,选择合适的lambda)
  • 我选用LASSO做特征选择的原因
    • 大牛的经验。在Teradata实习的时候,曾和一位有经验的大牛交流,了解到当用逻辑回归建模时,用Lasso做特征选择,效果较优;
    • LASSO与我做特征选择的原则相符。我做变量筛选的原则是选用一种较为严格的算法,筛选出变量个数较为的候选集,然后根据业务经验进行查缺补漏。LASSO符合这一条件,我可以调整lambda的值,来控制算法筛选变量的严厉程度。

1.3 用R实战

  1. # 准备数据集
  2. data <- read.csv('train_fs.csv')
  3. data_x <- as.matrix(data[,1:11])
  4. data_y <- data[,12]
  5. # 通过交叉验证得到(关于lambda的)最优的方程
  6. r2.cv <- cv.glmnet(x = data_x, y = data_y, family = "binomial", alpha = 1, nfold = 100)
  7. # 使用lambda.1se可以得到更简洁的模型(比lambda.min大,惩罚会更重)
  8. # "lambda.1se": 比最小的lambda大的且保证误差在一个标准误差内的最大lambda,它是既兼顾了误差和模型简洁性的lambda。
  9. r2.1se <- glmnet(x = data_x,y = data_y,family = "binomial",alpha = 1,lambda = r2.cv$lambda.1se)
  10. coef(r2.1se)
  11. 12 x 1 sparse Matrix of class "dgCMatrix"
  12. s0
  13. (Intercept) -0.5935278080
  14. brand -0.3392232190
  15. innet_dur 0.0197089521
  16. dou_M2 .
  17. g4_flux_M2 .
  18. dou_M3 .
  19. g4_flux_M3 .
  20. dou_M4 .
  21. g4_flux_M4 .
  22. arpu_M2 0.0016460497
  23. arpu_M3 0.0002593059
  24. arpu_M4 0.0021364381
  25. # 在很多书中,会将lambda.min 来作为best lambda。个人认为它的筛选条件不够严厉。
  26. r2.min <- glmnet(x = data_x,y = data_y,family = "binomial",alpha = 1,lambda = r2.cv$lambda.min)
  27. coef(r2.min)
  28. 12 x 1 sparse Matrix of class "dgCMatrix"
  29. s0
  30. (Intercept) -6.223512e-01
  31. brand -5.063543e-01
  32. innet_dur 2.598467e-02
  33. dou_M2 .
  34. g4_flux_M2 .
  35. dou_M3 .
  36. g4_flux_M3 .
  37. dou_M4 1.352535e-07
  38. g4_flux_M4 .
  39. arpu_M2 2.516216e-03
  40. arpu_M3 9.513896e-04
  41. arpu_M4 2.031288e-03
  42. # 当alpha 等于0时,是ridge regression。
  43. # 当alpha 介乎0和1之间时,是elastic net。
  44. ## 标准化对LASSO的分析结果影响不大。
  • 结果解释:
    • 分别用了lambda.1se和lambda.min进行特征选择,只有特征的s0值不为0时,才算通过了LASSO筛选;
    • 这里使用的是样本数据,实际运用时,如果机子性能够好,可以用全量数据进行;
    • 可以用“plot(r3.cv)”来简单观察用当前lambda进行正则化惩罚后,模型含有多少变量数;
    • 当用lamda.1se筛选出的变量仍然觉得太多,就要根据plot(rc.cv)的图主动选取合适的lambda。(根据图中最上角的变量个数值来确定对应的lambda)

2、用Random Forest进行特征选择

2.1 理论支撑

  • RF通过给某个特征随机加入噪声后,分类误差的变化来判断特征间的相对重要度。
  • 具体而言,当加入噪声后,分类误差增加,则说明这个特征对于样本的分类结果影响很大,重要程度相对较高。

2.2 用Python实战

  1. import numpy as np
  2. import pandas as pd
  3. import sklearn as sk
  4. from sklearn.ensemble import ExtraTreesClassifier
  5. RF = sk.ensemble.RandomForestClassifier()
  6. RF.fit(train_x,train_y)
  7. # 为了输出更美观,所以将结果输出成一列。
  8. # 为了输出更直观,所以添加一个排名列。
  9. ryan = RF.feature_importances_.reshape(11,1)
  10. ryan2 = pd.DataFrame(ryan,index =test_x.columns,columns = ['coefficient'])
  11. ryan3 = pd.DataFrame(ryan2.rank(ascending = False,axis =0).values
  12. ,index =test_x.columns
  13. ,columns = ['rank']
  14. )
  15. ryan4 = pd.concat([ryan2,ryan3],axis = 1)
  16. # 按照rank排序,将重要的变量排在前面
  17. print (ryan4.sort_index(by = 'rank'))
  18. coefficient rank
  19. innet_dur 0.213563 1
  20. arpu_M3 0.170554 2
  21. arpu_M2 0.128880 3
  22. dou_M4 0.087449 4
  23. dou_M3 0.070306 5
  24. arpu_M4 0.060509 6
  25. g4_flux_M4 0.055392 7
  26. g4_flux_M3 0.055275 8
  27. brand 0.055259 9
  28. g4_flux_M2 0.054844 10
  29. dou_M2 0.047969 11
  30. # 随机森林的输出结果是带有随机性的!

3、写在结尾

  • 通过Lasso和RF进行特征选择,本质上是借助于算法进行变量筛选,输出的结果不一定100%正确;
  • 100%正确的做法是算法为主,业务经验作补充
    • 先利用算法得到一个备选集A,可以尽量将筛选条件设置严厉一点;
    • 对备选集A进行查缺补漏。很多时候,算法认为不重要的变量,但从业务的角度来考虑,它却是一个不可剔除的变量。为了避免错误剔除变量,与业务部门进行沟通,查缺补漏!
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注