在我们上一次的课程中,我们简单地浏览了深度学习的大门。从如何通过神经网络预测房价开始,我们逐步探索了这一复杂且强大的工具。同时,我们也初步接触了三种主要的神经网络模型,并区分了两种不同类型的数据。你可能还记得,深度学习之所以在这几年逐渐盖过传统机器学习,是因为三个主要的推动力:更多的数据、更强大的计算力和不断进化的算法。今天,我们将从深度学习的入门点,逻辑回归开始,来逐步深化我们的理解。
二分类问题:
当我们提到逻辑回归时,我们通常是在谈论二分类问题。这就是说,我们的输出结果只有两种可能,通常是0和1。想象一下,你的电脑前有一堆图片,你需要告诉电脑哪些图片中有猫,哪些没有。在这种情境中,0就代表“没有猫”,而1则代表“有猫”。
就像下面这张图显示的那样,假设你手上有一张彩色的猫的图片,其分辨率是64x64像素,并且它有红、绿、蓝三个颜色通道。在神经网络的世界里,我们通常会把这样的图片“摊平”,变成一个长长的一维向量。具体来说,这张图片就会被转化为一个维度为12288x1的向量。若你有m张这样的图片,那么所有这些向量就可以形成一个12288xm的大矩阵。此外,每张图片是否有猫的信息(0或1)也会被整合成一个1xm的向量。
逻辑回归
逻辑回归是一种常用于解决二分类问题的方法。在逻辑回归中,我们的目标是预测一个事物属于某一类的概率,记作 h_hat。这个概率值的取值范围是[0,1]。
为了构建这个预测模型,我们使用线性方程并引入参数 w 和 b。其中,权重 w 的维度为 (nx, 1),而 b 是一个偏置项。因此,逻辑回归的线性预测值可以表示为:
y ^ = w T x + b \hat{y} = w^T x + b y^=wTx+b
但这样的线性预测可能得到任何实数值,而我们需要的输出是在 [0,1] 之间。为了达到这个目标,我们使用了一个叫做 Sigmoid 函数的工具,它可以将任何实数“压缩”到 [0,1] 的范围内。因此,完整的逻辑回归预测输出为:
y ^ = Sigmoid ( w T x + b ) \hat{y} = \text{Sigmoid}(w^T x + b) y^=Sigmoid(wTx+b)
其中,Sigmoid 函数定义为:
Sigmoid ( z ) = 1 1 + e − z \text{Sigmoid}(z) = \frac{1}{1 + e^{-z}} Sigmoid(z)=1+e−z1
观察Sigmoid函数的图像,你会看到一个S型的曲线。当z的值非常大时,Sigmoid函数的值趋近于1;而当z的值非常小或为负时,函数的值趋近于0。
更为有趣的是,Sigmoid函数的导数可以通过它自己来表示,这在计算时非常有用。它的导数为:
Sigmoid ′ ( z ) = Sigmoid ( z ) × ( 1 − Sigmoid ( z ) ) \text{Sigmoid}'(z) = \text{Sigmoid}(z) \times (1 - \text{Sigmoid}(z)) Sigmoid′(z)=Sigmoid(z)×(1−Sigmoid(z))
综上所述,通过结合线性方程和Sigmoid函数,逻辑回归可以有效地将输出限制在 [0,1] 的范围内,为我们提供了一个强大的二分类工具。
逻辑回归代价函数()
在逻辑回归中,参数w
和b
是我们需要学习的。为了找到这两个参数的最佳值,我们需要定义一个cost function。这个cost function与w
和b
相关,通过最小化它,我们可以找到最优的w
和b
。
对于m
个训练样本,我们用上标表示每个样本,例如
(
x
(
i
)
,
y
(
i
)
)
(x^{(i)}, y^{(i)})
(x(i),y(i)) 表示第i
个样本。
要定义所有m
个样本的cost function,首先考虑单个样本。我们期望每个样本的预测值
y
^
\hat{y}
y^ 与其真实值尽可能接近。可以用Loss function表示单个样本的cost function。尽管可以使用如下的平方错误(squared error):
L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 L(\hat{y},y) = \frac{1}{2} (\hat{y} - y)^2 L(y^,y)=21(y^−y)2
但是,我们通常不使用它作为逻辑回归的Loss function。原因是这个函数可能是非凸的,导致梯度下降可能会停在局部最小值,而不是全局最小值。为了避免这种情况,我们希望使用一个凸函数作为Loss function。基于此,我们选择以下Loss function:
L ( y ^ , y ) = − ( y log y ^ + ( 1 − y ) log ( 1 − y ^ ) ) L(\hat{y},y) = - (y \log \hat{y} + (1 - y) \log (1 - \hat{y})) L(y^,y)=−(ylogy^+(1−y)log(1−y^))
让我们来看这个函数的两种可能的情况:
-
当
y=1
时: L ( y ^ , y ) = − log y ^ L(\hat{y},y) = -\log \hat{y} L(y^,y)=−logy^。这意味着当 y ^ \hat{y} y^ 接近1时,loss是很小的,当 y ^ \hat{y} y^ 接近0时,loss会变得非常大。 -
当
y=0
时: L ( y ^ , y ) = − log ( 1 − y ^ ) L(\hat{y},y) = -\log (1 - \hat{y}) L(y^,y)=−log(1−y^)。这意味着当 y ^ \hat{y} y^ 接近0时,loss是很小的,当 y ^ \hat{y} y^ 接近1时,loss会变得非常大。
这个Loss function有效地衡量了预测值与真实值之间的差异,并且它是凸的。这只是对为什么使用这个Loss function的简要解释,更详细的理由和推导将在后面的课程中介绍。
现在,对于m
个样本,我们定义Cost function为所有样本的平均Loss。这个Cost function表示预测输出与真实输出之间的平均差异:
J ( w , b ) = − 1 m ∑ i = 1 m [ y ( i ) log y ^ ( i ) + ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) ] J(w,b) = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log \hat{y}^{(i)} + (1 - y^{(i)}) \log (1 - \hat{y}^{(i)}) \right] J(w,b)=−m1i=1∑m[y(i)logy^(i)+(1−y(i))log(1−y^(i))]
现在我们的目标是找到能够最小化这个Cost function的w
和b
值。
逻辑回归可以被视为一个只有一个神经元的简单神经网络,这也是为什么我们首先介绍它的原因。
4. Gradient Descent
现在我们已经有了Cost function的公式,下一步是使用梯度下降算法找到可以最小化这个函数的w
和b
。由于我们的Cost function是凸的,梯度下降会从一个随机的w
和b
值开始,然后在每次迭代中按照负梯度方向更新这些值,从而使Cost function逐渐接近其全局最小值。如下图所示。
在每次迭代中,w
和b
的更新公式如下:
w : = w − α ∂ J ( w , b ) ∂ w w := w - \alpha \frac{\partial J(w,b)}{\partial w} w:=w−α∂w∂J(w,b)
b : = b − α ∂ J ( w , b ) ∂ b b := b - \alpha \frac{\partial J(w,b)}{\partial b} b:=b−α∂b∂J(w,b)
其中,α
是学习率,它控制我们每次更新的步长。大的α
意味着我们每次都会走很大的一步,而小的α
意味着我们会走很小的步子。在代码中,我们通常用 dw
表示
∂
J
(
w
,
b
)
∂
w
\frac{\partial J(w,b)}{\partial w}
∂w∂J(w,b),用 db
表示
∂
J
(
w
,
b
)
∂
b
\frac{\partial J(w,b)}{\partial b}
∂b∂J(w,b)。
梯度下降
我们已经掌握了Cost function的表达式,接下来我们会采用梯度下降(Gradient Descent)算法,以计算出最佳的w和b,从而最小化m个训练样本的Cost function,即 J ( w , b ) J(w,b) J(w,b)。
由于 J ( w , b ) J(w,b) J(w,b)是凸函数(convex function),梯度下降算法的策略是首先随机选择一组w和b参数值。在每次迭代中,它都会沿着w和b的梯度(即偏导数)的反方向行进一小步,不断地调整w和b的值。随着每次迭代的w和b的更新, J ( w , b ) J(w,b) J(w,b)都会更接近其全局最小值。梯度下降的过程如下图所示。
在梯度下降算法中,每次迭代的更新规则为:
w : = w − α ∂ J ( w , b ) ∂ w w := w - \alpha \frac{\partial J(w,b)}{\partial w} w:=w−α∂w∂J(w,b)
b : = b − α ∂ J ( w , b ) ∂ b b := b - \alpha \frac{\partial J(w,b)}{\partial b} b:=b−α∂b∂J(w,b)
其中, α \alpha α是学习速率(learning rate),决定了梯度下降的步长。当 α \alpha α较大时,每次更新的步伐会更大;当 α \alpha α较小时,每次更新的步伐会更小。在代码中,我们通常使用dw来表示 ∂ J ( w , b ) ∂ w \frac{\partial J(w,b)}{\partial w} ∂w∂J(w,b),用db来表示 ∂ J ( w , b ) ∂ b \frac{\partial J(w,b)}{\partial b} ∂b∂J(w,b)。在微积分中, d f d x \frac{df}{dx} dxdf表示对一个变量求导,而 ∂ f ∂ x \frac{\partial f}{\partial x} ∂x∂f表示对多个变量中的某一个求偏导。
梯度下降算法确保在每次迭代中,w和b都朝向使 J ( w , b ) J(w,b) J(w,b)最小化的方向移动。其背后的数学原理是基于泰勒展开式的,可以参考我的另一篇博客:台湾大学林轩田机器学习基石课程学习笔记10 – Logistic Regression
导数
这部分内容为基础内容,是为了帮助那些对微积分和导数概念不太熟悉的同学。简单来说,梯度或导数可以视为函数的斜率。关于求导数的详细方法,这里不再深入讲解。
更多导数示例
Andrew给出了一些更为复杂的导数示例,这部分暂时略过。
计算图
神经网络的训练包括两个主要部分:正向传播(Forward Propagation)和反向传播(Back Propagation)。正向传播是从输入开始,经过神经网络计算得到预测输出的过程;而反向传播则从输出开始,计算参数w和b的梯度。接下来,我们将通过计算图(Computation graph)来更深入地理解这两个过程。
考虑一个简单的例子:假设Cost function为 J ( a , b , c ) = 3 ( a + b c ) J(a,b,c) = 3(a + bc) J(a,b,c)=3(a+bc),其中包含a、b和c三个变量。设u为bc,v为a+u,那么 J = 3 v J = 3v J=3v。其对应的计算图如下图所示。
设a=5,b=3,c=2,则u=bc=6,v=a+u=11,J=3v=33。在计算图中,从左到右的过程对应于神经网络或逻辑回归中的正向传播过程,从输入开始,通过权重运算计算得到Cost function。
8. 使用计算图求导数
在上一部分,我们讨论了计算图的正向传播,即如何基于输入参数进行计算。在这一部分,我们将讨论其反向传播。这意味着我们要计算输出相对于输入的偏导数。
首先,让我们回顾之前的计算图例子。我们有三个输入参数:a、b和c。
考虑到J对a的偏导数。从图上看,从右向左,J是v的函数,v又是a的函数。通过链式法则,我们可以得到:
∂
J
∂
a
=
∂
J
∂
v
×
∂
v
∂
a
=
3
×
1
=
3
\frac{\partial J}{\partial a} = \frac{\partial J}{\partial v} \times \frac{\partial v}{\partial a} = 3 \times 1 = 3
∂a∂J=∂v∂J×∂a∂v=3×1=3
如下图所示。
接着,考虑J对b的偏导数。再次从图上看,从右到左,J是v的函数,v是u的函数,u又是b的函数。所以:
∂
J
∂
b
=
∂
J
∂
v
×
∂
v
∂
u
×
∂
u
∂
b
=
3
×
1
×
c
=
3
×
1
×
2
=
6
\frac{\partial J}{\partial b} = \frac{\partial J}{\partial v} \times \frac{\partial v}{\partial u} \times \frac{\partial u}{\partial b} = 3 \times 1 \times c = 3 \times 1 \times 2 = 6
∂b∂J=∂v∂J×∂u∂v×∂b∂u=3×1×c=3×1×2=6
最后,考虑J对c的偏导数。根据图示,从右向左,J是v的函数,v是u的函数,u又是c的函数。所以:
∂
J
∂
c
=
∂
J
∂
v
×
∂
v
∂
u
×
∂
u
∂
c
=
3
×
1
×
b
=
3
×
1
×
3
=
9
\frac{\partial J}{\partial c} = \frac{\partial J}{\partial v} \times \frac{\partial v}{\partial u} \times \frac{\partial u}{\partial c} = 3 \times 1 \times b = 3 \times 1 \times 3 = 9
∂c∂J=∂v∂J×∂u∂v×∂c∂u=3×1×b=3×1×3=9
为了简化表示,我们可以使用da
、db
和dc
来分别表示J对a、b和c的偏导数。
9. 逻辑回归的梯度下降
接下来,我们将探讨逻辑回归中的梯度计算。首先,为了简化理解,考虑一个单独的样本。逻辑回归的损失函数可以表示为:
z
=
w
T
x
+
b
y
^
=
a
=
σ
(
z
)
L
(
a
,
y
)
=
−
(
y
log
(
a
)
+
(
1
−
y
)
log
(
1
−
a
)
)
z = w^T x + b \\ \hat{y} = a = \sigma(z) \\ L(a,y) = - \left( y \log(a) + (1 - y) \log(1 - a) \right)
z=wTx+by^=a=σ(z)L(a,y)=−(ylog(a)+(1−y)log(1−a))
正向传播过程相对简单。例如,如果输入样本x有两个特征
x
1
x_1
x1和
x
2
x_2
x2,并且相应的权重向量w也有两个维度
w
1
w_1
w1和
w
2
w_2
w2。那么,我们可以计算z如下:
z
=
w
1
x
1
+
w
2
x
2
+
b
z = w_1 x_1 + w_2 x_2 + b
z=w1x1+w2x2+b
如下图所示。
但是,关键在于如何计算损失函数相对于参数w和b的偏导数,也就是反向传播。我们可以这样进行推导:
∂
L
∂
a
=
−
y
a
+
1
−
y
1
−
a
∂
L
∂
z
=
a
−
y
\frac{\partial L}{\partial a} = - \frac{y}{a} + \frac{1 - y}{1 - a} \\ \frac{\partial L}{\partial z} = a - y
∂a∂L=−ay+1−a1−y∂z∂L=a−y
知道了
∂
L
∂
z
\frac{\partial L}{\partial z}
∂z∂L之后,我们可以继续求
w
1
w_1
w1、
w
2
w_2
w2和b的导数:
∂
L
∂
w
1
=
x
1
×
(
a
−
y
)
∂
L
∂
w
2
=
x
2
×
(
a
−
y
)
∂
L
∂
b
=
a
−
y
\frac{\partial L}{\partial w_1} = x_1 \times (a - y) \\ \frac{\partial L}{\partial w_2} = x_2 \times (a - y) \\ \frac{\partial L}{\partial b} = a - y
∂w1∂L=x1×(a−y)∂w2∂L=x2×(a−y)∂b∂L=a−y
最后,使用梯度下降算法更新参数:
w
1
:
=
w
1
−
α
∂
L
∂
w
1
w
2
:
=
w
2
−
α
∂
L
∂
w
2
b
:
=
b
−
α
∂
L
∂
b
w_1 := w_1 - \alpha \frac{\partial L}{\partial w_1} \\ w_2 := w_2 - \alpha \frac{\partial L}{\partial w_2} \\ b := b - \alpha \frac{\partial L}{\partial b}
w1:=w1−α∂w1∂Lw2:=w2−α∂w2∂Lb:=b−α∂b∂L
如下图所示。
10. 梯度下降在m个样本中的应用
在上一节中,我们讨论了如何对单一样本计算偏导和执行梯度下降。但当我们有m个样本时情况又如何呢?
首先,假设我们的模型预测为:
z ( i ) = w T x ( i ) + b z^{(i)} = w^T x^{(i)} + b z(i)=wTx(i)+b
然后通过sigmoid函数,我们得到:
y ^ ( i ) = a ( i ) = σ ( z ( i ) ) \hat{y}^{(i)} = a^{(i)} = \sigma(z^{(i)}) y^(i)=a(i)=σ(z(i))
我们的代价函数(也称为损失函数)为:
J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) = − 1 m ∑ i = 1 m [ y ( i ) log y ^ ( i ) + ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) ] J(w,b) = \frac{1}{m} \sum_{i=1}^{m} L(\hat{y}^{(i)}, y^{(i)}) = -\frac{1}{m} \sum_{i=1}^{m} [y^{(i)} \log \hat{y}^{(i)} + (1 - y^{(i)}) \log (1 - \hat{y}^{(i)})] J(w,b)=m1i=1∑mL(y^(i),y(i))=−m1i=1∑m[y(i)logy^(i)+(1−y(i))log(1−y^(i))]
为了计算w和b的偏导数,我们可以先计算每个样本的偏导数,然后取平均:
d
w
1
=
1
m
∑
i
=
1
m
x
1
(
i
)
(
a
(
i
)
−
y
(
i
)
)
dw_1 = \frac{1}{m} \sum_{i=1}^{m} x_1^{(i)} (a^{(i)} - y^{(i)})
dw1=m1i=1∑mx1(i)(a(i)−y(i))
d
w
2
=
1
m
∑
i
=
1
m
x
2
(
i
)
(
a
(
i
)
−
y
(
i
)
)
dw_2 = \frac{1}{m} \sum_{i=1}^{m} x_2^{(i)} (a^{(i)} - y^{(i)})
dw2=m1i=1∑mx2(i)(a(i)−y(i))
d
b
=
1
m
∑
i
=
1
m
(
a
(
i
)
−
y
(
i
)
)
db = \frac{1}{m} \sum_{i=1}^{m} (a^{(i)} - y^{(i)})
db=m1i=1∑m(a(i)−y(i))
使用这些偏导数,我们可以更新w和b:
J=0; dw1=0; dw2=0; db=0;
for i = 1 to m
z(i) = w * x(i) + b;
a(i) = sigmoid(z(i));
J += -[y(i) * log(a(i)) + (1 - y(i)) * log(1 - a(i))];
dz(i) = a(i) - y(i);
dw1 += x1(i) * dz(i);
dw2 += x2(i) * dz(i);
db += dz(i);
J /= m;
dw1 /= m;
dw2 /= m;
db /= m;
每次迭代后,我们根据梯度下降的原理来更新w和b:
w
1
:
=
w
1
−
α
d
w
1
w_1 := w_1 - \alpha dw_1
w1:=w1−αdw1
w
2
:
=
w
2
−
α
d
w
2
w_2 := w_2 - \alpha dw_2
w2:=w2−αdw2
b
:
=
b
−
α
d
b
b := b - \alpha db
b:=b−αdb
通过多次迭代,我们最终会得到最优的参数w和b。
但有一点很重要:为了提高计算效率,当我们的训练样本数量很大时,我们应尽量避免使用for循环。而是采用向量化的方法进行计算。关于向量化的更多内容,我们将在下一节中讨论。
11. 总结
这节课的内容主要围绕神经网络的基石——逻辑回归展开。我们从简单的二分类问题开始,例如图像识别,首先将多维输入x转换为特征向量,然后输出y仅有两个值{0,1}。接着,我们介绍了逻辑回归模型和它的代价函数。最重要的是,我们探讨了如何使用梯度下降法优化这些参数。通过计算图,我们深入了解了神经网络的前向传播和反向传播的过程。最后,我们将这些知识应用于逻辑回归,总结了如何找到最优参数w和b的过程。