第三周:浅层神经网络(Shallow neural networks)
3.1神经网络概述(Neural Network Overview)
在深入学习具体技术之前,将快速浏览一下如何实现神经网络。上一周讨论了逻辑回归,了解了如下模型(图3.1.1)如与公式3.1建立联系。
图3.1.1
公式3.1:
x
w
b
}
=
>
z
=
w
T
+
b
\left. \begin{array}{l} x \\ w \\ b \\ \end{array} \right\} = > z = w^T + b
xwb⎭⎬⎫=>z=wT+b
如上所示,首先需要输入特征
x
x
x,参数
w
w
w和
b
b
b,这样就可以计算出
z
z
z,公式3.2:
x
w
b
}
=
=
>
z
=
w
T
+
b
=
=
>
α
=
σ
(
z
)
=
=
>
L
(
a
,
y
)
\left. \begin{array}{l} x \\ w \\ b \\ \end{array} \right\} = = > z = w^T + b = = > \alpha = \sigma \left( z \right)\\ = = > L\left( {a,y} \right)
xwb⎭⎬⎫==>z=wT+b==>α=σ(z)==>L(a,y)
接下来使用
z
z
z就可以计算出
α
\alpha
α。我们将符号换为表示输出
y
^
=
=
>
a
=
σ
(
z
)
\widehat{y} = = > a = \sigma \left( z \right)
y
==>a=σ(z),然后可以计算出 loss function
L
(
a
,
y
)
L\left( {a,y} \right)
L(a,y)
神经网络看起来是如下这个样子(图3.1.2)。正如之前提到的,可以将很多 sigmoid 单元堆叠起来形成一个神经网络。对于图3.1.1中的节点,它包含了之前讲的计算的两个步骤:首先通过公式3.1计算出值
z
z
z,然后通过
σ
(
z
)
\sigma \left( z \right)
σ(z)计算值
a
a
a。
图3.1.2
在这个神经网络(图3.1.2)对应的3个节点,首先计算第一层网络中的各个节点相关数
z
[
1
]
z^{\left[ 1 \right]}
z[1],接着计算
α
[
1
]
\alpha ^{\left[ 1 \right]}
α[1],在计算下一层网络同理:我们会使用符号
[
m
]
^{\left[ m \right]}
[m]表示第m层网络中节点相关的数,这些节点的集合被称为第m层网络。这样可以保证
[
m
]
^{\left[ m \right]}
[m]不会和我们之前用来表示单个的训练样本的
(
i
)
^{\left( i \right)}
(i)(即我们使用表示第i个训练样本)混淆:整个计算过程,公式如下:公式3.3
x
W
[
1
]
b
[
1
]
}
=
=
>
z
[
1
]
=
W
[
1
]
x
+
b
[
1
]
=
=
>
a
[
1
]
=
σ
(
z
[
1
]
)
\left. \begin{array}{l} x \\ W^{\left[ 1 \right]} \\ b^{[1]} \\ \end{array} \right\} = = > z^{[1]} = W^{[1]} x + b^{[1]} = = > a^{[1]} = \sigma \left( {z^{[1]} } \right)
xW[1]b[1]⎭⎬⎫==>z[1]=W[1]x+b[1]==>a[1]=σ(z[1])
公式3.4:
x
d
W
[
1
]
d
b
[
1
]
}
<
=
=
d
z
[
1
]
=
d
(
W
[
1
]
x
+
b
[
1
]
)
<
=
=
d
a
[
1
]
=
d
σ
(
z
[
1
]
)
\left. \begin{array}{l} x \\ dW^{\left[ 1 \right]} \\ db^{[1]} \\ \end{array} \right\} < = = dz^{[1]} = d\left( {W^{[1]} x + b^{[1]} } \right) < = = da^{[1]} = d\sigma \left( {z^{[1]} } \right)
xdW[1]db[1]⎭⎬⎫<==dz[1]=d(W[1]x+b[1])<==da[1]=dσ(z[1])
类似逻辑回归,在计算后要使用计算,接下来需要使用另外一个线性方程对应的参数计算
z
[
2
]
z^{\left[ 2 \right]}
z[2],计算
a
[
2
]
a^{\left[ 2 \right]}
a[2],此时
a
[
2
]
a^{\left[ 2 \right]}
a[2]就是整个神经网络最终的输出,用KaTeX parse error: Undefined control sequence: \widehaty at position 1: \̲w̲i̲d̲e̲h̲a̲t̲y̲表示网络的输出。
公式3.5:
d a [ 1 ] = d σ ( z [ 1 ] ) d W [ 2 ] d b [ 2 ] } < = = d z [ 2 ] = d ( W [ 2 ] α [ 1 ] + b [ 2 ] ) < = = d a [ 2 ] = d σ ( z [ 2 ] ) \left. \begin{array}{l} da^{\left[ 1 \right]} = d\sigma \left( {z^{[1]} } \right) \\ dW^{\left[ 2 \right]} \\ db^{[2]} \\ \end{array} \right\} < = = dz^{[2]} = d\left( {W^{[2]} \alpha ^{[1]} + b^{[2]} } \right) < = = da^{\left[ 2 \right]} = d\sigma \left( {z^{[2]} } \right) da[1]=dσ(z[1])dW[2]db[2]⎭⎬⎫<==dz[2]=d(W[2]α[1]+b[2])<==da[2]=dσ(z[2])
< = = d L ( a [ 2 ] , y ) < = = dL\left( {a^{[2]} ,y} \right) <==dL(a[2],y)
这其中有很多细节,其中有一点非常难以理解,即在逻辑回归中,通过直接计算𝑧得到结果
a
a
a。而这个神经网络中,我们反复的计算
z
z
z和
a
a
a,计算
a
a
a和
z
z
z,最后得到了最终的输出 loss function。
你应该记得逻辑回归中,有一些从后向前的计算用来计算导数
d
a
da
da、
d
z
dz
dz。同样,在神经网络中我们也有从后向前的计算,看起来就像这样,最后会计算
d
a
[
2
]
da^{\left[ 2 \right]}
da[2]、
d
z
[
2
]
dz^{\left[ 2 \right]}
dz[2],计算出来之后,然后计算
d
W
[
2
]
dW^{\left[ 2 \right]}
dW[2]、
d
b
[
2
]
db^{\left[ 2 \right]}
db[2]等,按公式3.4,3.5箭头表示的那样,从右到左反向计算
3.2神经网络的表示(Neural Network Representation)
我们首先关注一个例子,本例中的神经网络只包含一个隐藏层(图 3.2.1)。这是一张神经网络的图片,让我们给此图的不同部分取一些名字。
图3.2.1
我们有输入特征
x
1
x_1
x1,
x
2
x_2
x2,
x
3
x_3
x3,它们被竖直地堆叠起来,这叫做神经网络的输入层,它包含了神经网络的输入;然后这里有另外一层我们称之为隐藏层(图3.2.1的四个节点)。稍后会再来讲解术语“隐藏”的意义:在本例中最后一层只由一个结点构成,而这个只
有一个结点的层被称为输出层,它负责产生预测值。解释隐藏层的含义:在一个神经网络中,
当你使用监督学习训练它的时候,训练集包含了输入
x
x
x,也包含了目标输出
y
y
y,所以术语隐藏层的含义是在训练集中,这些中间结点的准确值我们是不知道到的,也就是说你看不见它们在训练集中应具有的值。你能看见输入的值,你也能看见输出的值,但是隐藏层中的东西,在训练集中你是无法看到的。所以这也解释了词语隐藏层,只是表示你无法在训练集中看到他们。
现在我们再引入几个符号,就像我们之前用向量
x
x
x表示输入特征。这里有个可代替的记号
a
[
0
]
a^{[0]}
a[0]可以用来表示输入特征。
a
a
a表示激活的意思,它意味着网络中不同层的值会传递到它们后面的层中,输入层将
x
x
x传递给隐藏层,所以我们将输入层的激活值称为
a
[
0
]
a^{[0]}
a[0];下一层即隐藏层也同样会产生一些激活值,那么我将其记作
a
[
1
]
a^{[1]}
a[1],所以具体地,这里的第一个单元或结点
我们将其表示为
a
1
[
1
]
a_1^{[1]}
a1[1],第二个结点的值记为
a
1
[
2
]
a_1^{[2]}
a1[2]以此类推。所以这里的是一个四维的向量如果写成 Python 代码,那么它是一个规模为4x1 的矩阵或一个大小为 4 的列向量,如下公式,它是四维的,因为在本例中,我们有四个结点或者单元,或者称为四个隐藏层单元;
公式3.7:
a
[
1
]
=
[
a
1
[
1
]
a
2
[
1
]
a
3
[
1
]
a
4
[
1
]
]
a^{[1]} = \left[ \begin{array}{l} a_1^{[1]} \\ a_2^{[1]} \\ a_3^{[1]} \\ a_4^{[1]} \\ \end{array} \right]
a[1]=⎣⎢⎢⎢⎡a1[1]a2[1]a3[1]a4[1]⎦⎥⎥⎥⎤
最后输出层将产生某个数值
a
a
a ,它只是一个单独的实数,所以
y
^
\widehat{y}
y
值将取为
a
[
2
]
a^{[2]}
a[2]。这与逻辑回归很相似,在逻辑回归中,我们有
y
^
\widehat{y}
y
直接等于
a
a
a,在逻辑回归中我们只有一个输出层,所以我们没有用带方括号的上标。但是在神经网络中,我们将使用这种带上标的形式来明确地指出这些值来自于哪一层,有趣的是在约定俗成的符号传统中,在这里你所看到的这个例子,只能叫做一个两层的神经网络(图 3.2.2)。原因是当我们计算网络的层数时,输入层是不算入总层数内,所以隐藏层是第一层,输出层是第二层。第二个惯例是我们将输入层称为第零层,所以在技术上,这仍然是一个三层的神经网络,因为这里有输入层、隐藏层,还有输出层。但是在传统的符号使用中,如果你阅读研究论文或者在这门课中,你会看到人们将这个神经网络称为一个两层的神经网络,因为我们不将输入层看作一个标准的层。
图3.2.2
最后,我们要看到的隐藏层以及最后的输出层是带有参数的,这里的隐藏层将拥有两个参数
W
W
W和
b
b
b,我将给它们加上上
[
1
]
(
W
[
1
]
b
[
1
]
)
^{[1]} \left( {W^{[1]} b^{[1]} } \right)
[1](W[1]b[1]),表示这些参数是和第一层这个隐藏层有关系的。之后在这个例子中我们会看到
W
W
W是一个 4x3 的矩阵,而
b
b
b是一个 4x1 的向量,第一个数字 4 源自于我们有四个结点或隐藏层单元,然后数字 3 源自于这里有三个输入特征,我们之后会更加详细地讨论这些矩阵的维数,到那时你可能就更加清楚了。相似的输出层也有一些与之关联的参数
W
[
2
]
b
[
2
]
W^{[2]} b^{[2]}
W[2]b[2]。从维数上来看,它们的规模分别是 1x4 以及 1x1。1x4 是因为隐藏层有四个隐藏层单元而输出层只有一个单元,之后我们会对这些矩阵和向量的维度做出更加深入的解释,所以现在你已经知道一个两层的神经网络什么样的了,即它是一个只有一个隐藏层的神经网络。
在下一节中。我们将更深入地了解这个神经网络是如何进行计算的,也就是这个神经网络是怎么输入
x
x
x,然后又是怎么得到
y
^
\widehat{y}
y
。
3.3计算一个神经网络的输出(Cnmputing a Neural Network’s output)
在上一节中,我们介绍只有一个隐藏层的神经网络的结构与符号表示。在这节的视频中让我们了解神经网络的输出究竟是如何计算出来的。
首先,回顾顾下只有一个隐藏层的简单两层神经网络结构:
图3.3.1
其中,
x
x
x表示输入特征,
a
a
a表示每个神经元的输出,
W
W
W表示特征的权重,上标表示神经网络的层数(隐藏层为 1),下标表示该层的第几个神经元。这是神经网络的符号惯例,下同。
神经网络的计算
关于神经网络是怎么计算的,从我们之前提及的逻辑回归开始,如下图所示。用圆圈表示神经网络的计算单元,逻辑回归的计算有两个步骤,首先你按步骤计算出
z
z
z,然后在第二步中你以 sigmoid 函数为激活函数计算
z
z
z(得出
a
a
a),一个神经网络只是这样子做了好多次重复计算。
图3.3.2
回到两层的神经网络,我们从隐藏层的第一个神经元开始计算,如上图第一个最上面的箭头所指。从上图可以看出,输入与逻辑回归相似,这个神经元的计算与逻辑回归一样分为两步,小圆圈代表了计算的两个步骤。
第一步:计算 z 1 [ 1 ] z_1^{[1]} z1[1], z 1 [ 1 ] = w 1 [ 1 ] T x + b 1 [ 1 ] z_1^{[1]} = w_1^{[1]T} x + b_1^{[1]} z1[1]=w1[1]Tx+b1[1]
第二步:通过激活函数计算
a
1
[
1
]
a_1^{[1]}
a1[1],
a
1
[
1
]
=
σ
(
z
1
[
1
]
)
a_1^{[1]} = \sigma \left( {z_1^{[1]} } \right)
a1[1]=σ(z1[1])。
隐藏层的第二个以及后面两个神经元的计算过程一样,只是注意符号表示不同,最终分别得到
a
2
[
1
]
a_2^{[1]}
a2[1]、
a
3
[
1
]
a_3^{[1]}
a3[1]、
a
4
[
1
]
a_4^{[1]}
a4[1],详细结果如下:
z
1
[
1
]
=
w
1
[
1
]
T
x
+
b
1
[
1
]
,
a
1
[
1
]
=
σ
(
z
1
[
1
]
)
z
2
[
1
]
=
w
2
[
1
]
T
x
+
b
2
[
1
]
,
a
2
[
1
]
=
σ
(
z
2
[
1
]
)
z
3
[
1
]
=
w
3
[
1
]
T
x
+
b
3
[
1
]
,
a
3
[
1
]
=
σ
(
z
3
[
1
]
)
z
4
[
1
]
=
w
4
[
1
]
T
x
+
b
4
[
1
]
,
a
4
[
1
]
=
σ
(
z
4
[
1
]
)
\begin{array}{l} z_1^{[1]} = w_1^{[1]T} x + b_1^{[1]} , a_1^{[1]} = \sigma \left( {z_1^{[1]} } \right) \\ \\ z_2^{[1]} = w_2^{[1]T} x + b_2^{[1]} , a_2^{[1]} = \sigma \left( {z_2^{[1]} } \right) \\ \\ z_3^{[1]} = w_3^{[1]T} x + b_3^{[1]} , a_3^{[1]} = \sigma \left( {z_3^{[1]} } \right) \\ \\ z_4^{[1]} = w_4^{[1]T} x + b_4^{[1]} , a_4^{[1]} = \sigma \left( {z_4^{[1]} } \right) \\ \end{array}
z1[1]=w1[1]Tx+b1[1],a1[1]=σ(z1[1])z2[1]=w2[1]Tx+b2[1],a2[1]=σ(z2[1])z3[1]=w3[1]Tx+b3[1],a3[1]=σ(z3[1])z4[1]=w4[1]Tx+b4[1],a4[1]=σ(z4[1])
向量化计算
如果你执行神经网络的程序,用 for 循环来做这些看起来真的很低效。所以接下来我们要做的就是把这四个等式向量化。向量化的过程是将神经网络中的一层神经元参数纵向堆积起来,例如隐藏层中的𝑤纵向堆积起来变成一个(4,3)的矩阵,用符号
W
[
1
]
W^{[1]}
W[1]表示。另一个看待这个的方法是我们有四个逻辑回归单元,且每一个逻辑回归单元都有相对应的参数——向量
w
w
w,把这四个向量堆积在一起,你会得出这 4×3 的矩阵。
因此,公式 3.8:
z
[
n
]
=
w
[
n
]
x
+
b
[
n
]
z^{[n]} = w^{[n]} x + b^{[n]}
z[n]=w[n]x+b[n]
公式 3.9:
a
[
n
]
=
σ
(
z
[
n
]
)
a^{[n]} = \sigma \left( {z^{[n]} } \right)
a[n]=σ(z[n])
详细过程见下: 公式 3.10:
a
[
1
]
=
[
a
1
[
1
]
a
2
[
1
]
a
3
[
1
]
a
4
[
1
]
]
=
σ
(
z
[
1
]
)
a^{[1]} = \left[ \begin{array}{l} a_1^{[1]} \\ a_2^{[1]} \\ a_3^{[1]} \\ a_4^{[1]} \\ \end{array} \right] = \sigma \left( {z^{[1]} } \right)
a[1]=⎣⎢⎢⎢⎡a1[1]a2[1]a3[1]a4[1]⎦⎥⎥⎥⎤=σ(z[1])
公式 3.11:
[
z
1
[
1
]
z
2
[
1
]
z
3
[
1
]
z
4
[
1
]
]
=
[
.
.
.
W
1
[
1
]
T
.
.
.
.
.
.
W
2
[
1
]
T
.
.
.
.
.
.
W
3
[
1
]
T
.
.
.
.
.
.
W
4
[
1
]
T
.
.
.
]
⏞
W
[
1
]
∗
[
x
1
x
2
x
3
]
⏞
i
n
p
u
t
+
[
b
1
[
1
]
b
2
[
1
]
b
3
[
1
]
b
4
[
1
]
]
⏞
b
[
1
]
\left[ \begin{array}{l} z_1^{[1]} \\ z_2^{[1]} \\ z_3^{[1]} \\ z_4^{[1]} \\ \end{array} \right] = \overbrace {\left[ \begin{array}{l} ...W_1^{[1]T} ... \\ ...W_2^{[1]T} ... \\ ...W_3^{[1]T} ... \\ ...W_4^{[1]T} ... \\ \end{array} \right]}^{W^{[1]} } * \overbrace {\left[ \begin{array}{l} x_1 \\ x_2 \\ x_3 \\ \end{array} \right]}^{input} + \overbrace {\left[ \begin{array}{l} b_1^{[1]} \\ b_2^{[1]} \\ b_3^{[1]} \\ b_4^{[1]} \\ \end{array} \right]}^{b^{[1]} }
⎣⎢⎢⎢⎡z1[1]z2[1]z3[1]z4[1]⎦⎥⎥⎥⎤=⎣⎢⎢⎢⎡...W1[1]T......W2[1]T......W3[1]T......W4[1]T...⎦⎥⎥⎥⎤
W[1]∗⎣⎡x1x2x3⎦⎤
input+⎣⎢⎢⎢⎡b1[1]b2[1]b3[1]b4[1]⎦⎥⎥⎥⎤
b[1]
对于神经网络的第一层,给予一个输入
x
x
x,得到
a
[
0
]
a^{[0]}
a[0]。通过相似的衍生
你会发现,后一层的表示同样可以写成类似的形式,得到
a
[
0
]
a^{[0]}
a[0],
y
^
=
a
[
2
]
\widehat{y} = a^{[2]}
y
=a[2],具体工程见公式3.8,3.9。
图3.3.3
如上图左半部分所示为神经网络,把网络左边部分盖住先忽略,那么最后的输出单元就相当于一个逻辑回归的计算单元。当你有一个包含一层隐藏层的神经网络,你需要去实现以计算得到输出的是右边的四个等式,并且可以看成是一个向量化的计算过程,计算出隐藏层的四个逻辑回归单元和整个隐藏层的输出结果,如果编程实现需要的也只是这四行代码。
**总结:**通过本节,你能够根据给出的一个单独的输入特征向量,运用四行代码计算出一个简单神经网络的输出。接下来你将了解的是如何一次能够计算出不止一个样本的神经网络输出,而是能一次性计算整个训练集的输出。