在scikit-learn中,与逻辑回归有关的主要是这3个类。LogisticRegression, LogisticRegressionCV 和logistic_regression_path。其中LogisticRegression和LogisticRegressionCV的主要区别是LogisticRegressionCV使用了交叉验证来选择正则化系数C。而LogisticRegression需要自己每次指定一个正则化系数。除了交叉验证,以及选择正则化系数C以外, LogisticRegression和LogisticRegressionCV的使用方法基本相同。
logistic_regression_path类则比较特殊,它拟合数据后,不能直接来做预测,只能为拟合数据选择合适逻辑回归的系数和正则化系数。主要是用在模型选择的时候。一般情况用不到这个类,所以后面不再讲述logistic_regression_path类。
此外,scikit-learn里面有个容易让人误解的类RandomizedLogisticRegression,虽然名字里有逻辑回归的词,但是主要是用L1正则化的逻辑回归来做特征选择的,属于维度规约的算法类,不属于我们常说的分类算法的范畴。
后面的讲解主要围绕LogisticRegression和LogisticRegressionCV中的重要参数的选择来来展开,这些参数的意义在这两个类中都是一样的。
正则化选择参数:penalty
LogisticRegression和LogisticRegressionCV默认就带了正则化项。penalty参数可选择的值为"l1"和"l2".分别对应L1的正则化和L2的正则化,默认是L2的正则化。
在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。
penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。但是如果penalty是L1正则化的话,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而‘liblinear’并没有这个依赖。
具体使用了这4个算法有什么不同以及有什么影响我们下一节讲。
优化算法选择参数:solver
solver参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:
a) liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
b) lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
c) newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
d) sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候,SAG是一种线性收敛算法,这个速度远比SGD快。关于SAG的理解,参考博文线性收敛的随机优化算法之 SAG、SVRG(随机梯度下降)
从上面的描述可以看出,newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。
同时,sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了。要么通过对样本采样来降低样本量,要么回到L2正则化。
在sklearn的官方文档中,对于solver的使用说明如下:
In a nutshell, one may choose the solver with the following rules:
CaseSolverSmall dataset or L1 penalty“liblinear”Multinomial loss or large dataset“lbfgs”, “sag” or “newton-cg”Very Large dataset“sag”
从上面的描述,大家可能觉得,既然newton-cg, lbfgs和sag这么多限制,如果不是大样本,我们选择liblinear不就行了嘛!错,因为liblinear也有自己的弱点!我们知道,逻辑回归有二元逻辑回归和多元逻辑回归。对于多元逻辑回归常见的有one-vs-rest(OvR)和many-vs-many(MvM)两种。而MvM一般比OvR分类相对准确一些。郁闷的是liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。也意味着如果我们需要相对精确的多元逻辑回归不能使用L1正则化了。
总结而言,liblinear支持L1和L2,只支持OvR做多分类,“lbfgs”, “sag” “newton-cg”只支持L2,支持OvR和MvM做多分类。
具体OvR和MvM有什么不同我们下一节讲。
分类方式选择参数:multi_class
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
class_weight参数用于标示分类模型中各种类型的权重,可以不输入,即不考虑权重,或者说所有类型的权重一样。如果选择输入的话,可以选择balanced让类库自己计算类型权重,或者我们自己输入各个类型的权重,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9, 1:0.1},这样类型0的权重为90%,而类型1的权重为10%。
如果class_weight选择balanced,那么类库会根据训练样本量来计算权重。某种类型样本量越多,则权重越低,样本量越少,则权重越高。
sklearn的官方文档中,当class_weight为balanced时,类权重计算方法如下:
n_samples / (n_classes * np.bincount(y)),n_samples为样本数,n_classes为类别数量,np.bincount(y)会输出每个类的样本数,例如y=[1,0,0,1,1],则np.bincount(y)=[2,3]
那么class_weight有什么作用呢?在分类模型中,我们经常会遇到两类问题:
第一种是误分类的代价很高。比如对合法用户和非法用户进行分类,将非法用户分类为合法用户的代价很高,我们宁愿将合法用户分类为非法用户,这时可以人工再甄别,但是却不愿将非法用户分类为合法用户。这时,我们可以适当提高非法用户的权重。
第二种是样本是高度失衡的,比如我们有合法用户和非法用户的二元样本数据10000条,里面合法用户有9995条,非法用户只有5条,如果我们不考虑权重,则我们可以将所有的测试集都预测为合法用户,这样预测准确率理论上有99.95%,但是却没有任何意义。这时,我们可以选择balanced,让类库自动提高非法用户样本的权重。
提高了某种分类的权重,相比不考虑权重,会有更多的样本分类划分到高权重的类别,从而可以解决上面两类问题。
当然,对于第二种样本失衡的情况,我们还可以考虑用下一节讲到的样本权重参数: sample_weight,而不使用class_weight。sample_weight在下一节讲。
样本权重参数: sample_weight
上一节我们提到了样本不失衡的问题,由于样本不平衡,导致样本不是总体样本的无偏估计,从而可能导致我们的模型预测能力下降。遇到这种情况,我们可以通过调节样本权重来尝试解决这个问题。调节样本权重的方法有两种,第一种是在class_weight使用balanced。第二种是在调用fit函数时,通过sample_weight来自己调节每个样本权重。
在scikit-learn做逻辑回归时,如果上面两种方法都用到了,那么样本的真正权重是class_weight*sample_weight.
以上就是scikit-learn中逻辑回归类库调参的一个小结,还有些参数比如正则化参数C(交叉验证就是 Cs),迭代次数max_iter等,由于和其它的算法类库并没有特别不同,这里不多累述了。
plot_decision_boundary(lambda x: clf.predict(x))
第17行(超难句):这里面有两个难点:
lambda x: clf.predict(x)是什么?
lambda实际上是一种函数,当你想运行一个函数而又毫不关心他的函数名时,就可以叫他lambda。这个函数实际上可以写为
def call_clf_predict(x):
return clf.predict(x)
plot_decision_boundary(call_clf_predict)
lambda函数实际上和lambda演算相关,lambda演算就是尝试把函数当做数去使用。
第8行到底接受到了什么?
答案是第8行实际上接收到了一个方法(函数),这个方法被用pred_func进行了替换。那么这个方法又是谁呢?答案是lambda函数
lambda函数又是谁呢?答案是clf.predict(x)。所以pred_func实际上就是clf.predict(x)。
因此在调用环节,plot_decision_boundary(lambda x: clf.predict(x)) 等价于 plot_decision_boundary(clf.predict)
classifier = LogisticRegression() # 使用类,参数全是默认的
是默认的,所有的参数全都是默认的,其实我们可以自己设置许多。这需要用到官方给定的参数说明,如下:
classsklearn.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)
Logistic Regression (aka logit, MaxEnt) classifier.
In the multiclass case, the training algorithm uses a one-vs.-all (OvA) scheme, rather than the “true” multinomial LR.
This class implements L1 and L2 regularized logistic regression using the liblinear library. It can handle both dense and sparse input. Use C-ordered arrays or CSR matrices containing 64-bit floats for optimal performance; any other input format will be converted (and copied).
Parameters:
penalty : string, ‘l1’ or ‘l2’ 惩罚项的种类Used to specify the norm used in the penalization.
dual : booleanDual or primal formulation. Dual formulation is only implemented for l2 penalty. Prefer dual=False when n_samples > n_features.
C : float, optional (default=1.0)Inverse of regularization strength; must be a positive float. Like in support vector machines, smaller values specify stronger regularization.
fit_intercept : bool, default: TrueSpecifies if a constant (a.k.a. bias or intercept) should be added the decision function.
intercept_scaling : float, default: 1when self.fit_intercept is True, instance vector x becomes [x, self.intercept_scaling], i.e. a “synthetic” feature with constant value equals to intercept_scaling is appended to the instance vector. The intercept becomes intercept_scaling * synthetic feature weight Note! the synthetic feature weight is subject to l1/l2 regularization as all other features. To lessen the effect of regularization on synthetic feature weight (and therefore on the intercept) intercept_scaling has to be increased
class_weight : {dict, ‘auto’}, optional 考虑类不平衡,类似于代价敏感Over-/undersamples the samples of each class according to the given weights. If not given, all classes are supposed to have weight one. The ‘auto’ mode selects weights inversely proportional to class frequencies in the training set.
random_state: int seed, RandomState instance, or None (default) :The seed of the pseudo random number generator to use when shuffling the data.
tol: float, optional :Tolerance for stopping criteria.
Attributes:
`coef_` : array, shape = [n_classes, n_features]Coefficient of the features in the decision function.
coef_ is readonly property derived from raw_coef_ that follows the internal memory layout of liblinear.
`intercept_` : array, shape = [n_classes]Intercept (a.k.a. bias) added to the decision function. If fit_intercept is set to False, the intercept is set to zero.
LogisticRegression类中的方法有如下几种,我们常用的是fit和predict~
Methods
使用predict返回的就是测试样本的标记向量,其实个人觉得还应有LR分类器中的重要过程参数:权重向量,其size应该是和feature的个数相同。但是就没有这个方法,所以这就萌生了自己实现LR算法的念头,那样子就可以输出权重向量了。
一、什么是逻辑回归
机器学习算法三要素:模型、参数、目标函数。
1.模型
设X是连续随机变量,x服从logistic分布是指其具有下列分布函数和密度函数:
F(x)=P(x≤x)=11+e−(x−u)/γ
f(x)=F′(x)=e−(x−u)/γγ(1+e−(x−u)/γ)2
逻辑回归模型是如下的概率分布:
P(y=1|x)=e(w⋅x)1+e(w⋅x)
由此可看出:输出的y=1的对数几率是输入向量x的线性函数。
2.参数
逻辑回归的目的是求解w的最佳拟合参数,其求解过程由各类最优化算法实现。
3.目标函数
监督机器学习问题可总结为:“Minimize your error while regularizing your parameters”,正则化参数的同时最小化误差。
目标函数可归纳为如下形式:
第一项L为训练误差,第二项为正则化项(惩罚项)。第一项是为了最小化训练误差,得到最好的拟合数据,;第二项是为了简化模型,防止过拟合,得到更好的泛化能力。
二、调用sklearn中的LogisticRegression
调用sklearn逻辑回归算法十分简单:1.导入;2.fit()训练;3.predic()预测
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression()
clf.fit(train_feature,label)
predict['label'] = clf.predict(predict_feature)
但是其中参数设置才是关键的是sklearn.linear_model中LogisticRegression类的参数。默认参数如下:
class sklearn.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='liblinear', max_iter=100, multi_class='ovr', verbose=0, warm_start=False, n_jobs=1)penalty 惩罚项(str,有‘L1’、’L2’可选)
L1:向量中各元素绝对值的和。作用是产生少量的特征,而其他的特征都是0,常用于特征选择;
L2:向量中各个元素平方之和再开根号。作用是选择较多的特征,使他们都趋近于0;
C值(float,default=1.0)
目标函数的约束条件:s.t.||w||1
由此可看出 C值越小,则正则化强度越大。class_weight(dict or ‘balanced’, optional)
由于逻辑回归的学习方法有很多种:“liblinear”、“lbfgs” “newton-cg”“sag”,部分参数只有特定的方法中才有,所以大家可以用到的时候再查。
官方说明: