线性模型之-Lasso
算法的简要概述
在机器学习问题中,高维度数据进行回归和分类是一个很困难的问题。例如在许多Microarray生物数据上,数据的维度通常是千和万级别,但是由于收集数据需要昂贵的实验,因此可用的训练数据却相当少,通常只有50-300左右,这样的现象通常称为“small samples, large problem”。
高维度问题带来两个缺点:
1)计算量。从大小矩阵乘积计算和多矩阵计算角度来说,矩阵的稀疏程度越大,矩阵计算数量越少,矩阵计算速度越快。
2)overfitting。对于回归问题来说:
损失函数是$$J(\mathbf{w})=\frac{1}{n} \sum_{i=1}{n}\left(y_{i}-f\left(\mathbf{x}_{i}\right)\right)=\frac{1}{n}|\mathbf{y}-X \mathbf{w}|^{2}$$ 问题的解是$$\hat{\mathbf{w}}=\left(X^{T} X\right)^{-1} X^{T} \mathbf{y}$$ 其中:数据\(X=\left(\mathbf{x}_{1}, \dots, \mathbf{x}_{n}\right)^{T} \in \mathbb{R}^{n \times p}\),标签是\(\mathbf{y}=\left(y_{1}, \dots, y_{n}\right)^{T}\),n是数据个数,p是数据维度,如果n>p,矩阵\(X^{T} X\)的秩小于矩阵未知数的个数,所以矩阵有无数解,所以无论怎么样,我们现在得到的解不是最优解,所以我们需要减少数据的维度,找到最优解。减少数据维度的方法就是对w系数做出惩罚也就是做约束也叫正则化,常规的有L1正则化和L2正则化,L1正则化对应的是Lasso算法,L2正则化对应的是Ringe算法。
相关算法
- 多任务Lasso回归算法,标签y是一个2D数组,形式为(n_samples,n_tasks). 多任务学习是使用不同的线性函数在一样的数据上学习不同的目标函数,也就是在同一个数据上训练多个不同的线性函数。
- Ridge算法,不同于Lasso引入L1正则化,Ridge引入的是L2正则化。
算法的原理
算法公式是:$$J_{L}(\mathbf{w})=\frac{1}{n}|\mathbf{y}-X \mathbf{w}|^{2}+\lambda|\mathbf{w}|_{1}$$ 加入正则化项,使较多参数变成为0,获取大量稀疏解,关于稀疏解的推导和证明请参考这篇博客。
算法求解参数
L1范数罚有一个问题:由于|X|函数在0处不可导,故而直接使用最小二乘法、梯度下降法等方法均失效,但是由于其为第一类间断点中的可去间断点,可以通过补充该点的定义解决,通常,对于线性回归中的lasso回归可以采用近似的前向逐步回归,坐标轴下降法替代。
Sklearn中重要的参数和函数解释
参数名称 | |
---|---|
alpha | 惩罚项系数,默认是1,如果是0的话,算法相当于是最小二乘法 |
Sklearn的函数使用方法
1. 基本回归
1)使用sklean自带的make_regression去fake回归数据
from sklearn.datasets import make_regression
reg_data, reg_target = make_regression(n_samples=200,n_features=1500, n_informative=3, noise=7)
>>> reg_data.shape
(200, 1500)
2)导入Lasso模型,fit数据
>>> from sklearn.linear_model import Lasso
>>> lasso = Lasso()
>>> lasso.fit(reg_data, reg_target)
Lasso(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=1000,
normalize=False, positive=False, precompute=False, random_state=None,
selection='cyclic', tol=0.0001, warm_start=False)
可以看到,默认的alpha参数是1
2. 几个重要参数
1) 相关系数w0
>>> lasso.intercept_
-0.31346949753751252
2) 迭代次数参数
>>> lasso.n_iter_
11
3) 稀疏解的个数
>>> import numpy as np
>>> np.sum(lasso.coef_ != 0)
30
3. 交叉验证获取参数
在Lasso算法中,通常用交叉验证获取最佳参数。
>>> from sklearn.linear_model import LassoCV
>>> lassocv = LassoCV()
>>> lassocv.fit(reg_data, reg_target)
LassoCV(alphas=None, copy_X=True, cv=None, eps=0.001, fit_intercept=True,max_iter=1000,
n_alphas=100, n_jobs=1, normalize=False, positive=False,precompute='auto',
random_state=None, selection='cyclic', tol=0.0001,verbose=False)
CV方法获得的最佳系数
>>> np.sum(lasso.coef_ != 0)
30
>>> lasso.n_iter_
11
看起来,用LassoCV和Lasso获得的参数完全一致,所以可以判定Lasso是用CV方式获取参数。