逻辑回归算法梳理

这个暑假参加了DataWhale暑期学习-高级算法梳理的第八期,在整个学习的过程当中发现,无论之前看过多少次视频,翻过几遍书,对于知识的系统理解都不如自己好好梳理、推导并用文字把它记下来那么有效果。因此,虽然这一期并没有参加初级算法(线性回归、决策树、逻辑回归等)梳理的学习,但是一直有这个念想等得空的时候也把这些算法一起梳理一遍,加深理解。特别是决策树和逻辑回归,前者是后面bagging和boosting等各种集成算法的主要基学习器,后者在神经网络以及基于神经网络的各种深度学习算法发挥重要的基础作用,特别是各种优化算法,梯度下降、牛顿法等等,这些都是相通的。

本篇主要对逻辑回归进行梳理。

逻辑回归算法更为古老,可以追溯到19世纪早期,当时最初被用于对人口增长以及自催化的化学反应进行建模。并由Verhulst最终将以下方程命名为logistic function

W(t)=\Omega \frac{e^{\alpha+\beta \,t} }{1+e^{\alpha + \beta \,t} } \tag{1} \label{1}

从上述方程出发,做一些变换,人们抽象出另外一个被叫做sigmoid的函数,其图像如下:

LR

该函数有一个重要的性质,在后面的推导和优化当中会用到:

\tag{2} \label{2}

逻辑回归与线性回归的联系与区别

首先,两者都是属于线性模型的范畴。我们先来回顾以下线性回归:

给定数据集D={(x1,y1),(x2,y2),...,(xm,ym)}D=\{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\},其中xi=(xi1;xi2;xi3;...;xid)x_i=(x_{i1};x_{i2};x_{i3};...;x_{id})为由dd个属性所描述的示列,xix_ixx 在第 ii 个属性上面的取值,线性回归试图学习一个通过属性的线性组合来进行预测的函数,对于一个新的样本序列xN=(xN1;xN2;xN3;...;xNd)x_N=(x_N1;x_N2;x_N3;...;x_Nd),其对应的yNy_N是多少。需要学习的函数可表示如下:

f(\boldsymbol{x})=\theta_1x_1+\theta_2x_2+...+\theta_dx_d+b \tag{3} \label{3}

用向量表示可以写成:

f(\boldsymbol{x})=\boldsymbol{\theta^Tx}+b \tag{4} \label{4}

如果上述问题的yy是连续的,那么这是一个回归的问题,如果是非连续的,则是一个分类的问题。

如果对线性回归的预测目标yy做一些推广,比如yyxx之间不满足线性关系,但是lny\ln yxx之间满足线性关系,即将预测目标的对数作为θTx+b\boldsymbol{\theta^Tx}+b逼近的目标,即:

\ln y=\boldsymbol{\theta^Tx}+b \tag{5} \label{5}

这就是对数线性回归(log-linear regression),式(5)在形式上仍是线性回归,但是实质上试图让eθTx+be^{\boldsymbol{\theta^Tx}+b}来逼近yy,从输入空间到输入空间的映射,已然是一个非线性映射,具体如下图所示。

对数线性回归示意图

更为一般的情况,考虑单调可微函数g()g(\cdot),令

y=g^{-1}(\boldsymbol{\theta^Tx}+b) \tag{6} \label{6}

这样得到的模型称为广义线性模型(generalized linear model),其中函数g()g(\cdot)称为联系函数(link function)

到这里,我们发现线性回归虽然简单,但是通过选取不同的联系函数具备一定的扩展性,而我们本次介绍的主角——逻辑回归,主要用来对分类学习任务进行建模,和对数线性回归是一样的,也是广义线性模型的一种特例,只是选取了不同的联系函数。

为了这个特定的广义线性模型能够进行分类任务的学习,这个联系函数需要具备以下两个性质:

  • 单调可微
  • 将分类任务的真实yy与线性模型的预测值相联系

用在逻辑回归当中的联系函数正是我们前面介绍过的sigmoid函数的反函数。

逻辑回归的原理

为了便于区分,将sigmoid函数改写如下:

g(z)=\frac{1}{1+e^{-z} } \tag{7} \label{7}

定义域为(,+)(-\infty,+\infty),值域为[0, 1],导数表达式推导见式(2)。将sigmond函数作为联系函数的反函数g()g^-(\cdot)代入式(6)得到:

y=\frac{1}{1+e^{-(\boldsymbol{\theta^Tx}+b)} } \tag{8} \label{8}

将式(8)可以进一步变换成式(5)的形式,以便直观地看出逻辑回归所用的联系函数的形式,得到:

\ln{\frac{y}{1-y} }=\boldsymbol{\theta^Tx}+b \tag{9} \label{9}

显然,逻辑回归所用的联系函数表达式为lny1y\ln {\frac{y}{1-y} },通常我们把它称之为logit函数。

