一、为什么不用标准神经网络?
在前面一节中,我们构件了输入x和输出y,如果使用标准神经网络,可以得到如下的网络结构图:
但是,事实证明效果并不好,主要问题如下:
- 输入和输出通常会有不同的长度( T x T_x Tx和 T y T_y Ty不相等),如果用0来填充长度(padding),也不是一种好的表达方式
- 这种DNN结构并不能共享文本不同位置上学到的特征,举个简单的例子就是,如果网络能识别出不同位置的Harry名就太好了,这个和CNN类似,希望网络将图像某个区域上学到的特征推广到其他部分。这种更好的表达方式,可以大大减少网络中的参数量
后面要讲的RNN,就能很好地解决上述两个问题!
二、循环神经网络(Recurrent Neural Networks)
从左边看,首先给网络一个初始激活值
a
<
0
>
a^{<0>}
a<0>,通常是一个0向量,也有研究人员给出别的初始化方案。可以看到
x
<
t
>
x^{<t>}
x<t>输入网络后输出预测值
y
<
t
>
y^{<t>}
y<t>,得到激活值
a
<
l
>
a^{<l>}
a<l>传递给下一个时间。
在一些论文中也有用下图的形式表示的:
这个图是循环图,其中黑色块表示延迟了一个时间步。更多时候,吴恩达老师更倾向于分步的画法。
循环神经网络从左向右扫描数据,同时每个时间步的参数是共享的,比如输入层都使用
w
a
x
w_{ax}
wax,输出层都用
w
y
a
w_{ya}
wya,激活层都用
w
a
a
w_{aa}
waa表示。
循环神经网络的特点在于,在某个时刻的预测值时只用到了序列前面部分,并没有用到后面部分。比如下面这种情况,明显只依靠Teddy前面的词是不可能判断出Teddy是否为人名的。
如何解决上述问题?在后续课程中的双向循环神经网络(BRNN)会处理这个问题。
三、前向传播(Forward Propagation)
下面是前向传播的过程,通过
a
<
0
>
a^{<0>}
a<0>和
x
<
1
>
x^{<1>}
x<1>计算出
a
<
1
>
a^{<1>}
a<1>,从而计算出
y
^
<
1
>
\hat{y}^{<1>}
y^<1>的值。
现在简化这个表达式,方法就是将
W
a
a
W_{aa}
Waa和
W
a
x
W_{ax}
Wax两个参数矩阵合在一起(横向堆),把
a
<
t
−
1
>
a^{<t-1>}
a<t−1>和
x
<
t
>
x^{<t>}
x<t>合在一起(纵向堆):
对于
y
^
<
t
>
\hat{y}^{<t>}
y^<t>的计算,只需将
W
y
a
W_{ya}
Wya简化为
W
y
W_y
Wy即可表示是计算
y
y
y的参数。
四、跨越时间的反向传播(Backpropagation through time)
损失函数的定义 标准logistic回归损失函数
在某个时间步或某个单词位置上:
L
<
t
>
(
y
^
<
t
>
,
y
<
t
>
)
=
−
y
<
t
>
l
o
g
y
^
<
t
>
−
(
1
−
y
<
t
>
)
l
o
g
(
1
−
y
^
<
t
>
)
L^{<t>}(\hat{y}^{<t>}, {y}^{<t>}) = -{y}^{<t>}log \hat{y}^{<t>}-(1-{y}^{<t>})log(1-\hat{y}^{<t>})
L<t>(y^<t>,y<t>)=−y<t>logy^<t>−(1−y<t>)log(1−y^<t>)
整体损失函数(本质上是对每个时间步的损失值求和):
L
(
y
^
,
y
)
=
∑
t
=
1
T
x
L
<
t
>
(
y
^
<
t
>
,
y
<
t
>
)
L(\hat{y}, y)=\sum^{T_x}_{t=1} L^{<t>}(\hat{y}^{<t>}, {y}^{<t>})
L(y^,y)=t=1∑TxL<t>(y^<t>,y<t>)
下面是我绘制的循环神经网络正向传播和反向传播计算图,其中表明了参数、输入值、激活值、预测值、损失值以及反向传播在整个网络中的身份和位置。反向传播也称为跨越时间的传播,因为紫色箭头从右往左计算,拥有了“时光倒流”的奇妙现象。