1.广义线性模型
如果 是预测值,
在整个模块中,我们定义向量 作为 coef_ ,定义
作为 intercept_ 。
1.1 普通最小二乘法
LinearRegression 拟合一个带有系数 的线性模型,使得数据集实际观测数据和预测数据(估计值)之间的残差平方和最小。其数学表达式为:
LinearRegression 会调用 fit 方法来拟合数组 X, y,并且将线性模型的系数 存储在其成员变量 coef_中:
# 代码实现LinearRegression
>>> 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=None,
normalize=False)
>>> reg.coef_
Out[4]: array([0.5, 0.5])
奇异矩阵的概念:不是满秩的方阵.首先需要满足是方阵,然后再看矩阵是否满秩,如果矩阵的行列式|A|等于0,则称A为奇异矩阵,若不等于0,则称A为非奇异矩阵.可逆矩阵就是非奇异矩阵,若A为奇异矩阵,则AX=0 有无穷多解,AX=b有无穷多解或者无解.
最小二乘法依赖于各特征的相互独立性,如果特征之间存在相关性,且设计矩阵 的各列近似线性相关,那么设计矩阵会趋向于奇异矩阵,会导致最小二乘对随机误差非常敏感,产生较大的方差.
1.2 岭回归(Ridge)
Ridge 回归通过对系数的大小施加惩罚来解决 普通最小二乘法 的一些问题。 岭系数最小化的是带罚项的残差平方和,
loss函数为,
是控制收缩量w的参数,
越大,收缩量越大,这样系数w对共线性的鲁棒性也更强.
与其他线性模型一样, Ridge
用 fit
方法将模型系数 存储在其
coef_
成员中:
>>> from sklearn import linear_model
>>> reg = linear_model.Ridge(alpha = 0.5) # 正则化参数
>>> reg.fit ([[0, 0], [0, 0], [1, 1]], [0, .1, 1])
Out[7]:
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_
Out[8]: array([0.34545455, 0.34545455])
>>> reg.intercept_
Out[9]: 0.1363636363636364
1.2.1 设置正则化参数:广义交叉验证
RidgeCV
通过内置的 Alpha 参数的交叉验证来实现岭回归。 该对象与 GridSearchCV 的使用方法相同,只是它默认为 Generalized Cross-Validation(广义交叉验证 GCV),这是一种有效的留一验证方法(LOO-CV):
>>> 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])
Out[13]:
RidgeCV(alphas=array([ 0.1, 1. , 10. ]), cv=None, fit_intercept=True,
gcv_mode=None, normalize=False, scoring=None, store_cv_values=False)
>>> reg.alpha_
Out[14]: 0.1
>>> reg.coef_
Out[15]: array([0.44186047, 0.44186047])
1.3 Lasso 回归
The Lasso
是估计稀疏系数的线性模型。 它在一些情况下是有用的,因为它倾向于使用具有较少参数值的情况,有效地减少给定解决方案所依赖变量的数量。 因此,Lasso 及其变体是压缩感知领域的基础。 在一定条件下,它可以恢复一组非零权重的精确集(见 Compressive sensing: tomography reconstruction with L1 prior (Lasso) )。
在数学公式表达上,它由一个带有 先验的正则项的线性模型组成。 其最小化的目标函数是:
Lasso
类的实现使用了 coordinate descent (坐标下降算法)来拟合系数。 查看 最小角回归 ,这是另一种方法:
>>> from sklearn import linear_model
>>> reg = linear_model.Lasso(alpha = 0.1)
>>> reg.fit([[0, 0], [1, 1]], [0, 1])
Out[18]:
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])
由于 Lasso 回归产生稀疏模型,因此可以用于执行特征选择.alpha
参数控制估计系数的稀疏度。
1.3.1 交叉验证来实现Lasso 回归
scikit-learn 通过交叉验证来公开设置 Lasso alpha
参数的对象: LassoCV
和 LassoLarsCV
。 LassoLarsCV
是基于下面解释的 最小角回归 算法。
对于具有许多线性回归的高维数据集, LassoCV
最常见。 然而,LassoLarsCV
在寻找 参数值上更具有优势,而且如果样本数量与特征数量相比非常小时,通常
LassoLarsCV
比 LassoCV
要快。
>>> from sklearn import linear_model
>>> reg = linear_model.LassoCV(alphas= [0.1,0.01,1] )
>>> reg.fit([[0, 0], [0, 0], [1, 1]], [0, .1, 1])
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_split.py:2053: FutureWarning: You should specify a value for 'cv' instead of relying on the default value. The default value will change from 3 to 5 in version 0.22.
warnings.warn(CV_WARNING, FutureWarning)
Out[23]:
LassoCV(alphas=[0.1, 0.01, 1], copy_X=True, cv='warn', eps=0.001,
fit_intercept=True, max_iter=1000, n_alphas=100, n_jobs=None,
normalize=False, positive=False, precompute='auto', random_state=None,
selection='cyclic', tol=0.0001, verbose=False)
>>> reg.alpha_
Out[24]: 0.01
# LassoLarsCV代码实现基本一样
1.3.2 与 SVM 的正则化参数的比较
alpha
和 SVM 的正则化参数C
之间的等式关系是 alpha = 1 / C
或者 alpha = 1 / (n_samples * C)
,并依赖于估计器和模型优化的确切的目标函数。
1.4 多任务Lasso
MultiTaskLasso
是一个估计多元回归稀疏系数的线性模型: y
是一个 (n_samples, n_tasks)
的二维数组,其约束条件和其他回归问题(也称为任务)是一样的,都是所选的特征值。
下图比较了通过使用简单的 Lasso 或 MultiTaskLasso 得到的 W 中非零的位置。 Lasso 估计产生分散的非零值,而 MultiTaskLasso 的一整列都是非零的。
拟合 time-series model (时间序列模型),强制任何活动的功能始终处于活动状态。
在数学上,它由一个线性模型组成,以混合的
作为正则化器进行训练。目标函数最小化是:
其中 表示 Frobenius 标准:
并且
读取为:
MultiTaskLasso
类的实现使用了坐标下降作为拟合系数的算法。
1.5 弹性网络
弹性网络
是一种使用 L1, L2 范数作为先验正则项训练的线性回归模型。 这种组合允许学习到一个只有少量参数是非零稀疏的模型,就像 Lasso
一样,但是它仍然保持 一些像 Ridge
的正则性质。我们可利用 l1_ratio
参数控制 L1 和 L2 的凸组合。
弹性网络在很多特征互相联系的情况下是非常有用的。Lasso 很可能只随机考虑这些特征中的一个,而弹性网络更倾向于选择两个。
在实践中,Lasso 和 Ridge 之间权衡的一个优势是它允许在循环过程(Under rotate)中继承 Ridge 的稳定性。
在这里,最小化的目标函数是
ElasticNetCV
类可以通过交叉验证来设置参数和l1_ratio(p)
2.logistic回归
logistic回归是解决分类问题的一类线性模型,也被称作 logit 回归,maximum-entropy classification(MaxEnt,最大熵分类),或log-linear classifier(对数线性分类器)。模型利用函数 logistic function 将单次试验(single trial)的可能结果输出为概率。
sklearn中logistic回归用LogisticRegression
类中实现了二分类(binary)、一对多分类(one-vs-rest)及多项式 logistic 回归,并带有可选的 L1 和 L2 正则化。
L2范数正则化logistic回归的最小化损失函数为:
类似地,带 L1 正则的 logistic 回归解决的是如下优化问题:
在 LogisticRegression
类中实现了这些优化算法: “liblinear”, “newton-cg”, “lbfgs”, “sag” 和 “saga”。
“lbfgs”, “sag” 和 “newton-cg” solvers (求解器)只支持 L2 惩罚项,对某些高维数据收敛更快。这些求解器的参数 `multi_class`设为 “multinomial” 即可训练一个真正的多项式 logistic 回归 [5] ,其预测的概率比默认的 “one-vs-rest” 设定更为准确。
“sag” 求解器基于平均随机梯度下降算法(Stochastic Average Gradient descent) [6]。在大数据集上的表现更快,大数据集指样本量大且特征数多。
“saga” 求解器 [7] 是 “sag” 的一类变体,它支持非平滑(non-smooth)的 L1 正则选项 penalty="l1"
。因此对于稀疏多项式 logistic 回归 ,往往选用该求解器。
“saga” 一般都是最佳的选择,但出于一些历史遗留原因默认的是 “liblinear” 。
对于大数据集,还可以用 SGDClassifier
,并使用对数损失(’log’ loss)
LogisticRegressionCV
对 logistic 回归 的实现内置了交叉验证(cross-validation),可以找出最优的参数 C 。”newton-cg”, “sag”, “saga” 和 “lbfgs” 在高维数据上更快,因为采用了热启动(warm-starting)。 在多分类设定下,若 <cite>multi_class</cite> 设为 “ovr” ,会为每类求一个最佳的 C 值;若 <cite>multi_class</cite> 设为 “multinomial” ,会通过交叉熵损失(cross-entropy loss)求出一个最佳 C 值。
linear_model.LogisticRegressionCV(Cs=10, fit_intercept=True, cv='warn', dual=False, penalty='l2', scoring=None, solver='lbfgs', tol=0.0001, max_iter=100, class_weight=None, n_jobs=None, verbose=0, refit=True, intercept_scaling=1.0, multi_class='warn', random_state=None)
Cs --
正则化逆的强度
cv --
可以是整数型,或者是一个交叉验证生成器,默认为None.默认的交叉验证生成器是分层K-Folds。如果设定为某一整数,则它代表使用的折叠数
dual --
布尔型,默认值是False。Ture时,表示使用dual formulation,仅仅适用于liblinear且L2正则化时。False时,表示使用primal formulation,当n_samples > n_features,首选False。
penalty --
字符型,可选‘l1’ or ‘l2’, 默认为 ‘l2’,这个参数是选择正则化项的,分别对应的L1正则化和L2正则化。
在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。
penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。但是如果penalty是L1正则化的话,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而‘liblinear’并没有这个依赖。
solver --
字符型,可选‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’, LR默认为'liblinear',LRCV默认为 ‘lbfgs’,这个参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:
a) liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
b) lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
c) newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
d) sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。
d) saga:随机优化SAG的变种。
从上面的描述可以看出,newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。
同时,sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了。要么通过对样本采样来降低样本量,要么回到L2正则化。
从上面的描述,大家可能觉得,既然newton-cg, lbfgs和sag这么多限制,如果不是大样本,我们选择liblinear不就行了嘛!错,因为liblinear也有自己的弱点!我们知道,逻辑回归有二元逻辑回归和多元逻辑回归。对于多元逻辑回归常见的有one-vs-rest(OvR)和many-vs-many(MvM)两种。而MvM一般比OvR分类相对准确一些。郁闷的是liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。也意味着如果我们需要相对精确的多元逻辑回归不能使用L1正则化了。
multi_class --
字符型,可选为‘ovr’,或者‘multinomial’,默认为‘ovr’。这个参数决定我们的分类方式。
ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM)。如果是二元逻辑回归,ovr和multinomial并没有任何区别,区别主要在多元逻辑回归上。
OvR的思想很简单,无论你是多少元逻辑回归,我们都可以看做二元逻辑回归。具体做法是,对于第K类的分类决策,我们把所有第K类的样本作为正例,除了第K类样本以外的所有样本都作为负例,然后在上面做二元逻辑回归,得到第K类的分类模型。其他类的分类模型获得以此类推。
而MvM则相对复杂,这里举MvM的特例one-vs-one(OvO)作讲解。如果模型有T类,我们每次在所有的T类样本里面选择两类样本出来,不妨记为T1类和T2类,把所有的输出为T1和T2的样本放在一起,把T1作为正例,T2作为负例,进行二元逻辑回归,得到模型参数。我们一共需要T(T-1)/2次分类。
从上面的描述可以看出OvR相对简单,但分类效果相对略差(这里指大多数样本分布情况,某些样本分布下OvR可能更好)。而MvM分类相对精确,但是分类速度没有OvR快。
如果选择了ovr,则4种损失函数的优化方法liblinear,newton-cg, lbfgs和sag都可以选择。但是如果选择了multinomial,则只能选择newton-cg, lbfgs和sag了。
class_weight --
可以自己设置为dict形式(即{0:0.2,1:0.8}此种形式,为每个类别赋权)或者为‘balanced’,默认为None。这个参数是来确定类别权重的。
当默认None不填的时候,即不考虑权重,或者说所有类型的权重一样。
当自定义dict的时候,则按照自定义的权重。
当选择‘balanced’的时候,那么类库会根据训练样本量来计算权重。某种类型样本量越多,则权重越低,样本量越少,则权重越高。
那么class_weight有什么作用呢?在分类模型中,我们经常会遇到两类问题:
第一种是误分类的代价很高。比如对合法用户和非法用户进行分类,将非法用户分类为合法用户的代价很高,我们宁愿将合法用户分类为非法用户,这时可以人工再甄别,但是却不愿将非法用户分类为合法用户。这时,我们可以适当提高非法用户的权重。
第二种是样本是高度失衡的,比如我们有合法用户和非法用户的二元样本数据10000条,里面合法用户有9995条,非法用户只有5条,如果我们不考虑权重,则我们可以将所有的测试集都预测为合法用户,这样预测准确率理论上有99.95%,但是却没有任何意义。这时,我们可以选择balanced,让类库自动提高非法用户样本的权重。
提高了某种分类的权重,相比不考虑权重,会有更多的样本分类划分到高权重的类别,从而可以解决上面两类问题。
当然,对于第二种样本失衡的情况,我们还可以考虑用下一节讲到的样本权重参数: sample_weight,而不使用class_weight。
sample_weight --
这个参数不是在模型训练时需要设定的参数,而是在fit时,可能会用到的。为数组array格式。
由于样本可能存在不失衡的问题,导致样本不是总体样本的无偏估计,从而可能导致我们的模型预测能力下降。遇到这种情况,我们可以通过调节样本权重来尝试解决这个问题。调节样本权重的方法有两种,第一种是在class_weight使用balanced。第二种是在调用fit函数时,通过sample_weight来自己调节每个样本权重。
在scikit-learn做逻辑回归时,如果上面两种方法都用到了,那么样本的真正权重是class_weight*sample_weight.
通用参数介绍:
tol --
浮点型,默认值为1e-4,该参数用于指定判断算法收敛的阈值。
fit_intercept --
布尔型,默认值为True,指定是否应将常量(即平常所说的偏差或截距)添加到决策函数中。
intercept_scaling --
浮点型,默认为1。
只有当使用liblinear且fit_intercept设置为ture的时候,该参数才有用。
在这种情况下,x变为[x,intercept_scaling],即一个“合成”特征被附加到实例向量中, 该“合成”特征的常数值等于intercept_scaling。
截距变为intercept_scaling * synthetic_feature_weight。
注意! 合成特征权重与所有其他特征一样,需经过L1 / L2正则化。 为了减小正则化对合成特征权重(并因此对截距)的影响,必须增加intercept_scaling。
random_state --
可选,可以是int整数型,也可以是RandomState instance, 或者是 None。默认是None。只有当solver选择‘sag’ 或者是‘liblinear’时使用。
该参数表示在随机数据混洗时使用的伪随机数生成器的种子。
如果是int,则random_state是随机数生成器使用的种子;
如果是RandomState实例,则random_state是随机数生成器;
如果为None,则随机数生成器是np.random使用的RandomState实例。
max_iter --
整数型,默认值为100。仅适用于solver选择newton-cg,sag和lbfgs时,表示求解器收敛的最大迭代次数。
verbose --
整数型,默认值为0,适用于solver选择liblinear或bfgs时,将verbose设置为任何正数以表示冗长度。
n_jobs --
整数型,默认值为1,仅适用于multi_class=ovr时,用于指定并行运算的CPU数量。且,需要注意的是,如果solver选择liblinear,则不管multi_class设置为ovr或multinomial,这个参数都会被忽略。
如果给定值为-1,则使用所有CPU。
linear_model.LogisticRegression(penalty='l2', dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver='warn', max_iter=100, multi_class='warn', verbose=0, warm_start=False, n_jobs=None)
LogisticRegression个性化参数介绍:
C -- 浮点型,默认值为1.0。该参数表示正则化的惩罚系数。应该是一个正的浮点数。
warm_start -- 布尔型,默认值为False。
设置为True时,下次训练是以追加的形式进行,否则,就会重新全部计算。
warm_start对于liblinear没用,支持lbfgs,newton-cg,sag,saga。
与 liblinear 的区别:
当 fit_intercept=False
、回归得到的 coef_
以及待预测的数据为零时, LogisticRegression
用 solver=liblinear
及 LinearSVC
与直接使用外部liblinear库预测得分会有差异。这是因为, 对于 decision_function
为零的样本, LogisticRegression
和 LinearSVC
将预测为负类,而liblinear预测为正类。 注意,设定了 fit_intercept=False
,又有很多样本使得 decision_function
为零的模型,很可能会欠拟合,其表现往往比较差。建议您设置 fit_intercept=True
并增大 intercept_scaling
。
几个例子:
自己写的代码在 jupyter-notebook
L1 Penalty and Sparsity in Logistic Regression
比较不同C值下L1和L2罚时解的稀疏性可以看出,C值越大,模型的自由度越大。相反,C值越小,模型约束越大。在L1惩罚的情况下,这导致了更稀疏的解决方案。
Path with L1- Logistic Regression
Regularization path of L1- Logistic Regression
Plot multinomial and One-vs-Rest Logistic Regression
Multiclass sparse logisitic regression on newgroups20
MNIST classfification using multinomial logistic + L1
利用稀疏 logistic 回归(sparse logisitic regression)进行特征选择
带 L1 罚项的 logistic 回归 将得到稀疏模型(sparse model),相当于进行了特征选择(feature selection),详情参见 基于 L1 的特征选取 。
LogisticRegressionCV
对 logistic 回归 的实现内置了交叉验证(cross-validation),可以找出最优的参数 C。”newton-cg”, “sag”, “saga” 和 “lbfgs” 在高维数据上更快,因为采用了热启动(warm-starting)。在多分类设定下,若 multi_class 设为”ovr”,会为每类求一个最佳的C值;若 multi_class 设为”multinomial”,会通过交叉熵损失(cross-entropy loss)求出一个最佳 C 值。
3.随机梯度下降 SGD
Stochastic Gradient Descent官方文档
随机梯度下降是拟合线性模型的一个简单而高效的方法。在样本量(和特征数)很大时尤为有用。 方法 partial_fit
可用于 online learning (在线学习)或基于 out-of-core learning (外存的学习)
SGDClassifier
和 SGDRegressor
分别用于拟合分类问题和回归问题的线性模型,可使用不同的(凸)损失函数,支持不同的罚项。 例如,设定 loss="log"
,则 SGDClassifier
拟合一个逻辑斯蒂回归模型,而 loss="hinge"
拟合线性支持向量机(SVM).
SGDClassifier
(loss=’hinge’, penalty=’l2’, alpha=0.0001, l1_ratio=0.15, fit_intercept=True, max_iter=1000, tol=0.001, shuffle=True, verbose=0, epsilon=0.1, n_jobs=None, random_state=None, learning_rate=’optimal’, eta0=0.0, power_t=0.5, early_stopping=False, validation_fraction=0.1, n_iter_no_change=5, class_weight=None, warm_start=False, average=False)
sklearn.linear_model.SGDClassifier函数参数文档
loss --
str,默认:'hinge'.
可能的选项是'hinge','log','modified_huber','squared_hinge','perceptron'或回归损失:'squared_loss','huber','epsilon_insensitive'或'squared_epsilon_insensitive'。
'log'损失给出逻辑回归,即概率分类器。'modified_huber'是另一个平滑损失,它带来了对异常值的容忍度以及概率估计。'squared_hinge'就像铰链一样,但是被二次惩罚。'perceptron'是感知器算法使用的线性损耗。其他损失是为回归而设计的,但也可用于分类
penalty --
str,'none','l2','l1'或'elasticnet'
alpha --
常数乘以正则化项。默认为0.0001当设置为“最佳”时,还用于计算learning_rate
sklearn.linear_model.SGDRegressor函数参数文档
SGDRegressor
(loss=’squared_loss’, penalty=’l2’, alpha=0.0001, l1_ratio=0.15, fit_intercept=True, max_iter=1000, tol=0.001, shuffle=True, verbose=0, epsilon=0.1, random_state=None, learning_rate=’invscaling’, eta0=0.01, power_t=0.25, early_stopping=False, validation_fraction=0.1, n_iter_no_change=5, warm_start=False, average=False)
4. Perceptron(感知器)
Perceptron
是适用于 large scale learning(大规模学习)的一种简单算法。默认地,
- 不需要设置学习率(learning rate)。
- 不需要正则化处理。
- 仅使用错误样本更新模型。
最后一点表明使用合页损失(hinge loss)的感知机比SGD略快,所得模型更稀疏。
待续...