那么对于一个二分类问题,给定数据集D={(x1,y1),(x2,y2),...,(xm,ym)}D=\{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\},其中xRdx \in R^d是输入,y{0,1}y \in \{0,1\}是输出,θRdbR\theta \in R^d和 b \in R是待学习的参数,假设目标变量yy服从伯努利分布,则对于给定的输入实例xx,可以写出相应的条件概率P(y=1x)P(y=0x)P(y=1|x)和P(y=0|x)

P(y=1|x)=y=\frac{1}{1+e^{-(\boldsymbol{\theta^Tx}+b)} } \tag{10} \label{10}

P(y=0|x)=1-y=1-\frac{1}{1+e^{-(\boldsymbol{\theta^Tx}+b)} }=\frac{e^{-(\boldsymbol{\theta^Tx}+b)} }{1+e^{-(\boldsymbol{\theta^Tx}+b)} } \tag{11} \label{11}

逻辑回归随后会比较两个条件概率值的大小,然后将实例xx分到概率值较大的那一类。

因为y{0,1}y \in \{0,1\},通过观察,并令y=hθ(x)y=h_{\theta}(x),我们可以将式(10)和(11)合并为下式:

P(y|x,\theta)=h_{\theta}(x)^y(1-h_{\theta}(x))^{1-y} \tag{12} \label{12}

其中θ\boldsymbol{\theta}为模型参数,在输入当中增加一个维度,并令其为常量xi0=1x_{i0}=1,则θ0=b\theta_{0}=bθ1,θ2,θ3,...,θd\theta_1,\theta_2,\theta_3,...,\theta_d为原先的θ\boldsymbol{\theta},为了后续损失函数以及优化推导方便,下面用θ\boldsymbol{\theta}来表示模型参数。

逻辑回归损失函数推导及优化

在李航博士的《统计学习方法》一书中指出,损失函数(loss function)是用来估量你模型的预测值f(x)f(x)与真实值YY的不一致程度,它是一个非负实值函数,通常使用L(Y,f(x))L(Y,f(x))来表示,损失函数越小,模型的鲁棒性就越好。损失函数是经验风险函数的核心部分,也是 结构风险函数的重要组成部分。模型的结构风险函数包括了经验风险项和正则项,通常结构风险函数可以表示成如下式子:

\theta^*= \mathop{\arg\min}_{\theta}\frac{1}{M}\sum_{i=1}^M L(y_i,f(x_i,\theta))+\lambda\Phi(\theta) \tag{13} \label{13}

对于逻辑回归,其损失函数是log\log损失,也可以说是交叉熵损失,下面我们先来看看什么是交叉熵及相关的相对熵。

相对熵

决策树算法梳理一文当中已经接触到信息熵这个概念,那么什么是相对熵呢?

相对熵又称KL散度(Kullback-Leibler divergence),对于同一个随机变量XX的两个单独的概率分布P(X)P(X)Q(X)Q(X),我们可以用相对熵来衡量这两个分布之间的差异,对于离散随机变量可表示如下:

D_{KL}(P||Q)=\sum_{i=1}^m P(x_i)\log(\frac{P(x_i)}{Q(x_i)}) \tag{14} \label{14}

交叉熵

对式(14)变形可以得到:

\tag{15} \label{15}

式(15)右边的前一部分就是PP的信息熵,仅涉及数据的生成过程,与模型无关,在数据生成以后可以当作常量来看待,后面的一部分就是交叉熵,主要用来度量在给定的真实分布下,使用非真实分布所指定的策略消除系统的不确定性所需要付出的努力的大小。

在机器学习当中,交叉熵函数经常用来作为损失函数,因为最小化交叉熵等同于最小化相对熵,即最小化训练集真实分布P(X)P(X)与模型训练后分布Q(X)Q(X)之间的KL散度。

而最小化KL散度,通常可以作为对最大似然估计的一种解释,下面就使用最大似然估计来对逻辑回归的损失函数进行推导。

损失函数推导

所谓最大似然估计(MLE),就是利用已知的样本分布,找到最有可能(即最大概率)导致这种分布的参数值;或者说是什么样的参数才能使我们观测到目前这组数据的概率最大。使用MLE推导逻辑回归的loss function的过程如下。

根据公式(13),给定一定的样本之后,我们可以构造出似然函数,假定有mm个样本:

\tag{16} \label{16}

直接对上面的式子求导会不方便,为了便于计算,我们可以对似然函数取对数,经过化简可以得到下式的推导结果:

\tag{17} \label{17}

为了满足最小化风险理论,我们可以将MLE的思想转化为最小化风险理论,最大化似然函数其实就等价于最小化负的似然函数。如果我们将式(17)取反即可得到我们所要的损失函数:

J(\theta) =-\frac{1}{m}\sum_{i=1}^m [{y^{(i)} }\log h_{\theta}(x^{(i)})+(1-y^{(i)})\log(1-h_{\theta}(x^{(i)}))] \tag{18} \label{18}

