构建RNN(Recurrent Neural Network)

本文详细介绍了如何使用numpy手动实现RNN和LSTM的前向传播,包括基本RNN单元和LSTM单元的计算步骤。在前向传播部分,阐述了RNN如何通过记忆机制处理序列数据,并引入LSTM解决梯度消失问题。在反向传播部分,简要分析了基本RNN和LSTM的反向传播过程,包括门的导数计算和参数更新。
摘要由CSDN通过智能技术生成

目前RNN网络可以在深度学习框架下通过调用函数实现(比如:tf.nn.rnn_cell),但为了掌握更多RNN的细节,我们还是需要使用numpy来逐步实现。

由于RNN网络具有“记忆力”,因此非常适合NLP和序列任务。RNN网络每次读取一个输入X(t),输入信息从当前时间步传到下一步的过程中,网络隐含层的激活函数会“记住”一些信息或上下文内容。这种机制允许单向RNN从前面的输入中获取信息以处理后续输入,同时使得双向RNN网络能够从过去和未来的获取上下文信息。

导入所需的第三方库,其中所用辅助程序可点击此处下载。

import numpy as np
from rnn_utils import *

1.基本RNN的前向传播

基本RNN结构如下,其中Tx = Ty:

1.1RNN单元

RNN网络可以看做是一个单元的重复执行,首先要执行的单一时间步的计算,计算操作如图所示:

如图所示,需要计算的步骤如下:

(1)计算隐层状态a<t>:  

(2)计算预测值y<t>_hat:

(3)在缓存中存储cache:(a<t>,a<t-1>,X<t>,parameters)

(4)返回a<t>,y<t>_hat 和 cache

我们将m个样本向量化,因此X<t>的维度是(n_x, m),a<t>的维度是(n_a, m)

def rnn_cell_forward(xt, a_prev, parameters):

    Wax = parameters["Wax"]
    Waa = parameters["Waa"]
    Wya = parameters["Wya"]
    ba = parameters["ba"]
    by = parameters["by"]

    a_next = np.tanh(np.dot(Waa, a_prev) + np.dot(Wax, xt) + ba)
    yt_pred = softmax(np.dot(Wya, a_next) + by)

    cache = (a_next, a_prev, xt, parameters)

    return a_next, yt_pred, cache
np.random.seed(1)
xt = np.random.randn(3,10)
a_prev = np.random.randn(5,10)
Waa = np.random.randn(5,5)
Wax = np.random.randn(5,3)
Wya = np.random.randn(2,5)
ba = np.random.randn(5,1)
by = np.random.randn(2,1)
parameters = {"Waa": Waa, "Wax": Wax, "Wya": Wya, "ba": ba, "by": by}

a_next, yt_pred, cache = rnn_cell_forward(xt, a_prev, parameters)
print("a_next[4] = ", a_next[4])
print("a_next.shape = ", a_next.shape)
print("yt_pred[1] =", yt_pred[1])
print("yt_pred.shape = ", yt_pred.shape)
a_next[4] =  [ 0.59584544  0.18141802  0.61311866  0.99808218  0.85016201  0.99980978
 -0.18887155  0.99815551  0.6531151   0.82872037]
a_next.shape =  (5, 10)
yt_pred[1] = [0.9888161  0.01682021 0.21140899 0.36817467 0.98988387 0.88945212
 0.36920224 0.9966312  0.9982559  0.17746526]
yt_pred.shape =  (2, 10)

1.2RNN前向传播

 RNN的结构实质上就是1.1中介绍基本单元的多次组合,对于每一个单元将a<t-1>和X<t>,输出为a<t>和y<t>预测值,下图是一个RNN模型的前向传播的过程。

 

def rnn_forward(x, a0, parameters):

    caches = []
    n_x, m, T_x = x.shape
    n_y, n_a = parameters["Wya"].shape

    a = np.zeros((n_a, m, T_x))
    y_pred = np.zeros((n_y, m, T_x))

    a_next = a0

    for t in range(T_x):

        a_next, yt_pred, cache = rnn_cell_forward(x[:,:,t], a_next, parameters)
        a[:,:,t] = a_next
        y_pred[:,:,t] = yt_pred
        caches.append(cache)

    caches = (caches, x)

    return a, y_pred, caches
np.random.seed(1)
x = np.random.randn(3,10,4)
a0 = np.random.randn(5,10)
Waa = np.random.randn(5,5)
Wax = np.random.randn(5,3)
Wya = np.random.randn(2,5)
ba = np.random.randn(5,1)
by = np.random.randn(2,1)
parameters = {"Waa": Waa, "Wax": Wax, "Wya": Wya, "ba": ba, "by": by}

a, y_pred, caches = rnn_forward(x, a0, parameters)
print("a[4][1] = ", a[4][1])
print("a.shape = ", a.shape)
print("y_pred[1][3] =", y_pred[1][3])
print("y_pred.shape = ", y_pred.shape)
print("caches[1][1][3] =", caches[1][1][3])
print("len(caches) = ", len(caches))
a[4][1] =  [-0.99999375  0.77911235 -0.99861469 -0.99833267]
a.shape =  (5, 10, 4)
y_pred[1][3] = [0.79560373 0.86224861 0.11118257 0.81515947]
y_pred.shape =  (2, 10, 4)
caches[1][1][3] = [-1.1425182  -0.34934272 -0.20889423  0.58662319]
len(caches) =  2

目前我们已经完成了RNN的前向传播过程,这个模型已经可以解决不少训练问题了,但是存在着梯度消失的问题。下面我们将构建LSTM来解决这个问题,以便模型可以很好的利用上下文信息。

2.长短时记忆网络(LSTM)

LSTM的主要特点是增加了遗忘门、更新门和输出门,如下图所示;

 

LSTM网络也是有LSTM Cell堆叠构成的。

(1)遗忘门

假设我们在阅读一段文字,主语的单复数形式决定着后文谓语的形式,因此我们需要利用LSTM的记忆功能。但是当阅读到下一段主语形式变化了,LSTM需要丢弃之前的记忆,这个功能便需要遗忘门实现,公式如下:

 上式的结果是介于0-1的矢量,如果接近0,意味着LSTM应移除记忆信息;如果为1,意味着需要保持c<t-1>的信息。

(2)更新门

一旦决定遗忘主语的单数形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值