Logistic Regression as Neural Network
本周课程涉及到的知识点:
- Logistic regression 的基本结构
- Loss and cost function 定义
- Gradient descent 梯度下降算法
- Backward propagation 反向传播算法
Logistic regression 的基本结构
Logistic regression 可以认为是一种最简单的神经网络。我们以二元分类(binary classification)问题来说明它的具体结构:
我们需要解决的问题是输入一个图像,判断这个图像中是否包含一只猫。输出为1代表图像是一只猫,0则不是。为了解决这个问题,我们首先提取图像中所有的像素点,把它们放在一个向量 X 里。这个向量的维度是[64 * 64 * 3, 1], 其中64是像素点的个数,3 是因为每个像素点需要包含 RGB 三种颜色的信息。这个向量也即是我们的输入 X。随后我们首先对该输入向量做线性变换,得到 Z = W*X + b, 随后通过sigmoid方程 把结果转化为一个0, 1 之间的数。例如0.73, 因为0.73 > 0.5, 我们最后输出1, 也即认为图像中包含一只猫。
从上面的结构可以看出,logistic regression的目标则是给定一系列已经标记的图像(training dataset),通过不断的迭代调整参数(W, b)使得输出的判断结果(是猫或者不是猫)尽量准确。这个过程可以被概括成如下几步:
- 初始化模型结构,比如输入参数 X 的feature个数
- 初始化模型参数,比如 W 和 b
- 循环优化参数:
- 通过forward propagation计算cost function, 也即输出结果和真实结果之间的误差
- 通过backward propagation反过来计算cost function 对于W,b的梯度
- 用gradient descent来优化参数W, b,使得下一轮的判断更加准确
可见这个过程中有几个重要的部分:cost function的定义,forward propagation, backward propagation 以及 gradient descent。其中forward propagation就是根据输入 X 来计算最后的输出的过程,比较简单,这里不再多说,我们下面重点介绍一下其他的部分。
Loss and cost function 的定义
假设模型输出的结果是 y', 实际的真实结果是 y, 如何衡量输出值和真实值之间的差距呢?
我们用如下方式来定义loss function:
[图片上传失败...(image-846300-1511717383424)]=y\log(\hat{y})+(1-y)\log(1-\hat{y}))
直觉上来理解,当 y = 1 的时候 L = -log(y'), 为了尽量缩小 L, y' 应该尽量大,也即越靠近 1 越好。而 y = 0 的时候 L = -log(1 - y'), 可见 y' 越靠近1, L 就越小。这样就巧妙的把 y 和 y' 的取值对应了起来。 关于这个定义,有两点需要注意:
- 我们不用简单的 L = (y - y')^2 的方式来定义 loss, 主要原因是这个不能保证 L 是convex function,同样也就不能保证存在全局最优解。
- 这个loss function的来源其实是极大似然估计。解释如下:
假设 y' = P(y = 1|x), 那么一旦 y = 1 则 P(y | x) = y', 而一旦 y = 0 则 P(y | x) = 1 - y'. 这个关系可以被合并写成下式:
[图片上传失败...(image-af1ddf-1511717383424)]%20=%20\hat{y}y%20*%20(1%20-%20\hat{y}){1-y})
应用对数极大似然估计,我们对上式两边取对数,即可得到loss function的定义。关于极大似然估计的思想可以看这里。
注意loss function的定义是针对每个training data的,即对每个输入 X 我们都可以计算出一个loss value, 那么把m个training data的loss value取平均我们就得到了cost function的定义J:
[图片上传失败...(image-b8e501-1511717383424)]}\log(a{(i)})+(1-y{(i)})\log(1-a^{(i)}))
cost function非常重要,因为logistic regression的任务无非就是不断调整优化 W, b 参数使得cost function的值
J 最小化而已。至于如何做到,我们需要用到gradient descent算法。
Gradient descent 梯度下降算法
给定方程 J(W, b),如何才能找到合适的 W, b 值来使得 J 最小化呢?
为了简化问题,我们假定 J 只和 W 有关, 那么为了使 J 最小我们应该对 W 循环执行如下操作知道 J 收敛:
[图片上传失败...(image-456d84-1511717383424)]
其中 a 为 learning rate, dW 即 J 关于 W 求导 (dJ/dW)。关于为何这样可以最小化 J, 下图可谓一目了然:
我们每次都按照梯度 dW 的方向调整 W, 这样可以让 J 的值不断往谷底滑落直到最低点,因此这个算法被称为gradient descent(梯度下降)。
从后面的课程来看,这个看似简单算法实际上是neural network的核心。后面要提到的Adam optimization都是在最基本的gradient descent修改而来的。
Backward propagation 反向传播算法
为了应用梯度下降算法,我们首先要求得 J 对每个参数 W, b 的梯度 - 也即是backward propagation的作用。为了解释backward propagation, 我们先来看一下logistic regression的computation graph。
对于每个输入 X 和参数 w1,w2,b, 我们可以首先通过forward propagation计算 a 和 loss function. 现在的问题是如何计算dL/dw1
, dL/dw2
以及dL/db
。我们从后往前递推,首先计算dL/da = -y/a - (1-y)/(1-a)
, 随后计算dL/dz = dL/da * da/dz = a - y
。最后我们就可以计算得到dw1 = dL/dz * dz/dw1 = x1 * (a - y)
, dw2 = dL/dz * dz/dw2 = x2 * (a - y)
以及 db = dL/dz * dz/db = a - y
。
这解释了为何这个算法被称为 backward propagation, 因为其思路是从最后的 cost function 往后递推去计算 L 对每个参数的梯度, 这样做可以极大的降低计算复杂度。不然的话为了计算 dL/dw1
我们不得不先计算 dL/da
, da/dz
, dz/dw1
, 然后在计算dL/dw2
的时候又要重复计算dL/da
, da/dz
(除非我们把dL/da
, da/dz
的值缓存下来)。从后往前计算梯度则自然的避免了这些重复的计算过程。
最后,注意我们需要计算的是我们需要对m个training data计算反向梯度,也就是我们关心的其实是 dJ/dW
, dJ/db
, 这个可以通过下面两式求得:
[图片上传失败...(image-c1fa62-1511717383424)]^T)
[图片上传失败...(image-5b7905-1511717383424)]}-y^{(i)}))
总结
到这里我们已经可以构建一个基于logistic regression的最简单的分类器了。再概括一下,其思想无非是根据forward propagation计算输出以及cost function, 随后根据反向计算cost function对每个参数的梯度。最后根据梯度下降算法调整参数来使得cost function值降低,也即提高预测精度。其实deep neural network 的基本原理也无非就是这些,只不过层数加深以后输入参数的维度 W, b 变得更加复杂了而已。