需要注意的是,这里在损失函数前面乘以一个1m\frac{1}{m}是为了后续优化的时候方便,本身不会对结果造成什么影响。

损失函数优化

对式(18)进行极小化有比较多的方法,比较常见的有梯度下降法(Gradient descent),坐标轴下降法,牛顿法等。本文主要介绍的是梯度下降法的思想和优化步骤。

梯度下降法也叫最速下降法,要使用梯度下降法找到一个函数的局部最小值,必须向函数上当前点对应梯度(或者是近似梯度)的反方向的规定步长距离点进行迭代搜索。如果相反地向梯度正方向迭代进行搜索,则会接近函数的局部极大值点;这个过程则被称为梯度上升法。

梯度下降

回到逻辑回归,为了求解损失函数J(θ)J(\theta)最小时的参数θ\theta,基于梯度下降的思想,其迭代公式为:

\theta_j=\theta_{j-1}-\alpha \frac{\partial J(\theta)}{\partial \theta_j} \tag{19} \label{19}

其中α\alpha为步长,J(θ)θj\frac{\partial J(\theta)}{\partial \theta_j}为损失函数在θj\theta_j点的梯度。接下来看看如何对梯度进行推导。

在推导开始之前需要了解一些推导过程中需要用到的一些简单函数的导数和对数运算公式:

  • 简单函数的导数:

  • 对数运算公式:

基于对数运算公式(23)~(25)对式(18)进行化简:

\tag{26} \label{26}

然后利用简单函数的导数(20)~(22)及复合函数求导法则对式(26)对θj\theta_j求偏导,得到梯度如下:

\tag{27} \label{27}

忽略中间过程,得到逻辑回归损失函数的梯度为:

\frac{\partial}{\partial \theta_j} J(\theta)=\frac{1}{m}\sum_{i=1}^m (h_{\theta}(x)-y^{(i)})x_j^{(i)} \tag{28}\label{28}

参数θ\theta的迭代式子为:

\theta_{j}=\theta_{j-1}-\alpha \sum_{i=1}^m (h_{\theta}(x)-y^{(i)})x_j^{(i)} \tag{29}\label{29}

最优化算法并不限于梯度下降,还有:

上述优化算法中,BFGS与L-BFGS均由拟牛顿法引申出来,与梯度下降算法相比,其优点是:第一、不需要手动的选择步长;第二、比梯度下降算法快。但缺点是这些算法更加复杂,庆幸的是,在实践中,我们一般不用操心优化方法,大部分机器学习库都内置了各种逻辑回归的优化方法,在使用的时候选择相应的参数即可。

正则化

逻辑回归也会面临过拟合问题,所以我们也要考虑正则化,常见的有L1L_1正则化和L2L_2正则化。

逻辑回归的L1L_1正则化的损失函数表达式如下:

J(\theta) =-\frac{1}{m}\sum_{i=1}^m [{y^{(i)} }\log h_{\theta}(x^{(i)})+(1-y^{(i)})\log(1-h_{\theta}(x^{(i)}))]+\lambda|\theta_j| \tag{30} \label{30}

相比普通的逻辑回归损失函数,增加了L1L_1范数θj|\theta_j|做作为惩罚,超参数λ\lambda作为惩罚系数,调节惩罚项的大小。

逻辑回归的L1L_1正则化损失函数的优化方法常用的有坐标轴下降法和最小角回归法。

逻辑回归的L2L_2正则化损失函数表达式如下:

J(\theta) =-\frac{1}{m}\sum_{i=1}^m [{y^{(i)} }\log h_{\theta}(x^{(i)})+(1-y^{(i)})\log(1-h_{\theta}(x^{(i)}))]+\frac{\lambda}{2m}\sum_{j=1}^n{\theta_j}^2 \tag{31} \label{31}

其中超参数λ\lambda作为惩罚系数,调节惩罚项的大小,这里的超参数与L1L_1正则里面的超参数是不相同的。逻辑回归的L2L_2正则化损失函数的优化方法和普通的逻辑回归类似。

模型评估指标

分类问题

混淆矩阵

对于二分类问题,可将样例根据其真实类别与学习器预测类别的组合划分为真正例(True Positive)、假正例(False Positive)、真反例(True Negative)、假反例(False Negative)四种情形,令TP,FP,TN,FNTP,FP,TN,FN分别表示其对应的样例数,则显然有TP+FP+T+FN=样例总数TP+FP+T+FN=样例总数,分类结果的“混淆矩阵”(Confusion Matrix)如下:

Confusion Matrix

