原文章为scikit-learn中"用户指南"-->""######
下面是一组用在回归中的方法,其预期的结果为各输入变量的线性组合。在数学的概念里,如果** ý 表示我们预测出的结果:
在这一节中,我们定义向量 w = (w1, ..., wp) 为 系数(coef_) ,而 w0 为 截距(intercept_) **。如果要使用线性模型来进行分类的话,可以查看下方的。
1.1.1. 普通最小二乘法(Ordinary Least Squares)#
最小化残差平方和的公式 普通最小二乘法的绘图>>> from sklearn import linear_model
>>> reg = linear_model.LinearRegression()
>>> reg.fit ([[0, 0], [1, 1], [2, 2]], [0, 1, 2])
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> reg.coef_
array([0.5, 0.5])
然而,OLS(普通最小二乘法)里面的系数估量器依赖于当前的模型。当模型与设计矩阵** X **存在近似线性相关的关系时,设计矩阵会变得趋近奇异,其结果是最小二乘法的估量器对观察结果(估量结果)中出现的随机错误会变得很敏感,以致于产生很大的方差。在这种情况下有几率会出现多重共线性,例如,当没有经过实验与设计(数据)时所采集到的数据。
示例
1.1.1.1. OLS的复杂度##
这个方法通过X的奇异值分解来计算其最小二乘解。如果X是一个大小为(n, p)的矩阵,在假设** n ≥ p 的情况,其复杂度为 O(np^2) **。
1.1.2. 岭回归 (Ridge Regression)#
岭回归的最小化公式 。其中,α ≥ 0 是一个控制收缩量的复杂度参数:α的值越大,收缩量的值也越大。因此系数对共线性变得更加鲁棒。
岭系数作为正则化函数
与其他线性模型一样,岭会接收其** fit 方法的数组X, y,并且在拟合后将其计算出的系数 w 存放至其线性模型的 coef_ **属性里:
>>> from sklearn import linear_model
>>> reg = linear_model.Ridge (alpha = .5)
>>> reg.fit ([[0, 0], [0, 0], [1, 1]], [0, .1, 1])
Ridge(alpha=0.5, copy_X=True, fit_intercept=True, max_iter=None,
normalize=False, random_state=None, solver='auto', tol=0.001)
>>> reg.coef_
array([0.34545455, 0.34545455])
>>> reg.intercept_
0.13636...
示例
1.1.2.1. 岭的复杂度##
该方法与OLS有着相同的复杂度。
1.1.2.2. 设置正则化参数:广义交叉验证法##
>>> from sklearn import linear_model
>>> reg = linear_model.RidgeCV(alphas=[0.1, 1.0, 10.0])
>>> reg.fit([[0, 0], [0, 0], [1, 1]], [0, .1, 1])
RidgeCV(alphas=[0.1, 1.0, 10.0], cv=None, fit_intercept=True, scoring=None,
normalize=False)
>>> reg.alpha_
0.1
参考资料
- "正规化最小二乘法的笔记",Rifkin & Lippert (, )。
1.1.3. Lasso回归分析#
Lasso的最小化公式Lasso估量在添加了α || ω ||1后,其中 α 是为常数且 || ω ||1 为 L1范数 **的参数向量时,其能够最小化最小二乘法的惩罚。
的实例使用坐标下降法去拟合其系数。若要查看另一种实现,可以参考:
>>> from sklearn import linear_model
>>> reg = linear_model.Lasso(alpha = 0.1)
>>> reg.fit([[0, 0], [1, 1]], [0, 1])
Lasso(alpha=0.1, 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)
>>> reg.predict([[1, 1]])
array([0.8])
示例
1.1.3.1. 设置正则化参数##
**α **参数控制了估量器系数的稀疏程度。
1.1.3.1.1. 使用交叉验证###
Lasso中,每个折叠上的均方误差:坐标下降Lasso中,每个折叠上的均方误差:最小角回归
1.1.3.1.2. 基于模型选择的信息准则##
基于模型选择的信息准则示例
1.1.4. 多任务Lasso回归分析#
多任务Lasso与简单Lasso的对比图A多任务Lasso与简单Lasso的对比图B
在拟合时间序列模型时,需强制任何活动特征始终处于活动状态。
示例
在数学概念上,其包含了一个经过混合L1,L2范数训练出的线性模型。其最小化函数为:
其中** Fro **表示弗罗贝尼乌斯范数:
弗罗贝尼乌斯范数
且L1,L2:
L1,L2范数
在类的实现里,其使用了坐标下降算法去拟合其系数。
1.1.5. 弹性网络#
弹性网络的最小化公式弹性网络与Lasso的对比
类可以通过交叉验证来设置 alpha(α) 和 l1_ratio(ρ) **参数。
示例
1.1.6. 多任务弹性网络#
多任务弹性网络的最小化公式在类的实现里,其使用了坐标下降算法去拟合其系数。
类可以通过交叉验证来设置 alpha(α) 和 l1_ratio(ρ) **参数。
1.1.7. 最小角回归#
最小角回归(LARS)是一种面向高维度数据由 Bradley Efron, Trevor Hastie, Iain Johnstone 和 Robert Tibshirani开发的一种回归算法。
LARS的优点有:
- 在 p >> n 的情况下拥有高效的计算能力(即当维度的数量明显大于样本点的数量)
- 在计算速度上与前向选择一样快,并且具有与普通最小二乘法相同的复杂度。
- 产生一个完整的分段线性求解路径,其在交叉验证或类似的调整模型的行为上十分有效。
- 如果两个变量的响应几乎相等,那么其系数也有大致相同的增长速率。也因此该算法会表现的如同我们所期望般,并且也会更加稳定。
- 很容易为其他估量器产生解决解,例如Lasso。
当然也有缺点:
- 因为LARS是基于残差的迭代重组,所以它会表现出对噪音的高度敏感。这个问题的讨论细节于 Weisberg 在 Annals of Statistics article(2004) 中与 Efron 等人的讨论部分。
1.1.8.1 LARS Lasso#
LARS Lasso的路径>>> from sklearn import linear_model
>>> reg = linear_model.LassoLars(alpha=.1)
>>> reg.fit([[0, 0], [1, 1]], [0, 1])
LassoLars(alpha=0.1, copy_X=True, eps=..., fit_intercept=True,
fit_path=True, max_iter=500, normalize=True, positive=False,
precompute='auto', verbose=False)
>>> reg.coef_
array([0.717157..., 0. ])
示例
-
LARS算法几乎完全提供了沿着正则化参数的系数的完整路径,因此常见的操作是使用包括所有检索的路径的 函数。
1.1.8.1. 数学公式##
该算法类似前向逐步回归,但不在每一个步骤中都包含了变量,估计出的参数在与残差的每个相关的相同方向上增加。
LARS的解法是通过曲线表示参数向量的L1范数上每个值的解,而且不是输出一个向量值。全关联路径通过排序后存储进** coef_path_ **数组里,其大小为(n_features, max_features + 1),并且其第一列的值始终为0。
引用
- 原始算法在 Hastie 等人编写的论文 中有详细的描述。
1.1.9. 正交匹配追踪(OMP)#
OMP下对固定非零元素求最优解或者,OMP可以针对一个特定的误差而不是固定数量的非零系数来求最优解,这过程可以表达为:
OMP下对特定误差求最优解
OMP基于一个贪婪算法,使其能够包含在每一步计算中与当前残差最相关的元素。这与简单匹配追踪(MP)有点相似,但是比这一点更好的是,在每一次迭代中,它都会在先前选择出的字典元素空间中重新使用正交投影来计算残差。
示例
引用
- , S. G. Mallat, Z. Zhang,
1.1.10 贝叶斯回归#
概率公式**α **同样可以视为在估量过程中的一个随机变量。
贝叶斯回归的优点有:
- 它是适配数据的;
- 能够在估量过程中包含正则化参数。
其缺点为:
- 在推理模型的过程中可能很耗时。
引用
- BishopChristopher M. Bishop 著的 《Pattern Recognition and Machine learning》 一书中关于贝叶斯的章节。
- Radford M. Neal 著的 《Bayesian learning for neural networks》 一书中对原始算法的讨论。
1.1.10.1 贝叶斯岭回归##
ω的先验概率α 和 λ 的先验是通过决定的,即共轭先验的高斯精度。
其产生的模型被称之为贝叶斯岭回归,并且其跟相似。参数 ω , α 和 λ 都是在拟合模型的过程中同步估计出的。而剩余的超参数则是 α 和 λ **的先验参数。他们通常都是被选择为无信息的,通过最大化边际对数似然来估计参数。
在默认情况下, ** α1 = α2 = λ1 = λ2 = 1.e^-6 **。
权重分布图
以下是使用贝叶斯岭回归的例子:
>>> from sklearn import linear_model
>>> X = [[0., 0.], [1., 1.], [2., 2.], [3., 3.]]
>>> Y = [0., 1., 2., 3.]
>>> reg = linear_model.BayesianRidge()
>>> reg.fit(X, Y)
BayesianRidge(alpha_1=1e-06, alpha_2=1e-06, compute_score=False, copy_X=True,
fit_intercept=True, lambda_1=1e-06, lambda_2=1e-06, n_iter=300,
normalize=False, tol=0.001, verbose=False)
经过拟合后,模型就可以用来预测数据了:
>>> reg.predict ([[1, 0.]])
array([0.50000013])
可以通过访问模型的** coef_ 变量成员来获取权重 ω **:
>>> reg.coef_
array([ 0.49999993, 0.49999993])
因为贝叶斯的框架所致,用OLS和贝叶斯产生出来的模型的权重是不一样的。但是贝叶斯岭对此问题却更健壮。
示例
引用
- 能够在MacKay, David J. C编写的文章 中获取到更多有关于此的细节。
1.1.10.2. 自动相关决策 - ARD##
权重的高斯分布其中
A的角度 ARD和OLS的权重对比图
ARD在文献中也被称为稀疏贝叶斯学习和相关向量机[3][4]。
示例
引用
- Christopher M. Bishop: Pattern Recognition and Machine Learning, Chapter 7.2.1
- David Wipf and Srikantan Nagarajan:
- Michael E. Tipping:
- Tristan Fletcher:
1.1.11. Logistic 回归#
Logistic的L2最小化使用L1最小化的方法也是类似的:
Logistic的L1最小化
类中实现的解算器有“liblinear”,“newton-cg”,“lbfgs”和“sag”:
"liblinear"使用坐标下降(CD)算法并依赖于在scikit-learn内的C++的优秀类 实现的 。但是"liblinear"却没办法学习多分类模型。但是对这个问题的替代方案是,使用"one-vs-rest"方式来把所有的分类分割成单独的二元分类问题(即判断一个东西为A,B还是C,可以对这个东西分别判断A,B,C)。当然这一处理过程是向使用者隐藏的,所以实例在默认情况下是使用这一方式来作为求解器的。对于L1惩罚项, 会计算C的下限以获得一个非零模型(即防止所有特征权重值均为0)。
"lbfgs","sag"和"newton-cg"求解器只支持L2惩罚项且在对高维数据时有收敛更快的特性。可以通过在求解器设置** multi_class **为 "multinomial"使其能够支持多元Logistic回归模型[5],同时这样做能够使其比默认的"one-vs-rest"设置上有着更好的准确度。但"lbfgs","sag"和"newton-cg"求解器无法优化带有L1惩罚项的模型。
"sag"求解器使用一种叫随机梯度下降的算法[6]。它在大型数据集下有着比其他模型更快的收敛速度,即在大量样本数量和特征数量的情况下。
简而言之,根据下面的规则可以选择一个相对合适的求解器:
场景 | 求解器 |
---|---|
比较小的数据集 或 使用了L1惩罚项 | "liblinear" |
大型数据集 或 多项式损失 | "lbfgs", "sag" 或 "newton-cg" |
非常大型的数据集 | "sag" |
示例
引用
- Christopher M. Bishop: Pattern Recognition and Machine Learning, Chapter 4.3.4
- Mark Schmidt, Nicolas Le Roux, and Francis Bach:
1.1.12 随机梯度下降 - SGD#
引用
1.1.14. Passive Aggressive 算法#
引用
- K. Crammer, O. Dekel, J. Keshat, S. Shalev-Shwartz, Y. Singer - JMLR 7 (2006)
1.1.15. 稳健回归:异常值和建模误差#
稳健回归能够在有损坏的数据下拟合出一个回归模型:异常值或模型中的误差。
受损的y
1.1.15.1. 不同的场景和有用的概念##
在处理由异常值损坏的数据时有几点我们需要注意:
- 误差值在 X 还是 y ?
误差值在y | 误差值在X |
---|---|
误差值在y | 误差值在X |
- 异常值的比值与误差的幅度
小误差 | 大误差 |
---|---|
小误差 | 大误差 |
稳健拟合的一个重要概念是抛锚点(breakdown point):即模型会为了拟合外部的少量数据,而开始丢失内部的数据。
要时刻注意这一点,稳健回归在拟合高维度的数据(大量的 n_feature)中的设置是很难的。所以在这种设置下稳健模型可能不会进行工作。
- 除非样本的数据量非常大,否则一般情况下 会比 与 要快得多,即 ** 样本数量 >> 特征数量**。这是因为 和 是拟合数据集中的子集。
- 比 要快,且会随着样本的数量增加而表现的更好。
- 在处理大量于 y 里的异常值(同时这也是异常值最普遍出现的形式)表现良好。
-
能够比较好的应对于 X 里存在中等数量异常值的情况。但是这一特性会在高维中失效。
也就是说,如果不知道要用那种估量器时,用 就对了。
1.1.15.2. RANSAC: 随机抽样一致##
RANSAC(随机抽样一致)从完整数据中的随机子集来拟合模型。
RANSAC是一个非确定性算法他只会在一定概率下产生合理的结果,这概率取决于迭代的次数(可以通过** max_trals **参数设置)。其典型的应用场景是用来解决线性与非线性回归问题,并且它也在摄影测量计算机视觉领域中非常流行。
这个算法会把完整的输入拆分成一个集合集,同时这也会使得在每个集合中多多少少受到噪音与异常值的影响。例如。由错误测量引起的噪音或由无效的假设所收集的数据。最终产生的模型也是根据集合来决定。
RANSAC回归
1.1.15.2.1. 算法的细节###
该算法在每次迭代中都会执行以下步骤:
- 从原始数据中选出** min_samples 个随机样本并且检查数据集是否有效( is_data_valid **)。
- 根据随机出来的子集进行拟合。(base_estimator.fit),并且对估量出的模型进行判断其是否有效(is_model_valid)。
- 通过计算估量模型的残差(base_estimator.predict(X) - y)将所有数据进行分类(内点与离群点)。数据的残差比** residual_threshold **要小的就作为内点。
- 如果内点样本已达到最大值,就保存拟合后的模型为合适模型。以防止当前估计出的模型拥有相同数量的内点。不过如果模型的分数更高也会被认为是更好的模型。
这些步骤的最大执行次数(max_trials)或直到满足特殊停止条件之一(详见** stop_n_inliers ** 和 ** stop_score**)后停止。最后会使用先前所有估计出的合适模型来验证所有内点样本来决定最合适的模型。
** is_data_valid ** 和 ** is_model_valid 函数允许用来识别和拒绝随机子样本的退化组合。如果估计出的模型不再需要鉴定退化样本,那么就应该在拟合模型之前调用is_data_valid**,使的模型能够获得一个更好的计算性能。
示例
引用
- Martin A. Fischler and Robert C. Bolles - SRI International (1981)
- Sunglok Choi, Taemin Kim and Wonpil Yu - BMVC (2009)
1.1.15.3. Theil-Sen估量器:普通中值估量器##
示例
引用
1.1.15.3.1. 理论限制###
受损y在scikit-learn中, 的实现是根据多元线性回归的空间中值这一多维中值的概念[7][8]。
在时间和空间复杂度方面,Theil-Sen的尺度根据
Tenil-Sen的尺度
使得在大量数据与特征的情况下,不可能将所有的子集样本应用到该问题中。因此子集的量级可从考虑所有的随机子集的集合来限制时间和空间复杂度。
示例
引用
- Xin Dang, Hanxiang Peng, Xueqin Wang and Heping Zhang:
- T. Kärkkäinen and S. Äyrämö:
1.1.15.4. Huber回归##
Huber与Ridge的对比 Huber的最小化损失公式其中:
Huber的最小化损失公式中的H
建议设置参数** epsilon **的值为1.35以获得95%统计效率。
1.1.15.5. 注意事项##
- 是缩放不变的。当** epsilon 被设置了后,通过任意值缩放 X 与 y 都不会改成其异常值的鲁棒性。而 在缩放 X 与 y 后仍需要重新设置 epsilon **的值。
- 能够充分使用少量样本的数据,而 为了产生一致的鲁棒性则需要多次传递数据。
示例
引用
- Peter J. Huber, Elvezio M. Ronchetti: Robust Statistics, Concomitant scale estimates, pg 172
1.1.16 多项式回归:扩展具有基函数的线性模型#
一种常见的机器学习模式是使用数据的非线性函数的值(即不使用a,而是使用func(a)来代替a)去训练线性模型。这种方式能够保持线性方法的运行性能,也因此使其有能力去拟合更广泛的数据。
举个例子,一个简单的线性回归能够通过在系数上构造多项式特征来进行扩展。在标准的线性回归案例,你可能会有一个像下面这样的公式去拟合二维数据。
拟合二维数据的模型
如果我们想要拟合抛物面到数据而不是一个平面,我们可以结合一个二次多项式特征,所以现在我们的模型看起来是这样子的:
虽然对这个模型进行过处理,但是这个模型(可能会有点让人惊讶)仍旧是一个线性模型:为了了解这一点,想象一下创建一个新的变量向量
新变量Z
在数据进行重标签后,我们的模型看起来是这样的:
对数据重标签后的模型
我们可以知道这个多项式回归与我们先前的设想一样,跟线性模型是同一类的(即模式对** ω **是线性的),并且也可以通过相同(处理线性回归)的技术去处理他。通过考虑在用这些基函数构建的更高维空间内的线性拟合,这个模型对拟合更广泛的数据有具灵活。
这里是一个对单位数据上使用不同程度的多项式特征的例子:
这个图表是通过使用 预处理器生成的。这个预处理器转换输入的数据矩阵成为一个给定维度的新数据矩阵。使用方式如下:
>>> from sklearn.preprocessing import PolynomialFeatures
>>> import numpy as np
>>> X = np.arange(6).reshape(3, 2)
>>> X
array([[0, 1],
[2, 3],
[4, 5]])
>>> poly = PolynomialFeatures(degree=2)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
**X 的特征已经从 [x1, x2] 转换成 [1, x1, x2, x1^2, x1x2, x2^2] **,并且能够在任意的线性模型中使用它了。
>>> from sklearn.preprocessing import PolynomialFeatures
>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.pipeline import Pipeline
>>> import numpy as np
>>> model = Pipeline([('poly', PolynomialFeatures(degree=3)),
... ('linear', LinearRegression(fit_intercept=False))])
>>> # fit to an order-3 polynomial data
>>> x = np.arange(5)
>>> y = 3 - 2 * x + x ** 2 - x ** 3
>>> model = model.fit(x[:, np.newaxis], y)
>>> model.named_steps['linear'].coef_
array([ 3., -2., 1., -1.])
这个模型由多项式特征上训练而成,使得其能够精确地恢复输入的多项式系数。
例如当处理布尔特征时,对于所有的n而言,** xi^n = xi 是毫无作用的(因为等于本身而且是布尔量)。但是 xixj 却代表了两个布尔量之间的链接关系。根据这种关系,我们可以通过线性分类来解决异或问题**:
>>> from sklearn.linear_model import Perceptron
>>> from sklearn.preprocessing import PolynomialFeatures
>>> import numpy as np
>>> X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
>>> y = X[:, 0] ^ X[:, 1]
>>> y
array([0, 1, 1, 0])
>>> X = PolynomialFeatures(interaction_only=True).fit_transform(X).astype(int)
>>> X
array([[1, 0, 0, 0],
[1, 0, 1, 0],
[1, 1, 0, 0],
[1, 1, 1, 1]])
>>> clf = Perceptron(fit_intercept=False, n_iter=10, shuffle=False).fit(X, y)
并且这个分类器的“预测”是完全正确的:
>>> clf.predict(X)
array([0, 1, 1, 0])
>>> clf.score(X, y)
1.0
(在尝试翻译这篇文档的时候难免会因为各种问题而出现错翻,如果发现的话,烦请指出,谢谢> <)