吴恩达神经网络与深度学习章节笔记(一)——逻辑回归
- 1. 二元分类 (Binary Classification)
- 2. Logistic回归 (Logistic Regression)
- 3. Logistic回归损失函数 (Logistic Regression Cost Function)
- 4. 梯度下降法 (Gradient Descent)
- 5. 计算图 (Computation Graph)
- 6. 计算图的导数计算 (Derivatives with a Computation Graph)
- 7. Logistic回归的梯度下降法 (Logistic Regression Gradient Descent)
- 8. m m m个样本的梯度下降 (Gradient Descent on m m m examples)
- 9. 向量化 (Vectorization)
- 10. Logistic损失函数的解释 (Explanation of Logistic Regression Cost Function)
视频课程链接:
https://www.bilibili.com/video/BV1FT4y1E74V?
笔记参考链接:
https://blog.youkuaiyun.com/weixin_36815313/article/details/105728919
课程作业链接:
https://download.youkuaiyun.com/download/baoli8425/19821557?spm=1001.2014.3001.5503
1. 二元分类 (Binary Classification)
逻辑回归是一个用于二元分类(binary classification)的算法。以一张图片作为输入,如果识别为猫,则输出标签1。如果识别到不是猫,那么输出标签0。现在我们用字母
y
y
y来表示输出的结果。
一张图片在计算机中的表示方式类似于上图。一张图片由红、绿、蓝(RGB)三种颜色通道的矩阵构成,如果你的图片大小为
64
×
64
64\times64
64×64像素,那么你就有三个规模为
64
×
64
64\times64
64×64的矩阵,分别对应图片中红、绿、蓝三种像素的强度值。为简单起见,上图只用了规模为
5
×
4
5\times4
5×4的矩阵表示。
为了把这些像素值转换为特征向量
x
x
x,首先定义一个特征向量
x
x
x来表示这张图片,我们把所有的像素都取出来,例如255、231等等,直到取完所有红色通道的像素,接着最后是255、134、…、255、134等等,直到得到一个特征向量,把图片中所有的红、绿、蓝像素值都列出来。如果图片的大小为
64
×
64
64\times64
64×64像素,那么向量
x
x
x的总维度将是
n
=
n
x
=
64
×
64
×
3
=
12288
n=n_x=64\times64\times3=12288
n=nx=64×64×3=12288,即三个像素矩阵中像素的总量。
所以在二元分类问题中,我们的目标就是得到一个分类器,它以图片的特征向量作为输入,然后预测输出结果
y
\pmb{y}
yyy为1还是0,也就是预测图片中是否有猫。
2. Logistic回归 (Logistic Regression)
对于二元分类问题来讲,给定一个输入特征向量
X
X
X,它可能对应一张图片,你想识别这张图片识别看它是否是一只猫或者不是一只猫的图片,你想要一个算法能够输出预测,你只能称之为
y
^
\hat{y}
y^,也就是你对实际值
y
y
y的估计。
X
X
X是一个
n
x
n_x
nx维的向量(相当于有
n
x
n_x
nx个特征的特征向量)。我们用
w
w
w表示逻辑回归的参数,这也是一个
n
x
n_x
nx维向量(因为
w
w
w实际上是特征权重,维度与特征向量相同),参数里面还有
b
b
b,这是一个实数,表示偏差。因此给出输入
x
x
x以及参数
w
w
w和
b
b
b之后,我们可以使用
y
^
=
w
T
x
+
b
\hat{y}=w^Tx+b
y^=wTx+b表达预测值。
但是这对于二元分类问题来讲不是一个非常好的算法,因为你想让
y
^
\hat{y}
y^表示实际值
y
y
y等于1的机率的话,
y
^
\pmb{\hat{y}}
y^y^y^应该在0到1之间。这是一个需要解决的问题,因为
w
T
x
+
b
w^Tx+b
wTx+b可能比1要大得多,或者甚至为一个负值。对于你想要的在0和1之间的概率来说它是没有意义的,因此在逻辑回归中,我们的输出
y
^
\hat{y}
y^应该是等于由上面得到的线性函数式子作为自变量的sigmoid函数中,公式如上图最下面所示,将线性函数转换为非线性函数。
下图是sigmoid函数的图像,如果我把水平轴作为z轴,那么关于
z
z
z的sigmoid函数是这样的,它是平滑地从0走向1,曲线与纵轴相交的截距是0.5,这就是关于的sigmoid函数的图像。我们通常都使用z来表示
w
T
x
+
b
w^Tx+b
wTx+b的值。
在这里
z
z
z是一个实数,这里要说明一些要注意的事情,如果
z
z
z非常大那么
e
−
z
e^{-z}
e−z将会接近于0,关于
z
z
z的sigmoid函数将会近似等于1除以1加上某个非常接近于0的项,因为
e
e
e的指数如果是个绝对值很大的负数的话,这项将会接近于0,所以如果
z
z
z很大的话那么关于
z
z
z的sigmoid函数会非常接近1。相反地,如果
z
z
z非常小或者说是一个绝对值很大的负数,那么关于
e
−
z
e^{-z}
e−z这项会变成一个很大的数,你可以认为这是1除以1加上一个非常非常大的数,所以这个就接近于0。实际上你看到当z变成一个绝对值很大的负数,关于
z
z
z的sigmoid函数就会非常接近于0。因此当你实现逻辑回归时,你的工作就是去让机器学习参数
w
w
w以及
b
b
b这样才使得
y
^
\hat{y}
y^成为对
y
=
1
y = 1
y=1这一情况的概率的一个很好的估计。
为了训练逻辑回归模型的参数
w
\pmb{w}
www和参数
b
\pmb{b}
bbb ,我们需要一个代价函数,通过训练代价函数来得到参数
w
\pmb{w}
www和参数
b
\pmb{b}
bbb。
3. Logistic回归损失函数 (Logistic Regression Cost Function)
为了让模型通过学习调整参数,你需要给予一个
m
m
m样本的训练集,这会让你在训练集上找到参数
w
w
w和参数
b
b
b,来得到你的输出。对训练集的预测值
y
^
\pmb{\hat{y}}
y^y^y^,我们更希望它会接近于训练集中的
y
\pmb{y}
yyy值。 训练样本
i
i
i所对应的预测值是
y
(
i
)
y(i)
y(i),是用训练样本的然后通过sigmoid函数来得到,也可以定义为
z
z
z,我们将使用这个符号
(
i
)
(i)
(i)注解,上标
(
i
)
(i)
(i)来指明数据表示
x
x
x或者
y
y
y或者
z
z
z或者其他数据的第
i
i
i个训练样本,这就是上标
(
i
)
(i)
(i)的含义。
损失函数又叫做误差函数,用来衡量预测输出值和实际值有多接近,Loss function:
L
(
y
^
,
y
)
L(\hat{y},y)
L(y^,y)。一般我们用预测值和实际值的平方差或者它们平方差的一半,但是通常在逻辑回归中我们不这么做,因为当我们在学习逻辑回归参数的时候,会发现我们的优化目标不是凸优化,只能找到多个局部最优值,梯度下降法很可能找不到全局最优值。
我们在逻辑回归中用到的损失函数是:
(1)当
y
y
y = 1时损失函数
L
=
−
l
o
g
(
y
^
)
L = − log( \hat{y} )
L=−log(y^),如果想要损失函数
L
L
L尽可能得小,那么
y
^
\hat{y}
y^就要尽可能大,因为sigmoid函数取值[0,1],所以
y
^
\hat{y}
y^会无限接近于1。
(2)当
y
y
y = 0时损失函数
L
=
−
l
o
g
(
1
−
y
^
)
L = − log( 1 − \hat{y} )
L=−log(1−y^),如果想要损失函数
L
L
L尽可能得小,那么
y
^
\hat{y}
y^就要尽可能小,因为sigmoid函数取值[0,1],所以
y
^
\hat{y}
y^会无限接近于0。
损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,算法的代价函数是对
m
\pmb{m}
mmm个样本的损失函数求和然后除以
m
\pmb{m}
mmm:
损失函数只适用于像这样的单个训练样本,而代价函数是参数的总代价,所以在训练逻辑回归模型时候,我们需要找到合适的 w \pmb{w} www和 b \pmb{b} bbb,来让代价函数 J \pmb{J} JJJ的总代价降到最低。根据我们对逻辑回归算法的推导及对单个样本的损失函数的推导和针对算法所选用参数的总代价函数的推导,结果表明逻辑回归可以看做是一个非常小的神经网络。
4. 梯度下降法 (Gradient Descent)
4.1 多维空间
在这个图中,横轴表示空间参数
w
w
w和
b
b
b,实际上,
w
w
w可以是更高的维度,但是为了更好地绘图,我们定义
w
w
w和
b
b
b,都是单一实数,代价函数(成本函数)
J
(
w
,
b
)
J (w,b)
J(w,b)是在水平轴
w
w
w和
b
b
b上的曲面,因此曲面的高度就是
J
(
w
,
b
)
J(w,b)
J(w,b)在某一点的函数值。我们所要做的就是找到使得代价函数(成本函数)
J
(
w
,
b
)
\pmb{J (w,b)}
J(w,b)J(w,b)J(w,b)函数值是最小值,对应的参数
w
\pmb{w}
www和
b
\pmb{b}
bbb。
如上图,代价函数(成本函数)
J
(
w
,
b
)
J(w,b)
J(w,b)是一个凸函数(convex function)。
如上图,它是非凸的并且有很多不同的局部最小值。由于逻辑回归的代价函数(成本函数)
J
(
w
,
b
)
J(w,b)
J(w,b)特性,我们必须定义代价函数(成本函数)
J
(
w
,
b
)
\pmb{J(w,b)}
J(w,b)J(w,b)J(w,b)为凸函数。
通过以下的三个步骤我们可以找到全局最优解,也就是代价函数(成本函数)
J
(
w
,
b
)
J(w,b)
J(w,b)这个凸函数的最小值点。
(1)初始化参数
w
\pmb{w}
www和
b
\pmb{b}
bbb,可以采用随机初始化的方法。对于逻辑回归几乎所有的初始化方法都有效,因为函数是凸函数;
(2)朝最陡的下坡方向走一步,我们可能停在这里也有可能继续朝最陡的下坡方向再走一步;
(3)直到走到全局最优解或者接近全局最优解的地方。
4.2 二维空间
假设代价函数(成本函数)
J
(
w
)
J(w)
J(w)只有一个参数
w
w
w,即用一维曲线代替多维曲线。
w
:
=
w
−
α
d
J
(
w
)
d
w
w:=w-\alpha\frac{dJ(w)}{dw}
w:=w−αdwdJ(w)其中:=表示更新参数,
α
\alpha
α表示学习率(learning rate),用来控制步长(step),则向下走一步的长度
d
J
(
w
)
d
w
\frac{dJ(w)}{dw}
dwdJ(w),就是函数
J
(
w
)
J(w)
J(w)对
w
w
w求导(derivative),在Python代码中我们会使用
d
w
dw
dw表示这个结果。
对于导数更加形象化的理解就是斜率(slope),如上图该点的导数就是这个点相切于
J
(
w
)
J(w)
J(w)的小三角形的高除宽。假设我们以如图点为初始化点,该点处的斜率的符号是正的,即
d
J
(
w
)
d
w
>
0
\frac{dJ(w)}{dw}>0
dwdJ(w)>0,因此根据公式
w
w
w会逐步递减,即向左走一步。
如上图,整个梯度下降法的迭代过程就是不断地向左走,直至逼近最小值点。
假设我们以上图中的点为初始化点,该点处的斜率的符号是负的,即
d
J
(
w
)
d
w
<
0
\frac{dJ(w)}{dw}<0
dwdJ(w)<0,因此根据公式
w
w
w会逐步递增,即向右走一步。
如上图,整个梯度下降法的迭代过程就是不断地向右走,即朝着最小值点方向走。
因此扩展到两个参数的情况下,逻辑回归的代价函数(成本函数)
J
(
w
,
b
)
J(w,b)
J(w,b):
其中,
∂
\partial
∂表示求偏导符号,可以读作
r
o
u
n
d
round
round,
∂
J
(
w
,
b
)
∂
w
\frac{\partial J(w,b)}{\partial w}
∂w∂J(w,b)就是函数
J
(
w
,
b
)
J(w,b)
J(w,b)对
w
w
w求偏导,在代码中我们会使用
d
w
dw
dw表示这个结果;
∂
J
(
w
,
b
)
∂
b
\frac{\partial J(w,b)}{\partial b}
∂b∂J(w,b)就是函数
J
(
w
,
b
)
J(w,b)
J(w,b)对
b
b
b求偏导,在代码中我们会使用
d
b
db
db表示这个结果。
小写字母
d
d
d用在求导数(derivative),即函数只有一个参数, 偏导数符号
∂
\partial
∂用在求偏导(partial derivative),即函数含有两个以上的参数。
5. 计算图 (Computation Graph)
可以说,一个神经网络的计算,都是按照前向或反向传播过程组织的。首先我们计算出一个新的网络的输出(前向过程),紧接着进行一个反向传输操作。后者我们用来计算出对应的梯度或导数。计算图解释了为什么我们用这种方式组织这些计算过程。
举例说明,我们尝试计算函数
J
(
a
,
b
,
c
)
=
3
∗
(
a
+
b
∗
c
)
J(a,b,c)=3*(a+b*c)
J(a,b,c)=3∗(a+b∗c),这个函数由三个变量
a
,
b
,
c
a,b,c
a,b,c组成。计算这个函数实际上有三个不同的步骤:
(1)首先是计算
u
=
b
∗
c
u=b*c
u=b∗c;
(2)然后计算
v
=
a
+
u
v=a+u
v=a+u;
(3)最后输出
J
=
3
∗
v
J=3*v
J=3∗v,这就是要计算的函数
J
J
J。
我们可以把这三步画成如下的计算图。
6. 计算图的导数计算 (Derivatives with a Computation Graph)
6.1 导数计算
为了计算导数,从右到左(红色箭头)的过程是用于计算导数最自然的方式。
根据导数计算可知
d
J
d
v
=
3
\frac{dJ}{dv}=3
dvdJ=3,这样我们就完成了第一步反向传播。
对于第二个方框中的
a
a
a和
u
u
u,可对其求导得到
d
v
d
a
=
1
\frac{dv}{da}=1
dadv=1,
d
v
d
u
=
1
\frac{dv}{du}=1
dudv=1。根据多元微积分计算的链式法则,可得
d
J
d
u
=
d
J
d
v
∗
d
v
d
u
=
3
∗
1
=
3
\frac{dJ}{du}=\frac{dJ}{dv}*\frac{dv}{du}=3*1=3
dudJ=dvdJ∗dudv=3∗1=3,
d
J
d
a
=
d
J
d
v
∗
d
v
d
a
=
3
∗
1
=
3
\frac{dJ}{da}=\frac{dJ}{dv}*\frac{dv}{da}=3*1=3
dadJ=dvdJ∗dadv=3∗1=3,这样就完成了另一个反向传播。
对于第三个方框中的
b
b
b和
c
c
c,对其求导可得
d
u
d
b
=
c
=
2
\frac{du}{db}=c=2
dbdu=c=2,
d
v
d
c
=
b
=
3
\frac{dv}{dc}=b=3
dcdv=b=3,因此根据链式法则可得
d
J
d
b
=
d
J
d
v
∗
d
v
d
u
∗
d
u
d
b
=
3
∗
1
∗
2
=
6
\frac{dJ}{db}=\frac{dJ}{dv}*\frac{dv}{du}*\frac{du}{db}=3*1*2=6
dbdJ=dvdJ∗dudv∗dbdu=3∗1∗2=6,
d
J
d
c
=
d
J
d
v
∗
d
v
d
u
∗
d
u
d
c
=
3
∗
1
∗
3
=
9
\frac{dJ}{dc}=\frac{dJ}{dv}*\frac{dv}{du}*\frac{du}{dc}=3*1*3=9
dcdJ=dvdJ∗dudv∗dcdu=3∗1∗3=9,这样就完成了最后两个反向传播。
6.2 符号约定
在Python中,可用变量名
d
F
i
n
a
l
O
u
t
p
u
t
v
a
r
_
d
v
a
r
dFinalOutputvar\_dvar
dFinalOutputvar_dvar来表示导数
d
F
i
n
a
l
O
u
t
p
u
t
v
a
r
d
v
a
r
\frac{dFinalOutputvar}{dvar}
dvardFinalOutputvar,但这样子变量名太长。由于在反向传播计算中,始终是对最终输出变量
F
i
n
a
l
O
u
t
p
u
t
v
a
r
FinalOutputvar
FinalOutputvar求导,因此可以简化使用变量名
d
v
a
r
dvar
dvar,来表示那个量。
在上述例子中,可作如下定义:
- Python代码中的变量名 d v dv dv,代表 d J d v \frac{dJ}{dv} dvdJ。
- Python代码中的变量名 d u du du,代表 d J d u \frac{dJ}{du} dudJ。
- Python代码中的变量名 d a da da,代表 d J d a \frac{dJ}{da} dadJ。
- Python代码中的变量名 d b db db,代表 d J d b \frac{dJ}{db} dbdJ。
- Python代码中的变量名 d c dc dc,代表 d J d c \frac{dJ}{dc} dcdJ。
7. Logistic回归的梯度下降法 (Logistic Regression Gradient Descent)
7.1 前向过程
假设样本只有两个特征
x
1
x_1
x1和
x
2
x_2
x2,为了计算
z
z
z,我们需要输入参数
w
1
w_1
w1、
w
2
w_2
w2和
b
b
b,除此之外还有特征值
x
1
x_1
x1和
x
2
x_2
x2。因此
z
z
z的计算公式为:
z
=
w
1
x
1
+
w
2
x
2
+
b
z=w_1x_1+w_2x_2+b
z=w1x1+w2x2+b逻辑回归的公式定义如下:
y
^
=
a
=
σ
(
z
)
\hat{y}=a=\sigma(z)
y^=a=σ(z)其中
z
=
w
T
+
b
z = w^T+b
z=wT+b,
σ
(
z
)
=
1
1
+
e
−
z
\sigma(z)=\frac{1}{1+e^{-z}}
σ(z)=1+e−z1
因此损失函数:
L
(
y
^
(
i
)
,
y
(
i
)
)
=
−
y
(
i
)
log
y
^
(
i
)
−
(
1
−
y
(
i
)
)
log
(
1
−
y
^
(
i
)
)
L(\hat{y}^{(i)},y^{(i)})=-y^{(i)}\log\hat{y}^{(i)}-(1-y^{(i)})\log(1-\hat{y}^{(i)})
L(y^(i),y(i))=−y(i)logy^(i)−(1−y(i))log(1−y^(i))代价函数:
J
(
w
,
b
)
=
1
m
∑
i
m
L
(
y
^
(
i
)
,
y
(
i
)
)
J(w,b)=\frac1m\sum_i^mL(\hat{y}^{(i)},y^{(i)})
J(w,b)=m1i∑mL(y^(i),y(i))假设现在只考虑单个样本的情况,单个样本的损失函数定义如下:
L
(
a
,
y
)
=
−
(
y
log
(
a
)
+
(
1
−
y
)
log
(
1
−
a
)
)
L(a,y)=-(y\log(a)+(1-y)\log(1-a))
L(a,y)=−(ylog(a)+(1−y)log(1−a))其中
a
a
a是逻辑回归的输出,
y
y
y是样本的标签值。现在让我们画出表示这个计算的计算图。
因此,为了使得逻辑回归中最小化代价函数 L ( a , y ) L(a,y) L(a,y),我们需要做的仅仅是修改参数 w w w和 b b b的值。
7.2 反向过程
首先我们需要反向计算出代价函数 L ( a , y ) L(a,y) L(a,y)关于 a a a的导数,根据微积分计算可得: d a = d L ( a , y ) d a = − y a + 1 − y 1 − a da=\frac{dL(a,y)}{da}=\frac{-y}{a}+\frac{1-y}{1-a} da=dadL(a,y)=a−y+1−a1−y接下来再反向一步,计算代价函数 L L L关于 z z z的导数 d L ( a , y ) d z \frac{dL(a,y)}{dz} dzdL(a,y),根据微积分计算可得: d z = d L ( a , y ) d z = d L d z = ( d L d a ) ⋅ ( d a d z ) = ( − y a + 1 − y 1 − a ) ⋅ a ( 1 − a ) = a − y dz=\frac{dL(a,y)}{dz}=\frac{dL}{dz}=(\frac{dL}{da})⋅(\frac{da}{dz})=(\frac{-y}{a}+\frac{1-y}{1-a})⋅a(1-a)=a-y dz=dzdL(a,y)=dzdL=(dadL)⋅(dzda)=(a−y+1−a1−y)⋅a(1−a)=a−y现在进行最后一步反向推导,也就是计算 w w w和 b b b变化对代价函数 L L L的影响。其中, d w 1 = ∂ L ∂ w 1 = ( ∂ L ∂ a ) ⋅ ( ∂ a ∂ z ) ⋅ ( ∂ z ∂ w 1 ) = x 1 ⋅ d z dw_1=\frac{\partial L}{\partial w_1}=(\frac{\partial L}{\partial a})\cdot(\frac{\partial a}{\partial z})\cdot(\frac{\partial z}{\partial w_1})=x_1\cdot dz dw1=∂w1∂L=(∂a∂L)⋅(∂z∂a)⋅(∂w1∂z)=x1⋅dz d w 2 = ∂ L ∂ w 2 = ( ∂ L ∂ a ) ⋅ ( ∂ a ∂ z ) ⋅ ( ∂ z ∂ w 2 ) = x 2 ⋅ d z dw_2=\frac{\partial L}{\partial w_2}=(\frac{\partial L}{\partial a})\cdot(\frac{\partial a}{\partial z})\cdot(\frac{\partial z}{\partial w_2})=x_2\cdot dz dw2=∂w2∂L=(∂a∂L)⋅(∂z∂a)⋅(∂w2∂z)=x2⋅dz d b = d z db=dz db=dz 因此,对于单个样本的梯度下降算法,需要做如下事情:
- 根据公式 d z = ( a − y ) ⋅ d z = ( a − y ) dz=(a-y)\cdot dz=(a−y) dz=(a−y)⋅dz=(a−y)计算 d z dz dz,根据公式 d w 1 = x 1 ⋅ d z dw_1=x_1 \cdot dz dw1=x1⋅dz计算 d w 1 dw_1 dw1, 根据公式 d w 2 = x 2 ⋅ d z dw_2=x_2 \cdot dz dw2=x2⋅dz计算 d w 2 dw_2 dw2,根据 d b = d z db=dz db=dz计算 d b db db;
- 更新 w 1 = w 1 − α ⋅ d w 1 w_1=w_1-\alpha\cdot dw_1 w1=w1−α⋅dw1,更新 w 2 = w 2 − α ⋅ d w 2 w_2=w_2-\alpha\cdot dw_2 w2=w2−α⋅dw2,更新 b = b − α ⋅ d b b=b-\alpha\cdot db b=b−α⋅db;
这就是关于单个样本实例的梯度下降算法中参数更新一次的步骤。
8. m m m个样本的梯度下降 (Gradient Descent on m m m examples)
在上一节中已经了解了怎样计算导数,并且实现针对单个训练样本的逻辑回归的梯度下降算法,但是训练逻辑回归模型不仅仅只有一个训练样本,而是有
m
m
m个训练样本的整个训练集。
首先回顾一下算法的代价函数
J
(
w
,
b
)
J(w,b)
J(w,b)的定义:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
a
(
i
)
,
y
(
i
)
)
J(w,b)=\frac{1}{m} \sum_{i=1}^{m}L(a^{(i)},y^{(i)})
J(w,b)=m1i=1∑mL(a(i),y(i))带有求和的全局代价函数,实际上是从1到
m
m
m项的各个损失函数的平均,它表明全局代价函数对
w
1
w_1
w1的微分也同样是各项损失函数对
w
1
w_1
w1微分的平均。
d
w
1
=
∂
L
∂
w
1
=
x
1
⋅
d
z
=
1
m
∑
i
m
x
1
(
i
)
(
a
(
i
)
−
y
(
i
)
)
dw_1=\frac{\partial L}{\partial w_1}=x_1\cdot dz=\frac{1}{m}\sum_{i}^{m}x_1^{(i)}(a^{(i)}-y^{(i)})
dw1=∂w1∂L=x1⋅dz=m1i∑mx1(i)(a(i)−y(i))
d
w
2
=
∂
L
∂
w
2
=
x
2
⋅
d
z
=
1
m
∑
i
m
x
2
(
i
)
(
a
(
i
)
−
y
(
i
)
)
dw_2=\frac{\partial L}{\partial w_2}=x_2\cdot dz=\frac{1}{m}\sum_{i}^{m}x_2^{(i)}(a^{(i)}-y^{(i)})
dw2=∂w2∂L=x2⋅dz=m1i∑mx2(i)(a(i)−y(i))
d
b
=
d
z
=
1
m
∑
i
m
(
a
(
i
)
−
y
(
i
)
)
db=dz=\frac{1}{m}\sum_{i}^{m}(a^{(i)}-y^{(i)})
db=dz=m1i∑m(a(i)−y(i)) 伪代码实现流程:
# 变量初始化
J=0
dw1=0
dw2=0
db=0
# 遍历m个训练样本
for i = 1 to m:
# 逻辑回归的计算
z(i) = wx(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)
# 遍历n个特征
for j = 1 to n:
dwj += xj(i)*dz(i)
db += dz(i)
J/= m
dw1/= m
dw2/= m
db/= m
w1 = w1-alpha*dw1
w2 = w2-alpha*dw2
b = b-alpha*db
但这种计算中有两个缺点,也就是说应用此方法在逻辑回归上需要编写两个for循环。第一个for循环是循环遍历所有
m
\pmb{m}
mmm个训练样本,第二个for循环是遍历所有
n
\pmb{n}
nnn个特征。
当你应用深度学习算法,你会发现在代码中显式地使用for循环会使你的算法很低效,同时在深度学习领域会有越来越大的数据集。所以能够应用你的算法且没有显式的for循环是重要的,并且会帮助你适用于更大的数据集。所以这里采用向量化的技术,它可以允许你的代码摆脱这些显式的for循环。
9. 向量化 (Vectorization)
9.1 向量化Logistic回归
Logistic回归的向量化实现流程如下:
(1) 创建一个
n
x
×
m
n_x\times m
nx×m的矩阵
X
=
[
x
(
1
)
,
x
(
2
)
,
⋯
⋯
,
x
(
m
)
]
X=[x^{(1)},x^{(2)},⋯⋯,x^{(m)}]
X=[x(1),x(2),⋯⋯,x(m)]作为训练输入,即
X
X
X是一个
n
x
n_x
nx行
m
m
m列的矩阵
R
n
x
×
m
R^{n_x\times m}
Rnx×m。
(2) 创建一个
n
x
×
m
n_x\times m
nx×m的矩阵
Z
=
[
z
(
1
)
,
z
(
2
)
,
⋯
⋯
,
z
(
m
)
]
=
w
T
X
+
[
b
,
b
,
⋯
⋯
,
b
]
=
[
w
T
x
(
1
)
+
b
,
w
T
x
(
2
)
+
b
,
⋯
⋯
,
w
T
x
(
m
)
+
b
]
Z=[z^{(1)},z^{(2)},⋯⋯,z^{(m)}]=w^TX+[b,b,⋯⋯,b]=[w^Tx^{(1)}+b,w^Tx^{(2)}+b,⋯⋯,w^Tx^{(m)}+b]
Z=[z(1),z(2),⋯⋯,z(m)]=wTX+[b,b,⋯⋯,b]=[wTx(1)+b,wTx(2)+b,⋯⋯,wTx(m)+b]计算所有的
z
z
z,这里的
b
b
b是一个实数,或者可以说是一个
1
×
1
1\times 1
1×1的矩阵,当你将这个向量加上这个实数时,Python自动把这个实数
b
b
b扩展成一个
n
x
×
m
n_x\times m
nx×m的行向量,这在Python中被称作广播(Broadcasting)。
(3) 计算所有的激活函数
A
=
[
a
(
1
)
,
a
(
2
)
,
⋯
⋯
,
a
(
m
)
]
=
σ
(
Z
)
A=[a^{(1)},a^{(2)},⋯⋯,a^{(m)}]=σ(Z)
A=[a(1),a(2),⋯⋯,a(m)]=σ(Z)。
Python代码实现(
n
x
=
2
,
m
=
2
n_x=2,m=2
nx=2,m=2):
import numpy as np
w = np.array([[2,2],[2,2]])
b = np.array([[1,1],[1,1]])
X = np.array([[2,6],[4,8]])
Z = np.dot(w.T,X)+b
A = 1 / (1 + np.exp(Z))
print(Z)
print(A)
输出结果:
这样就利用向量化在同一时间内高效地完成所有 m m m个训练样本的前向传播计算,得到所有的激活函数 a a a。
9.2 向量化Logistic回归的梯度输出
前面已经计算得到 A = [ a ( 1 ) , a ( 2 ) , ⋯ ⋯ , a ( m ) ] A=[a^{(1)},a^{(2)},⋯⋯,a^{(m)}] A=[a(1),a(2),⋯⋯,a(m)],我们需要找到这样一个行向量 Y = [ y ( 1 ) , y ( 2 ) , ⋯ ⋯ , y ( m ) ] Y=[y^{(1)},y^{(2)},⋯⋯,y^{(m)}] Y=[y(1),y(2),⋯⋯,y(m)],由此可以计算 d Z = [ d z ( 1 ) , d z ( 2 ) , ⋯ ⋯ , d z ( m ) ] = [ a ( 1 ) − y ( 1 ) , a ( 2 ) − y ( 2 ) , ⋯ ⋯ , a ( m ) − y ( m ) ] = A − Y dZ=[dz^{(1)},dz^{(2)},⋯⋯,dz^{(m)}]=[a^{(1)}-y^{(1)},a^{(2)}-y^{(2)},⋯⋯,a^{(m)}-y^{(m)}]=A-Y dZ=[dz(1),dz(2),⋯⋯,dz(m)]=[a(1)−y(1),a(2)−y(2),⋯⋯,a(m)−y(m)]=A−YPython代码实现:
dZ = A - Y
对于 d b db db和 d W dW dW,前面已经推导出 d b = 1 m ∑ i m d z ( i ) db=\frac{1}{m}\sum_{i}^{m} dz^{(i)} db=m1i∑mdz(i) d W = 1 m ∗ d Z ∗ X T = 1 m ∗ ( x ( 1 ) d z ( 1 ) + x ( 2 ) d z ( 2 ) + ⋯ ⋯ + x ( m ) d z ( m ) ) dW=\frac{1}{m}∗dZ∗X^T=\frac{1}{m}∗(x^{(1)}dz^{(1)}+x^{(2)}dz^{(2)}+⋯⋯+x^{(m)}dz^{(m)}) dW=m1∗dZ∗XT=m1∗(x(1)dz(1)+x(2)dz(2)+⋯⋯+x(m)dz(m)) Python代码实现:
db = np.sum(dZ) / m
dW = np.dot(dZ, X.T) / m
这样就利用向量化高效地完成反向传播的计算并以此来计算梯度。
10. Logistic损失函数的解释 (Explanation of Logistic Regression Cost Function)
10.1 单个训练样本的损失函数
在逻辑回归中,需要预测的结果
y
^
\hat{y}
y^可以表示为
y
^
=
σ
(
w
T
x
+
b
)
=
1
1
+
e
−
z
\hat{y}=\sigma(w^Tx+b)=\frac{1}{1+e^{-z}}
y^=σ(wTx+b)=1+e−z1。我们约定
y
^
=
p
(
y
=
1
∣
x
)
\hat{y}=p(y=1|x)
y^=p(y=1∣x),即算法的输出
y
^
\hat{y}
y^是给定训练样本
x
x
x条件下
y
y
y等于1的概率。
{
y
=
1
:
p
(
y
∣
x
)
=
y
^
y
=
0
:
p
(
y
∣
x
)
=
1
−
y
^
\begin{cases} y=1:& p(y|x)=\hat{y}\\ y=0:& p(y|x)=1-\hat{y} \end{cases}
{y=1:y=0:p(y∣x)=y^p(y∣x)=1−y^上述的两个条件概率公式可以合并成如下公式:
p
(
y
∣
x
)
=
y
^
y
(
1
−
y
^
)
1
−
y
p(y|x)=\hat{y}^y(1-\hat{y})^{1-y}
p(y∣x)=y^y(1−y^)1−y由于
log
\log
log函数是严格单调递增的函数,因此最大化
log
(
p
(
y
∣
x
)
)
\log(p(y|x))
log(p(y∣x))等价于最大化
p
(
y
∣
x
)
p(y|x)
p(y∣x)。计算
p
(
y
∣
x
)
p(y|x)
p(y∣x)的
log
\log
log对数,即计算
log
(
y
^
y
(
1
−
y
^
)
1
−
y
)
\log(\hat{y}^{y}(1-\hat{y})^{1-y})
log(y^y(1−y^)1−y),根据对数函数的性质可化简为:
log
(
p
(
y
∣
x
)
)
=
log
(
y
^
y
(
1
−
y
^
)
1
−
y
)
=
y
l
o
g
y
^
+
(
1
−
y
)
l
o
g
(
1
−
y
^
)
\log(p(y|x))=\log(\hat{y}^{y}(1-\hat{y})^{1-y})=ylog\hat{y} +(1−y)log(1− \hat{y})
log(p(y∣x))=log(y^y(1−y^)1−y)=ylogy^+(1−y)log(1−y^)而这就是我们前面提到的损失函数的负数
−
L
(
y
^
,
y
)
-L(\hat{y},y)
−L(y^,y),前面有一个负号的原因是当你训练深度学习算法时,需要算法输出值的概率是最大的(以最大的概率预测这个值),然而在逻辑回归中我们需要最小化损失函数,因此将最小化损失函数与最大化条件概率的对数
log
(
p
(
y
∣
x
)
)
\log(p(y|x))
log(p(y∣x))关联起来,这就是单个训练样本的损失函数表达式。
10.2 m m m个训练样本的损失函数
假设所有的训练样本服从同一分布且相互独立,即独立同分布的,所有这些样本的联合概率就是每个样本概率的乘积:
P
(
l
a
b
e
l
s
i
n
t
r
a
i
n
i
n
g
s
e
t
)
=
∏
i
=
1
m
P
(
y
(
i
)
∣
x
(
x
)
)
P(labels\ in\ training\ set)=\prod_{i=1}^{m}P(y^{(i)}∣x^{(x)})
P(labels in training set)=i=1∏mP(y(i)∣x(x))令这个概率最大化等价于令其对数最大化,对等式两边取对数:
P
(
l
a
b
e
l
s
i
n
t
r
a
i
n
i
n
g
s
e
t
)
=
log
∏
i
=
1
m
P
(
y
(
i
)
∣
x
(
x
)
)
=
∑
i
=
1
m
log
P
(
y
(
i
)
∣
x
(
x
)
)
=
∑
i
=
1
m
−
L
(
y
^
(
i
)
,
y
(
i
)
)
P(labels\ in\ training\ set)=\log\prod_{i=1}^{m}P(y^{(i)}∣x^{(x)})=\sum_{i=1}^{m}\log P(y^{(i)}∣x^{(x)})=\sum_{i=1}^{m}-L(\hat{y}^{(i)},y^{(i)})
P(labels in training set)=logi=1∏mP(y(i)∣x(x))=i=1∑mlogP(y(i)∣x(x))=i=1∑m−L(y^(i),y(i))计算这个式子的最大值,可以将负号移到求和符号的外面,即
−
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
-\sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)})
−∑i=1mL(y^(i),y(i)),这样我们就推导出了前面给出的logistic回归的损失函数(成本函数)
J
(
w
,
b
)
=
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
J(w,b)=\sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)})
J(w,b)=∑i=1mL(y^(i),y(i)),并且计算
J
(
w
,
b
)
J(w,b)
J(w,b)的最小值。
最后为了方便,可以对损失函数(成本函数)进行适当的缩放,因此就在前面加一个额外的常数因子
1
m
\frac{1}{m}
m1,即:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
J(w,b)=\frac{1}{m} \sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)})
J(w,b)=m1i=1∑mL(y^(i),y(i))