基于混淆矩阵,主要有以下指标:

  • 真正率(True Positive Rate,TPR):TPR=TPTP+FNTPR=\frac{TP}{TP+FN},即被预测为正的正样本数/正样本实际数
  • 假正率(False Positive Rate,FPR):FPR=FPFP+TNFPR=\frac{FP}{FP+TN},即被预测为正的负样本数/负样本实际数
  • 假负率(False Negative Rate,FNR):FNR=FNTP+FNFNR=\frac{FN}{TP+FN},即被预测为负的正样本数/正样本实际数
  • 真负率(True Negative Rate,TNR):TPR=TNFP+TNTPR=\frac{TN}{FP+TN},即被预测为负的负样本数/负样本实际数
  • 准确率(Accuracy):Accuracy=TP+TNTP+FN+FP+TNAccuracy=\frac{TP+TN}{TP+FN+FP+TN},即正确预测的正反例数/总数
  • 精确率(Precision):Precision=TPTP+FPPrecision=\frac{TP}{TP+FP},精确率容易和准确率被混为一谈。其实,精确率只是针对预测正确的正样本而不是所有预测正确的样本。表现为预测出是正的里面有多少真正是正的。可理解为查准率,即正确预测的正例数/预测正例总数
  • 召回率(Recall):Recall=TPTP+FNRecall=\frac{TP}{TP+FN},召回率表现出在实际正样本中,分类器能预测出多少。与真正率相等,可理解为查全率,即正确预测的正例数/实际正例总数

实际上,查准率和查全率是一对矛盾的度量。一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。一般我们还会用F1 Score,是精确率和召回率的调和值,更接近于两个数较小的那个,所以精确率和召回率接近时,F1 Score最大。计算表达式如下:

F1=\frac{2\times P \times R}{P+R}\tag{32}\label{32}

ROC曲线

对于二分类逻辑回归,SigmoidSigmoid函数输出的是一个(0,1)区间的数值,我们在据此对正负例进行界定的时候,通常会设一个阈值,大于阈值的为正类,小于阈值为负类。如果我们减小这个阀值,更多的样本会被识别为正类,提高正类的识别率,但同时也会使得更多的负类被错误识别为正类。为了直观表示这一现象,引入ROC。根据分类预测结果对样例进行排序,按此顺序逐个把样本作为正类预测,即按顺序逐个设置正负界定阈值,每次计算两个重要量的值,分别为作为横坐标的False Positive Rate(FPR假正率),作为纵坐标的True Positive Rate(TPR真正率),得到ROC空间中相应的点,最后将这些点连接起来就形成ROC curve。一般情况下,这个曲线都应该处于(0,0)和(1,1)连线的上方,如下图所示:

ROC Curve

ROC曲线中的四个点和一条线:

  • 点(0,1):即FPR=0, TPR=1,意味着FN=0且FP=0,将所有的样本都正确分类
  • 点(1,0):即FPR=1,TPR=0,最差分类器,避开了所有正确答案
  • 点(0,0):即FPR=TPR=0,FP=TP=0,分类器把每个实例都预测为负类
  • 点(1,1):分类器把每个实例都预测为正类
  • (0,0)和(1,1)连线:即随机分类的分类器

总之:ROC曲线越接近左上角,该分类器的性能越好。而且一般来说,如果ROC是光滑的,那么基本可以判断没有太大的过拟合。

AUC

AUC(Area Under Curve)被定义为ROC曲线下与坐标轴围成的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于(0,0)和(1,1)连线这条直线的上方,所以AUC的取值范围在0.5和1之间。AUC越接近1.0,检测方法真实性越高;等于0.5时,则相当于随机分类器,真实性最低,无应用价值。

AUC的统计学意义是随机挑选一个正样本以及一个负样本,分类器判定正样本的值高于负样本的概率就是 AUC 值。前面已经提到,AUC值(面积)越大的分类器,性能越好,如下图:

AUC

回归问题

均方误差(Mean Squared Error,MSE)

观测值与真值偏差的平方和与观测次数的比值:

MSE=\frac{1}{m}\sum_{i=1}^m(f_i-y_i)^2\tag{45}\label{45}

均方根误差(Root Mean Squard Error,RMSE)

标准差是方差的算术平方根。
标准误差是均方误差的算术平方根。
标准差是用来衡量一组数自身的离散程度,而均方根误差是用来衡量观测值同真值之间的偏差,它们的研究对象和研究目的不同,但是计算过程类似。

RMSE=\sqrt{\frac{1}{m}\sum_{i=1}^m(f_i-y_i)^2} \tag{46}\label{46}

它的意义在于开个根号后,误差的结果就与数据是一个级别的,可以更好地来描述数据。标准误差对一组测量中的特大或特小误差反映非常敏感,所以,标准误差能够很好地反映出测量的精密度。这正是标准误差在工程测量中广泛被采用的原因。

平均绝对误差(Mean Absolute Error,MAE)

平均绝对误差是绝对误差的平均值,能更好地反映预测值误差地实际情况。

MAE=\frac{1}{m}\sum_{i=1}^m|f_i-y_i|\tag{47}\label{47}

R-squared

R^2=1-\frac{\sum_{i=1}^m(f_i-y_i)^2}{\sum_{i=1}^m(\bar{y_i}-y_i)^2} \tag{48}\label{48}

上面分子就是我们训练出的模型预测的误差和。
下面分母就是瞎猜的误差和。(通常取观测值的平均值)

如果结果是0,就说明我们的模型跟瞎猜差不多。
如果结果是1。就说明我们模型无错误。

R2R^2介于0~1之间,越接近1,回归拟合效果越好,一般认为超过0.8的模型拟合优度比较高。

可以对式(48)进一步化简,分子分母同时除以mm,那么分子就变成了我们的均方误差MSEMSE,下面分母就变成了方差。

R^2=1-\frac{\frac{1}{m}\sum_{i=1}^m(f_i-y_i)^2}{\frac{1}{m}\sum_{i=1}^m(\bar{y_i}-y_i)^2} = 1-\frac{MSE(f,y)}{Var(y)}\tag{49}\label{49}

类别不平衡问题

前面介绍的分类学习方法都有一个共同的基本假设,即不同类别的训练样本数目相当。如果不同类别的训练样本数目稍有差别,通常影响不大,但是如果差别很大,则会对学习过程造成困挠。例如在医学的病情筛选案例当中,通常正样本极少,那么此时如果学习方法只需返回一个永远将新样本预测为负样本的模型,就能够达到非常高的精度,但是这样的模型往往没什么价值,因为它不能预测出任何正样本。

类别不平衡就是指分类任务中不同类别的训练样本数目差别很大的情况。不失一般性,我们假定正样本较少,负样本较多。为了便于理解,我们从线性分类器的角度进行讨论。

在用y=θTxy=\theta^T x对新样本进行分类时,事实上是在用预测出来的yy值与一个阈值进行比较,例如通常在y>0.5y>0.5时判断为正样本,否则为负。预测值实际上表达了正样本的可能性,几率y1y\frac{y}{1-y}则反映了正样本可能性与负样本可能性之比的值。阈值设置为0.5恰表明分类器认为真实正、负样本可能性相同,此时的决策规则如下:

若\frac{y}{1-y}>1\,\,则预测为正样本\tag{33}\label{33}

但是,当训练集中正负样本的数目不相同时,令m+m^+表示正样本数目,mm^-表示负样本数目,则观测几率m+m\frac{m^+}{m^-},如果假设训练集是真实样本的无偏采样,那么观测几率就代表了真实几率。于是,只要分类器的预测几率高于观测几率就应该判定为正样本,即:

若\frac{y}{1-y}>\frac{m^+}{m^-}\,\,则预测为正样本\tag{34}\label{34}

然后,我们的分类器是基于式(33)进行决策的,因此,需要对其预测值进行调整,使其在基于式(33)决策时,实际是在执行式(34)。要做到这一点很容易,只需要令:

\frac{y^{'} }{1-y^{'} }=\frac{y}{1-y}\times\frac{m^-}{m^+}\tag{35}\label{35}

这就是类别不平衡学习的一个基本策略——“再缩放”(Rescaling)。

再缩放的思想虽然简单,但实际操作却不平凡,主要因为”训练集是真实样本总体的无偏采样”这个假设通常不成立,换句话说,我们未必能够有效地基于训练集观测几率来推断出真实几率。

对此,现有技术大体上有三类做法:

  • 直接对训练集里面的负样本进行欠采样
  • 直接对训练集里面的正样本进行过采样
  • 直接基于原始训练集进行学习,在用训练好的分类器进行预测时,进行阈值移动,将式(35)嵌入到其决策过程中

推广到多元逻辑回归

前面几节我们的逻辑回归的模型和损失函数都局限于二元逻辑回归,实际上二元逻辑回归的模型和损失函数很容易推广到多元逻辑回归。比如总是认为某种类型为正值,其余为0值,这种方法为最常用的one-vs-rest,简称OvR.

另一种多元逻辑回归的方法是Many-vs-Many(MvM),它会选择一部分类别的样本和另一部分类别的样本来做逻辑回归二分类。最常用的是One-Vs-One(OvO)。OvO是MvM的特例。每次我们选择两类样本来做二元逻辑回归。

这里只介绍多元逻辑回归的softmax回归的一种特例推导:

首先回顾下二元逻辑回归。

P(y=1|x,\theta)=h_{\theta}(x)=\frac{1}{1+e^{-\theta^T x} }=\frac{e^{\theta^T x} }{1+e^{\theta^T x} }\tag{36}\label{36}

P(y=0|x,\theta)=1-h_{\theta}(x)=1-\frac{e^{\theta^T x} }{1+e^{\theta^T x} }=\frac{1}{1+e^{\theta^T x} }\tag{37}\label{37}

其中y{0,1}y \in\{0,1\},式(36)与(37)相除再取对数则有:

