逻辑斯蒂回归(对数几率回归)

二元分类与Logistic回归

逻辑斯蒂回归(周志华书中把他叫做对数几率回归)不是用于回归而是用于分类,是用来解决二分类的问题(Binary Classification)。以Andrew Ng课程中的例子为例,我们要训练出一个模型能够自动的判别照片中是否有猫。这里我们就可以将图片的向量化然后通过logistic回归进行分类。

模型

给定一张没有便签的图片,我们将其向量化,表示成XRnx,那么我们如何使用算法来区别照片中是否有猫呢?我们假设Logistic函数的参数是wRnx以及bR,则我们的输出值函数可以表示为:

ŷ =σ(wTx+b)

这里的σ表示Sigma函数,函数的图形如下:

逻辑斯蒂回归(对数几率回归)

损失函数和代价函数

我们的训练目标是在给定训练数据 (x(1),y(1)),...,(x(m),y(m)) 的情况下使得 yi^尽可能接近 y(i),而所谓的损失函数即是用于衡量预测结果与真实值之间的误差。最简单的损失函数定义方式为平方差损失:

L(ŷ ,y)=12(ŷ y)2

不过 Logistic 回归中我们并不倾向于使用这样的损失函数,因为其对于梯度下降并不友好,很多情况下会陷入非凸状态而只能得到局部最优解。这里我们将会使用如下的损失函数:
L(ŷ ,y)=(ylogŷ +(1y)log(1ŷ ))

我们的优化目标是希望损失函数值越小越好,这里我们考虑两个极端情况,当 y=1 时,损失函数值为 logŷ ;此时如果 ŷ =1,则损失函数为 0。反之如果 ŷ =0,则损失函数值趋近于无穷大。当 y=0 时,损失函数值为 log(1ŷ );如果 ŷ =1,则损失函数值也变得无穷大。这样我们可以将 Logistic 回归中总的代价函数定义为:
J(w,b)=1mi=1mL(y(i)^y(i))=1mi=1m[y(i)logy(i)^+(1y(i))log(1y(i)^)]

在深度学习的模型训练中我们常常会接触到损失函数(Loss Function)代价函数(Cost Function)的概念,其中损失函数代指单个训练用例的错误程度,而代价函数往往是整个训练集中所有训练用例的损失函数值的平均

梯度下降求解

Gradient descent 又叫 steepest descent,是利用一阶的梯度信息找到函数局部最优解的一种方法,也是机器学习里面最简单最常用的一种优化方法。它的思想很简单,要找最小值,我们只需要每一步都往下走(也就是每一步都可以让代价函数小一点),然后不断的走,那肯定能走到最小值的地方,例如下图所示:
逻辑斯蒂回归(对数几率回归)
参数 w 的更新公式为:

w:=wαdJ(w,b)dw

b:=bαdJ(w,b)db

其中 α 表示学习速率,即每次更新的 w 的步伐长度;当 w 大于最优解 w 时,导数大于0;即 dJ(w)dw 的值大于 0,那么 w 就会向更小的方向更新。反之当 w 小于最优解 w 时,导数小于 0,那么 w 就会向更大的方向更新。

随机梯度下降SGD(stochastic gradient descend)

梯度下降算法在每次更新回归系数的时候都需要遍历整个数据集(计算整个数据集的回归误差),该方法对小数据集尚可。但当遇到有数十亿样本和成千上万的特征时,就有点力不从心了,它的计算复杂度太高。改进的方法是一次仅用一个样本点(的回归误差)来更新回归系数。这个方法叫随机梯度下降算法。由于可以在新的样本到来的时候对分类器进行增量的更新(假设我们已经在数据库A上训练好一个分类器h了,那新来一个样本x。对非增量学习算法来说,我们需要把x和数据库A混在一起,组成新的数据库B,再重新训练新的分类器。但对增量学习算法,我们只需要用新样本x来更新已有分类器h的参数即可),所以它属于在线学习算法。与在线学习相对应,一次处理整个数据集的叫“批处理”。

Logistic 回归中的导数计算

我们在上文中讨论过 Logistic 回归的损失函数计算公式为:

z=wTx+bŷ =a=σ(z)L(a,y)=(ylog(a)+(1y)log(1a))

这里我们假设输入的特征向量维度为 2,即输入参数共有 x1,w1,x2,w2,b 这五个;可以推导出如下的计算图:
逻辑斯蒂回归(对数几率回归)

接下来我们要求出Lw1,w2和b的求导,要对w1,w2和b的求导就需要我们使用上面的链式法则来进行求导。首先我们反向求出 L 对于 a 的导数:

da=dL(a,y)da=ya+1y1a
然后继续反向求出 L 对于 z 的导数:
dz=dLdz=dL(a,y)dz=dLdadadz=(ya+1y1a)a(1a)=ay

a = Sigma(z)的导数为a(1-a)

然后我们最终求得:

dw1=dLdw1=dL(a,y,w1)dz=dLdadadzdzdw1=(ay)x1dw2=dLdw2=dL(a,y,w2)dz=dLdadadzdzdw2=(ay)x2db=dLdb=dL(a,y,b)dz=dLdadadzdzb=(ay)

依次类推求出最终的损失函数相较于原始参数的导数之后,根据如下公式进行参数更新:
w1:=w1αdw1w2:=w2αdw2b:=bαdb

接下来我们需要将对于单个用例的损失函数扩展到整个训练集的代价函数:

J(w,b)=1mi=1mL(a(i),y) a(i)=y(i)^=σ(z(i))=σ(wTx(i)+b)
我们可以对于某个权重参数 w1,其导数计算为:
J(w,b)w1=1mi=1mw1L(a(i),y(i))
完整的 Logistic 回归中某次训练的流程如下,这里仅假设特征向量的维度为 2:

逻辑斯蒂回归(对数几率回归)

量化操作

在上述的 m 个训练用例的 Logistic 回归中,每次训练我们需要进行两层循环,外层循环遍历所有的特征,内层循环遍历所有的训练用例;如果特征向量的维度或者训练用例非常多时,多层循环无疑会大大降低运行效率,因此我们使用向量化(Vectorization)操作来进行实际的训练。我们首先来讨论下何谓向量化操作。在 Logistic 回归中,我们需要计算 z=wTx+b,如果是非向量化的循环方式操作,我们可能会写出如下的代码:

z = 0
for i in range(n_x):
    z += w[i] * x[i]
z += b

而如果是向量化的操作,我们的代码则会简洁很多:

z = np.dot(w, x) + b

下面我们将上述的 Logistic 回归流程转化为向量化操作,其中输入数据可以变为 nx×m 的矩阵,即共有 m 个训练用例,每个用例的维度为 nx

Z=np.dot(WTX)+bA=[a(1),a(2),...,a(m)]=σ(z)
我们可以得到各个变量梯度计算公式为:
dZ=AY=[a(1)y(1),a(2)y(2)....]

db=1mi=1mdz(i)=1mnp.sum(dZ)

dW=1mXdZT=1m[x(i1)...x(im)  ] [dz(i)  ]=1m[ x(1)dz(1)+...+x(m)dz(m)  ] 

注:文章主要是整理Andrew Ng深度学习课程的资料

相关文章: