由于这一门课要在本周就结束了,所以这一周的视频都非常的简短,以便于后面大作业的完成。
4.1 深层神经网络
这一节主要介绍了如何描述神经网络的种类和各个部分。
首先,什么是深层神经网络?
单隐层神经网络我们上一周已经见到过了,而深层这个形容词,就是特指层数多的神经网络了。
图中第二个(右上)是单隐层网络,而后是双隐层网络(左下),以及五隐层网络。第一个逻辑回归模型显然是非常地浅的,而它右边的双层网络(注意层的计算是包括输出层的,但不算输入层),也就是单隐层网络,就相对而言深一些,其中最深层的是最后一个。吴老师在这里说了一句话叫做:
但是前几年在人工智能或机器学习社区中,大家发觉有些函数,只有非常深层的神经网络才能够学习,而浅一些的模型通常无法学习。
这关系到为什么要用深层而不是只是浅层的神经网络就好的原因,我们先记住这句话,后面再说(
好了让我们继续来描述神经网络:
这是一个四层的神经网络,因为里面有三个隐层。
这里我们用L表示层数,该神经网络显然L=4;
n
[
l
]
\ n^{[l]}
n[l]表示第l层的神经元的数量,例如
n
[
1
]
=
n
[
2
]
=
5
,
n
[
3
]
=
3
,
n
[
4
]
=
1
,
n
[
0
]
=
5
;
\ n^{[1]}=n^{[2]}=5,n^{[3]}=3,n^{[4]}=1,n^{[0]}=5;
n[1]=n[2]=5,n[3]=3,n[4]=1,n[0]=5;
a
[
l
]
\ a^{[l]}
a[l]表示第l层中的激活函数,
a
[
l
]
=
g
[
l
]
(
z
[
l
]
)
;
\ a^{[l]}=g^{[l]} (z^{[l]});
a[l]=g[l](z[l]);
w
[
l
]
,
\ w^{[l]},
w[l],
b
[
l
]
\ b^{[l]}
b[l]来表示在
a
[
l
]
\ a^{[l]}
a[l]中计算
z
[
l
]
\ z^{[l]}
z[l]的权重;
x
\ x
x表示输入特征,,也是
a
[
0
]
\ a^{[0]}
a[0]层的激活函数;
另
a
[
L
]
=
y
^
\ a^{[L]}=\hat{y}
a[L]=y^,也就是说
a
[
L
]
\ a^{[L]}
a[L]等于预测输出,
4.2深层神经网络中的前向传播
这一节吴老师用一个样例总结推导出了深层神经网络前向传播的公式,我们下面来看这个例子:
首先来看他画蓝色框框的这一层,根据前面我们学习到的,我们能写出表达式:
z
[
1
]
=
w
[
1
]
x
+
b
[
1
]
,
a
[
1
]
=
g
[
1
]
(
z
[
1
]
)
.
\ z^{[1]}=w^{[1]}x+b^{[1]}, a^{[1]}=g^{[1]}(z^{[1]}).
z[1]=w[1]x+b[1],a[1]=g[1](z[1]).
再看紫色框框,我们又可以接着写:
z
[
2
]
=
w
[
2
]
a
[
1
]
+
b
[
2
]
,
a
[
2
]
=
g
[
2
]
(
z
[
2
]
)
.
\ z^{[2]}=w^{[2]}a^{[1]}+b^{[2]}, a^{[2]}=g^{[2]}(z^{[2]}).
z[2]=w[2]a[1]+b[2],a[2]=g[2](z[2]).
好了到了没有框框的一层,显然他讲课中没有写不过不碍事我们来写一哈:
z
[
3
]
=
w
[
3
]
a
[
2
]
+
b
[
3
]
,
a
[
3
]
=
g
[
3
]
(
z
[
3
]
)
.
\ z^{[3]}=w^{[3]}a^{[2]}+b^{[3]}, a^{[3]}=g^{[3]}(z^{[3]}).
z[3]=w[3]a[2]+b[3],a[3]=g[3](z[3]).
(显然跟上一个式子除了层数不同之外,没什么区别)
那么我们来写绿色框框:(突然兴奋
z
[
4
]
=
w
[
4
]
a
[
3
]
+
b
[
4
]
,
a
[
4
]
=
g
[
4
]
(
z
[
4
]
)
=
y
^
.
\ z^{[4]}=w^{[4]}a^{[3]}+b^{[4]}, a^{[4]}=g^{[4]}(z^{[4]})=\hat{y}.
z[4]=w[4]a[3]+b[4],a[4]=g[4](z[4])=y^.
四个式子下来,于是我们找到了规律(
z
[
n
]
=
w
[
n
]
a
[
n
−
1
]
+
b
[
n
]
,
a
[
n
]
=
g
[
n
]
(
z
[
n
]
)
.
\ z^{[n]}=w^{[n]}a^{[n-1]}+b^{[n]}, a^{[n]}=g^{[n]}(z^{[n]}).
z[n]=w[n]a[n−1]+b[n],a[n]=g[n](z[n]).
可能你会问,第一个式子和他们长得不一样啊,或许可能是隔壁家老王的吧(逃
不过输入x本来就等于
a
[
0
]
\ a^{[0]}
a[0]的哇
不过这只是针对一个训练样本的公式写法,那怎么用向量化的方法训练整个训练集咧:
我们要做的只是把第一遍的z和a叠加成向量,例如我们的Z就长这个样子:
那么把上述过程重复一遍后,同理可得:
Z
[
n
]
=
w
[
n
]
A
[
n
−
1
]
+
b
[
n
]
,
A
[
n
]
=
g
[
n
]
(
Z
[
n
]
)
.
\ Z^{[n]}=w^{[n]}A^{[n-1]}+b^{[n]}, A^{[n]}=g^{[n]}(Z^{[n]}).
Z[n]=w[n]A[n−1]+b[n],A[n]=g[n](Z[n]).
且
Y
^
=
a
[
4
]
=
g
[
4
]
(
Z
[
4
]
)
.
\ \hat{Y}=a^{[4]}=g^{[4]}(Z^{[4]}).
Y^=a[4]=g[4](Z[4]).
如果你愿意再观察一遍上述推导过程的话,就会发现它就是一个for i in rang(4)
的循环,虽然我们不想在我们的运算中有for循环,但是它似乎是不可用别的方法替代的,所以在实现正向传播的时候,我们用for循环也是可以的,用它计算从1到L层的数据,算出预测的结果。
核对矩阵的维数
在深层神经网络中,常用的检查代码是否有错的方法是过一遍算法中矩阵的维数。下面我们用一个例子来示范一下如何做:
首先我们来算一下第一层的维数们:
根据上一节的公式
z
[
1
]
=
w
[
1
]
x
+
b
[
1
]
\ z^{[1]}=w^{[1]}x+b^{[1]}
z[1]=w[1]x+b[1],我们可以开始推向量的维数了(
根据上图的例子,我们首先写出
z
[
1
]
\ z^{[1]}
z[1]是
(
3
,
1
)
\ (3,1)
(3,1)的,则
b
[
1
]
\ b^{[1]}
b[1]也是同样的
(
3
,
1
)
\ (3,1)
(3,1),而后我们由图可知 x 为
(
2
,
1
)
\ (2,1)
(2,1),所以
w
[
1
]
\ w^{[1]}
w[1]的维数是
(
3
,
2
)
\ (3,2)
(3,2),而根据
a
[
1
]
=
g
[
1
]
(
z
[
1
]
)
.
\ a^{[1]}=g^{[1]}(z^{[1]}).
a[1]=g[1](z[1]).得a与z的维数相等,于是
a
[
1
]
\ a^{[1]}
a[1]的维数是
(
3
,
1
)
\ (3,1)
(3,1)。
好了鉴于描述实在是很容易凌乱且非常麻烦,我们接下来的层数就都来画表格吧~
维数 | |
---|---|
z [ 1 ] \ z^{[1]} z[1] | ( 3 , 1 ) / ( n [ 1 ] , 1 ) \ (3,1)/(n^{[1]},1) (3,1)/(n[1],1) |
w [ 1 ] \ w^{[1]} w[1] | ( 3 , 2 ) / ( n [ 1 ] , n [ 0 ] ) \ (3,2)/(n^{[1]},n^{[0]}) (3,2)/(n[1],n[0]) |
a [ 0 ] \ a^{[0]} a[0] | ( 2 , 1 ) / ( n [ 0 ] , 1 ) \ (2,1)/(n^{[0]},1) (2,1)/(n[0],1) |
b [ 1 ] \ b^{[1]} b[1] | ( 3 , 1 ) / ( n [ 1 ] , 1 ) \ (3,1)/(n^{[1]},1) (3,1)/(n[1],1) |
z [ 2 ] \ z^{[2]} z[2] | ( 5 , 1 ) / ( n [ 2 ] , 1 ) \ (5,1)/(n^{[2]},1) (5,1)/(n[2],1) |
w [ 2 ] \ w^{[2]} w[2] | ( 5 , 3 ) / ( n [ 2 ] , n [ 1 ] ) \ (5,3)/(n^{[2]},n^{[1]}) (5,3)/(n[2],n[1]) |
a [ 1 ] \ a^{[1]} a[1] | ( 3 , 1 ) / ( n [ 1 ] , 1 ) \ (3,1)/(n^{[1]},1) (3,1)/(n[1],1) |
b [ 2 ] \ b^{[2]} b[2] | ( 5 , 1 ) / ( n [ 2 ] , 1 ) \ (5,1)/(n^{[2]},1) (5,1)/(n[2],1) |
z [ 3 ] \ z^{[3]} z[3] | ( 4 , 1 ) / ( n [ 3 ] , 1 ) \ (4,1)/(n^{[3]},1) (4,1)/(n[3],1) |
w [ 3 ] \ w^{[3]} w[3] | ( 4 , 5 ) / ( n [ 3 ] , n [ 2 ] ) \ (4,5)/(n^{[3]},n^{[2]}) (4,5)/(n[3],n[2]) |
a [ 2 ] \ a^{[2]} a[2] | ( 5 , 1 ) / ( n [ 2 ] , 1 ) \ (5,1)/(n^{[2]},1) (5,1)/(n[2],1) |
b [ 3 ] \ b^{[3]} b[3] | ( 4 , 1 ) / ( n [ 3 ] , 1 ) \ (4,1)/(n^{[3]},1) (4,1)/(n[3],1) |
……
则
z [ l ] = a [ l ] = b [ l ] \ z^{[l]}=a^{[l]}=b^{[l]} z[l]=a[l]=b[l] | ( n [ l ] , 1 ) \ (n^{[l]},1) (n[l],1) |
---|---|
w [ l ] \ w^{[l]} w[l] | ( n [ l ] , n [ l − 1 ] ) \ (n^{[l]},n^{[l-1]}) (n[l],n[l−1]) |
当然了如果你要实现反向传播的话,那么 dw 和 w ,dz 和 z 的维度应该相同:
d z [ l ] = a [ l ] = b [ l ] \ dz^{[l]}=a^{[l]}=b^{[l]} dz[l]=a[l]=b[l] | ( n [ l ] , 1 ) \ (n^{[l]},1) (n[l],1) |
---|---|
d w [ l ] \ dw^{[l]} dw[l] | ( n [ l ] , n [ l − 1 ] ) \ (n^{[l]},n^{[l-1]}) (n[l],n[l−1]) |
接下来让我们一起来看一下向量化之后,维数会发生哪些变化:
在单一的数据样本值下,我们的变量维数是这样的(第一层):
维数 | |
---|---|
z [ 1 ] \ z^{[1]} z[1] | ( n [ 1 ] , 1 ) \ (n^{[1]},1) (n[1],1) |
w [ 1 ] \ w^{[1]} w[1] | ( n [ 1 ] , n [ 0 ] ) \ (n^{[1]},n^{[0]}) (n[1],n[0]) |
x \ x x | ( n [ 0 ] , 1 ) \ (n^{[0]},1) (n[0],1) |
b [ 1 ] \ b^{[1]} b[1] | ( n [ 1 ] , 1 ) \ (n^{[1]},1) (n[1],1) |
那经历向量化,就是把样本数据值变成一个向量之后,
(向量长下面这个样子:),维度的变化(我们继续画表格:
维数(m是样本数量) | |
---|---|
Z [ 1 ] \ Z^{[1]} Z[1] | ( n [ 1 ] , m ) \ (n^{[1]},m) (n[1],m) |
W [ 1 ] \ W^{[1]} W[1] | ( n [ 1 ] , n [ 0 ] ) \ (n^{[1]},n^{[0]}) (n[1],n[0]) |
X \ X X | ( n [ 0 ] , m ) \ (n^{[0]},m) (n[0],m) |
b [ 1 ] \ b^{[1]} b[1] | ( n [ 1 ] , 1 ) \ (n^{[1]},1) (n[1],1) |
最后一点关于
b
[
1
]
\ b^{[1]}
b[1],我们知道python的广播操作,所以
b
[
1
]
\ b^{[1]}
b[1]是可以不变的,python在计算过程中会自动把它变成
(
n
[
1
]
,
m
)
\ (n^{[1]},m)
(n[1],m)的格式方便计算。
当你自己去实现神经网络的时候,如果很清楚的知道不同矩阵的维数的话,对于减少你的bug是有非常大的好处的。
4.4 为毛使用深层表示(
还记得我们在第一节记住的吴老师的那句话吗?
但是前几年在人工智能或机器学习社区中,大家发觉有些函数,只有非常深层的神经网络才能够学习,而浅一些的模型通常无法学习。
现在我们来认真探究一下,吴老师用一个例子来举例证明了有些函数,确实是浅层神经网络,例如逻辑回归,所不能完成的。
这个例子由左到右的隐层,分别有着识别边缘特征,器官特征(课程中举例眼睛,鼻子),面部特征的功能。第一个隐层可以当作探测简单的函数,比如边缘特征。如果加上它之后的特征,就可以学习到更多的东西。可以看到正是有了前面的基础,才可以达到后面实现人脸识别的功能。第一层的边缘探测器是针对的比较小的区域,而到了最后面部特征,就会是大区域的探测了。而这就是浅层神经网络所做不到的。
这种从简单到复杂的金字塔状方法,也可以应用在图像或者人脸识别以外的其他数据之上,比如如果你想建立一个语音识别系统,那么神经网络的第一层可能就负责试着探测分辨白噪音,而后一层网络,可能就可以探测音位(比如cat中的c音就是一个音位),有了基本的声音单元之后,我们就可以识别更复杂的单词,或者词组,甚至是更长的句子了。
另外一个关于深度神经网络为什么有效的原因,来自于电路理论:
这些函数都可以用相对较小但很深的神经网络来计算,这里“小”指的是隐藏单元的数量相对小,但是你如果想用浅一些的网络去计算相同的函数,那么就需要足够数量的隐藏单元了。
以此为例子,如果你想要计算这个多重异或门的网络的结果的话,按照这样的多层结构,你所需要的单元数量不会很多,但如果你被迫要求只能用一层来计算结果,那么你恐怕需要一个指数倍的单元数量来完成这件事,因为你要模拟
x
1
,
x
2
…
…
x
n
\ x^1,x^2……x^n
x1,x2……xn的所有情况。
其实对于使用深层神经网络的原因,还有另外一个解释:
Hornik在1989年证明了一个定理:
只需一个包含足够多神经元的隐层,多层前馈神经网络就能以任意精度逼近任意复杂的连续函数
但是我们在实际情况中既没有足够多的神经元,也不能保证要拟合的模型是连续函数,而且在复杂的实际情况中,最后预测和尽可能贴近的结果很大可能并不是一个显而易见的简单函数,所以我们用单个隐层并不能完成我们最后预测的需求,于是我们需要深层神经网络。
虽然如此,但吴老师仍然建议我们在运算的最初要先试一下逻辑回归等浅层的神经网络,因为深层神经网络并非是一个万能钥匙,如果可以简单地完成的话,我们为什么要复杂呢?