\log{\frac{P(y=1|x,\theta)}{P(y=0|x,\theta)} }={\theta^T x}\tag{38}\label{38}

如果我们要推广到多元逻辑回归,则模型要稍微做下扩展。

我们假设是KK元分类模型,即样本输出yy的取值为1,2,...,K1,2,...,K

根据二元逻辑回归的经验,我们会有相应的K1K-1个方程。

\tag not allowed in aligned environment\begin{aligned} \log{\frac{P(y=1|x,\theta)}{P(y=K|x,\theta)} } &= \theta_1^T x \tag{39} \\ \log{\frac{P(y=2|x,\theta)}{P(y=K|x,\theta)} } &= \theta_2^T x \tag{40} \\ &\vdots \\ \log{\frac{P(y=K-1|x,\theta)}{P(y=K|x,\theta)} } &= \theta_{K-1}^T x \tag{41} \end{aligned}

另外,所有概率之和为1,则有:

\sum_{i=1}^K P(y=i|x,\theta)=1\tag{42}\label{42}

最终得到KK个方程,里面有KK个逻辑回归的概率分布,解出这个KK元一次方程,得到KK元逻辑回归的概率分布如下:

P(y=kx,θ)={eθkTx1+t=1K1eθtTxk=1,2,...,K111+t=1K1eθtTxk=K(43)P(y=k|x,\theta) = \begin{cases} \dfrac{e^{\theta_k^T x}}{1+\sum_{t=1}^{K-1}e^{\theta_t^T x}} & k=1,2,...,K-1 \\[1em] \dfrac{1}{1+\sum_{t=1}^{K-1}e^{\theta_t^T x}} & k=K \end{cases} \tag{43}

多元逻辑回归的损失函数推导以及优化方法和二元逻辑回归类似,如果换一种归一化的方式,用1j=1keθjTx(i)\frac{1}{\sum_{j=1}^k {e^{\theta_j^T x^(i)} } }来对概率分布进行归一化,可以将函数hθ(x)h_\theta(x)写成下列形式,那么就很容易看出多元逻辑回归的损失函数形式及其推导过程了。另外,通常把这一类的多元逻辑回归叫做Softmax回归。

h_\theta(x^{(i)})= \left[ \right]= \frac{1}{\sum_{j=1}^k {e^{\theta_j^T x^(i)} } } \left[ \right] \tag{44} \label{44}

sklearn参数详解

sklearn当中一共有两个逻辑回归实现,不带交叉验证的LogisticRegression和带交叉验证的LogisticRegressionCV,以下区分进行介绍。

LogisticRegression

参数(Parameters)

  • penalty : str, ‘l1’, ‘l2’, ‘elasticnet’ or ‘none’, optional (default=’l2’)

    • 为了防止过拟合,指明惩罚项里面对应的范数,是L1还是L2又或者是Elasticnet,需要注意的是newton-cg、sag以及lbfgs优化器仅支持L2,saga仅支持Elasticnet。默认是L2,如果设置为none则不考虑正则
  • dual : bool, optional (default=False)

    • 对偶或者原始方法,用来指明是否将原问题改成他的对偶问题,对偶问题可以理解成相反问题,比如原问题是求解最大值的线性规划,那么他的对偶问题就是转化为求解最小值的线性规划,适用于样本较小的数据集,因样本小时,计算复杂度较低
  • tol : float, optional (default=1e-4)

    • 残差收敛条件,默认是0.0001,也就是只需要收敛的时候两步只差<0.0001就停止,可以设置更大或更小
  • C : float, optional (default=1.0)

    • 正则化系数,正则化强度的导数,必须是一个正数,值越小,正则化强度越大,即防止过拟合的程度更大
  • fit_intercept : bool, optional (default=True)

    • 是否将截距/方差加入到决策模型中,默认为True
  • intercept_scaling : float, optional (default=1)

    • 仅在采用liblinear求解器及fit_intercept设置为True时才可用,float类型,默认为1
  • class_weight : dict or ‘balanced’, optional (default=None)

    • class_weight是很重要的一个参数,是用来调节正负样本比例的,默认是值为None,也就是正负样本的权重是一样的,你可以以dict的形式给模型传入任意你认为合适的权重比,也可以直接指定一个值“balanced”,模型会根据正负样本的绝对数量比来设定模型最后结果的权重比,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9, 1:0.1},这样类型0的权重为90%,而类型1的权重为10%
  • random_state : int, RandomState instance or None, optional (default=None)

    • 随机种子的设置,默认是None,如果设置了随机种子,那么每次使用的训练集和测试集都是一样的,这样不管你运行多少次,最后的准确率都是一样的;如果没有设置,那么每次都是不同的训练集和测试集,最后得出的准确率也是不一样的
  • solver : str, {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}, optional (default=’liblinear’).

    • 优化问题当中所采用的算法
      • liblinear:默认采用的算法,采用坐标轴下降法来迭代优化损失函数,对于小数据集是个好的选择
      • lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
      • newton-cg:也是牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
      • sag:即随机梯度下降,是梯度下降的变种,是一种线性收敛算法,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于大样本量数据,提高迭代速递
      • saga:即随机平均梯度下降,也是梯度下降的变种

