当前位置: 代码迷 >> 综合 >> 线性回归(六)—— LASSO
  详细解决方案

线性回归(六)—— LASSO

热度:60   发布时间:2024-01-26 10:48:23.0

LASSO

介绍

在岭回归那一篇说到特征过多而样本过少会出现过拟合的问题,岭回归的解决策略是加一个惩罚函数,也就是正则化。

其实岭回归中的正则化只是L2正则化,如果换成是L1正则化,那么代价函数就会变为
J ( θ 0 , θ 1 , , θ n ) = 1 2 m ( i = 1 m ( y i ? h θ ( x i ) ) 2 + λ i = 1 m θ i ) J(\theta_0,\theta_1,…,\theta_n) = \frac{1}{2m}(\sum_{i=1}^{m}{(y^i-h_\theta(x^i))^2}+\lambda\sum_{i=1}^m|\theta_i|)
这就是LASSO的代价函数。

优势

为什么好端端的岭回归不用,要用这个LASSO呢?

因为岭回归缺乏解释力,最后就算把 λ \lambda 调的非常大,特征参数也只是会趋向0,不会等于0。

明明是特征过多导致的问题,最后你怎么还能预测这么多特征呢?

LASSO就不一样了,随着 λ \lambda 的增大,会将一个个特征参数逐步变成0,这些参数对应的特征就可以被认为是“多余”的。

下面给出解释

再来看一眼Ridge回归的代价函数
J ( θ 0 , θ 1 , , θ n ) = 1 2 m ( i = 1 m ( y i ? h θ ( x i ) ) 2 + λ i = 1 m θ i 2 ) J(\theta_0,\theta_1,…,\theta_n) = \frac{1}{2m}(\sum_{i=1}^{m}{(y^i-h_\theta(x^i))^2}+\lambda\sum_{i=1}^m\theta_i^2)
如果把 λ \lambda 看成是还未选定的参数,那么我们就是求以下这个函数的极小值
J ( θ 0 , θ 1 , , θ n , λ ) = 1 2 m ( i = 1 m ( y i ? h θ ( x i ) ) 2 + λ i = 1 m θ i 2 ) J(\theta_0,\theta_1,…,\theta_n,\lambda) = \frac{1}{2m}(\sum_{i=1}^{m}{(y^i-h_\theta(x^i))^2}+\lambda\sum_{i=1}^m\theta_i^2)
如果你学过高等数学下册的话,就很容易想到拉格朗日乘数法,也就是说,求上面这个函数的极小值和求以下这个函数的条件极值是一样的
J ( θ 0 , θ 1 , , θ n ) = 1 2 m i = 1 m ( y i ? h θ ( x i ) ) 2 J(\theta_0,\theta_1,…,\theta_n) = \frac{1}{2m}\sum_{i=1}^{m}{(y^i-h_\theta(x^i))^2}
条件是为: i = 1 m θ i 2 t \sum_{i=1}^m\theta_i^2\leq t

同理,LASSO和Ridge一样,只不过条件为: i = 1 m θ i t \sum_{i=1}^m|\theta_i|\leq t

以二元为例,我们看一下这张图

在这里插入图片描述

左边是LASSO,右边是Ridge。

残差平方和要取到最小,并且在条件的限制下(图中蓝色区域),那么最小值一定发生在相切处。

Ridge的条件是一个圆,刚好相切在 β 1 \beta_1 β 2 \beta_2 取0时的概率很小,但LASSO是凸出来的角,就很容易在凸角处相切。就更容易使 β 1 \beta_1 β 2 \beta_2 取到0。

因为是带绝对值的,所以有些地方是不可导的,那就不能用梯度下降或正规方程来解特征参数,我也还没搞明白到底是怎么求 θ \theta 的,以后搞明白了再补一篇吧。

LASSO的python实现

# encoding:utf-8
import numpy as np
from sklearn import linear_model# 读取数据
data = np.genfromtxt('../data/longley.csv',delimiter=',')
x_data = data[1:,2:]
y_data = data[1:,1]# 创建模型 
model = linear_model.LassoCV()
model.fit(x_data,y_data)# 打印lasso系数
print("LASSO系数为 :{0}".format(model.alpha_))
print("真实值为:")
print(y_data)
print("LASSO预测值为:")
print(model.predict(x_data))

LASSO