小结一下:newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear对L1正则化和L2正则化都适用,但是liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。同时,因sag每次仅仅使用了部分样本进行梯度迭代,所以当数据量较少时不宜选用,而当数据量很大时,sag是第一选择
Algorithm to use in the optimization problem.

  • max_iter : int, optional (default=100)

    • 算法收敛的最大迭代次数,即求取损失函数最小值的迭代次数,默认是100
  • multi_class : str, {‘ovr’, ‘multinomial’, ‘auto’}, optional (default=’ovr’)

    • 类方法参数选择,‘ovr’和‘multinomial’两个值可以选择,默认值为‘ovr’,如果分类问题是二分类问题,那么这两个参数的效果是一样的,主要体现在多分类问题上
  • verbose : int, optional (default=0)

    • 文意思是”冗余“,就是会输出一些模型运算过程中的东西(任务进程),默认是False,也就是不需要输出一些不重要的计算过程
  • warm_start : bool, optional (default=False)

    • 是否使用上次的模型结果作为初始化,默认是False,表示不使用
  • n_jobs : int or None, optional (default=None)

    • 并行运算数量(核的数量),默认为1,如果设置为-1,则表示将电脑的cpu全部用上
      Number of CPU cores used when parallelizing over classes if multi_class=’ovr’”. This parameter is ignored when the solver is set
  • l1_ratio : float or None, optional (default=None)

    • ElasticNet混合参数,仅在惩罚项是ElasticNet时才有用

属性(Attributes)

  • classes_ : array, shape (n_classes, )

    • 分类标签列表
  • coef_ : array, shape (1, n_features) or (n_classes, n_features)

    • 决策函数里面各个特征的系数,绝对值大小可以理解成特征重要性
  • intercept_ : array, shape (1,) or (n_classes,)

    • 决策函数当中的截距,相当于偏置,如果fit_intercept设置为False,则截距为0,二分类当中,截距为标量
  • n_iter_ : array, shape (n_classes,) or (1, )

    • 算法迭代次数

方法(Methods)

方法名称 方法解释
decision_function(self, X) Predict confidence scores for samples.
densify(self) Convert coefficient matrix to dense array format.
fit(self, X, y[, sample_weight]) Fit the model according to the given training data.
get_params(self[, deep]) Get parameters for this estimator.
predict(self, X) Predict class labels for samples in X.
predict_log_proba(self, X) Log of probability estimates.
predict_proba(self, X) Probability estimates.
score(self, X, y[, sample_weight]) Returns the mean accuracy on the given test data and labels.
set_params(self, **params) Set the parameters of this estimator.
sparsify(self) Convert coefficient matrix to sparse format.

LogisticRegressionCV

参数(Parameters)

  • Cs : list of floats or int, optional (default=10)

    • 正则化系数列表,正则化强度的导数,必须是一个正数,值越小,正则化强度越大,即防止过拟合的程度更大
  • cv : int or cross-validation generator, optional (default=None)

    • 在Stratified K-Folds中使用的默认CV生成器,如果提供的是一个正整数,那么就是CV的折数
  • scoring : string, callable, or None, optional (default=None)

    • CV时的评价指标,具体可以参考sklearn.metrics,默认采用accuracy
  • refit : bool, optional (default=True)

    • 如果设置True,scores会根据所有的folds进行求平均处理,然后用相对应于最佳score的模型参数进行重新拟合
  • penalty : str, ‘l1’, ‘l2’, ‘elasticnet’ or ‘none’, optional (default=’l2’)

    • 为了防止过拟合,指明惩罚项里面对应的范数,是L1还是L2又或者是Elasticnet,需要注意的是newton-cg、sag以及lbfgs优化器仅支持L2,saga仅支持Elasticnet。默认是L2,如果设置为none则不考虑正则
  • dual : bool, optional (default=False)

    • 对偶或者原始方法,用来指明是否将原问题改成他的对偶问题,对偶问题可以理解成相反问题,比如原问题是求解最大值的线性规划,那么他的对偶问题就是转化为求解最小值的线性规划,适用于样本较小的数据集,因样本小时,计算复杂度较低
  • tol : float, optional (default=1e-4)

    • 残差收敛条件,默认是0.0001,也就是只需要收敛的时候两步只差<0.0001就停止,可以设置更大或更小
  • fit_intercept : bool, optional (default=True)

    • 是否将截距/方差加入到决策模型中,默认为True
  • intercept_scaling : float, optional (default=1)

    • 仅在采用liblinear求解器及fit_intercept设置为True时才可用,float类型,默认为1
  • class_weight : dict or ‘balanced’, optional (default=None)

    • class_weight是很重要的一个参数,是用来调节正负样本比例的,默认是值为None,也就是正负样本的权重是一样的,你可以以dict的形式给模型传入任意你认为合适的权重比,也可以直接指定一个值“balanced”,模型会根据正负样本的绝对数量比来设定模型最后结果的权重比,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9, 1:0.1},这样类型0的权重为90%,而类型1的权重为10%
  • random_state : int, RandomState instance or None, optional (default=None)

    • 随机种子的设置,默认是None,如果设置了随机种子,那么每次使用的训练集和测试集都是一样的,这样不管你运行多少次,最后的准确率都是一样的;如果没有设置,那么每次都是不同的训练集和测试集,最后得出的准确率也是不一样的
  • solver : str, {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}, optional (default=’lbfgs’).

    • 优化问题当中所采用的算法
      • liblinear:采用坐标轴下降法来迭代优化损失函数,对于小数据集是个好的选择
      • lbfgs:默认采用的算法,拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
      • newton-cg:也是牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
      • sag:即随机梯度下降,是梯度下降的变种,是一种线性收敛算法,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于大样本量数据,提高迭代速递
      • saga:即随机平均梯度下降,也是梯度下降的变种

小结一下:newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear对L1正则化和L2正则化都适用,但是liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。同时,因sag每次仅仅使用了部分样本进行梯度迭代,所以当数据量较少时不宜选用,而当数据量很大时,sag是第一选择
Algorithm to use in the optimization problem.

  • max_iter : int, optional (default=100)

    • 算法收敛的最大迭代次数,即求取损失函数最小值的迭代次数,默认是100
  • multi_class : str, {‘ovr’, ‘multinomial’, ‘auto’}, optional (default=’ovr’)

    • 类方法参数选择,‘ovr’和‘multinomial’两个值可以选择,默认值为‘ovr’,如果分类问题是二分类问题,那么这两个参数的效果是一样的,主要体现在多分类问题上
  • verbose : int, optional (default=0)

    • 文意思是”冗余“,就是会输出一些模型运算过程中的东西(任务进程),默认是False,也就是不需要输出一些不重要的计算过程
  • n_jobs : int or None, optional (default=None)

    • 并行运算数量(核的数量),默认为1,如果设置为-1,则表示将电脑的cpu全部用上
      Number of CPU cores used when parallelizing over classes if multi_class=’ovr’”. This parameter is ignored when the solver is set
  • l1_ratio : float or None, optional (default=None)

    • ElasticNet混合参数,仅在惩罚项是ElasticNet时才有用

属性(Attributes)

  • classes_ : array, shape (n_classes, )

    • 分类标签列表
  • coef_ : array, shape (1, n_features) or (n_classes, n_features)

    • 决策函数里面各个特征的系数,绝对值大小可以理解成特征重要性
  • intercept_ : array, shape (1,) or (n_classes,)

    • 决策函数当中的截距,相当于偏置,如果fit_intercept设置为False,则截距为0,二分类当中,截距为标量
  • n_iter_ : array, shape (n_classes,) or (1, )

    • 算法迭代次数

方法(Methods)

方法名称 方法解释
decision_function(self, X) Predict confidence scores for samples.
densify(self) Convert coefficient matrix to dense array format.
fit(self, X, y[, sample_weight]) Fit the model according to the given training data.
get_params(self[, deep]) Get parameters for this estimator.
predict(self, X) Predict class labels for samples in X.
predict_log_proba(self, X) Log of probability estimates.
predict_proba(self, X) Probability estimates.
score(self, X, y[, sample_weight]) Returns the score using the scoring option on the given test data and labels.
set_params(self, **params) Set the parameters of this estimator.
sparsify(self) Convert coefficient matrix to sparse format.

逻辑回归案例分享

逻辑回归的应用场景很多,分类、排序等等,本质上,逻辑回归还是一个排序的模型。这里分享两个案例,一个是用逻辑回归构建评分卡,另外一个是Facebook发表的论文,利用GBDT+LR用于广告点击率预测。

信用评分卡

GBDT+LR论文

逻辑回归小结

优点

  • 模型清晰,背后的概率推导经得住推敲。
  • 输出值自然地落在0到1之间,并且有概率意义,本质上是一种期望
  • 参数代表每个特征对输出的影响,可解释性强
  • 实施简单,非常高效(计算量小、存储占用低),可以在大数据场景中使用
  • 可以使用online learning的方式更新轻松更新参数,不需要重新训练整个模型
  • 解决过拟合的方法很多,如L1、L2正则化
  • L2正则化就可以解决多重共线性问题
  • 支持多分类

缺点

  • 本质上是一个线性模型,特征之间交叉信息无法学习到
  • 特征空间很大时,性能不好
  • 容易欠拟合,精度不高

参考