RNN——循环神经网络(tensorflow)

1、RNN的基本设定

在语言模型任务中,给定特定的单词序列(句子片段),任务目标是预测该片段的下一个单词(或者符号)。传统的n-gram模型可以应用于该任务,但是它存在着许多难以解决的问题:假设预测序列为 Tom open his ___

①强假设问题:n-gram模型的构建依赖于过强的假设,即假设待预测的第n各单词只依赖于它之前的n-1个单词,即:

P(x^{(t+1)}|x^{(t)},...,x^{(1)})=p(x^{(t+1)}|x^{(t)},...,x^{(t-n+2)})

②稀疏问题:由于n-gram模型的预测靠的是第对条件概率:

P(x^{(t+1)}|x^{(t)},...,x^{(t-n+2)})=\frac{P(x^{(t+1)},x^{(t)},...,x^{(t-n+2)})}{P(x^{(t)},...,x^{(t-n+2)})}=\frac{count(x^{(t+1)},x^{(t)},...,x^{(t-n+2)})}{count(x^{(t)},...,x^{(t-n+2)})}

如果分子统计量为0,则预测概率会被模型直接置为0;如果分母的统计量为0,则无法正确地计算预测概率。当我们试图通过增大n-gram模型中的参数n来扩展待预测单词的语境以达到更好的效果是,稀疏问题会变得愈发严重。

③存储问题:为了更好得到n-gram模型,我们需要对训练语料中的所有n元组进行计算并存储相关数据;当n或者语料增大时,模型大小也会随之增大。

面对传统n-gram模型的种种问题,我们希望得到一个不依赖于过强假设、不会出现稀疏问题、可以更好利用语境与句中的长距离依赖关系、且模型的大小不会随着输入的变化而变化的模型。由此引入RNN模型。

2、RNN是什么?

Recurrent Neural Networks(RNN)是一类神经网络结构,最基础的RNN结构如下:

最基础的RNN模型分为上中下三层。中间的红色部分称为隐藏层,每个红色方框表示一个隐藏状态。RNN的特点:每个隐藏状态h^{(t)}的值都依赖于它前一个隐藏状态h^{(t-1)}和当前状态的输入值x^{(t)},并且模型中很多参数都是共享的。所谓共享是指,虽然模型中不同的隐藏状态处于不同的位置,但是他们的输入、输出、以及状态转移时所使用的参数矩阵(E,W_{t},U)(E,W_{t},U)是相同的。并且由于RNN结构中隐藏状态的处理在时间上是有先后顺序,只有处理完前一个隐藏状态才能处理当前的状态,因此隐藏状态又被称为时间步。

3、RNN在语言模型任务中的应用

①首先,给定一个输入句子S=x_{1}x_{2}...x_{n},可以通过查词库得到每个单词x_{t}的one-hot向量表示(x^{t}\in R^{|V|});之后,利用词向量矩阵E得到每个单词对应的词向量e^{t}=Ex^{t},e^{t}\in R ^{d},d表示词向量的维度;

②然后,有了输入的词向量之后,按照顺序对每个隐藏状态进行计算:

 

h^{(t)} = \sigma (W_{h} h^{(t-1)} + W_{e} e^{(t)} +b _{1}), h^{(t)} \in R^{D_{h}}

其中,D_{h}表示隐藏状态的维度,W_{h}表示隐藏状态间的转换矩阵,W_{e}表示输入与隐藏层间的转换矩阵;

③最后,通过softmax层给出模型对单词概率的预测\hat{y}^{(t)}=softmax(Uh^{(t)} + b_{2})\in R^{|V|},其中,U表示从隐藏层到输出之间的权重矩阵。

以任务预测句子 the student opened their ___ 的下一个单词为例,其过程如下图所示:

 

4、RNN的优缺点

优点:

①可以处理任意长度的输入,且模型大小不会随着输入的增长而变化;模型中的参数量是固定的,与输入大小无关。

②理论上,对隐藏状态h^{(t)}进行计算时,可以利用多步之前的信息。

缺点:

①计算缓慢:必须计算完迁移状态才能计算当前状态,我们只能序列化的计算所有状态而无法利用并行算法加速计算。

②虽然理论上RNN可以利用多步以前的信息,然而实践当中很难做到这一点。

5、RNN模型的训练过程与反向传播(https://zhuanlan.zhihu.com/p/101928642

6、梯度消失与梯度爆炸(https://zhuanlan.zhihu.com/p/101928642

梯度消失:随着反向传播的前进,梯度越来越小,小到几乎为0。这样远小于来自附近的梯度信息的来自远处的梯度信息就会丢失,模型的权重参数也就只受附近信息的影响,而不受远处信息的影响。

梯度爆炸:反向传播时梯度的数值迅速变得非常巨大。

对于梯度爆炸的解决方法:

假设对于代价函数J(W, b)的梯度图如图所示: 

 

对于含有陡峭悬崖的梯度模型,需要进行梯度阶段(Gradient Clipping)。其中红色的点为最优值的位置,如果使用梯度截断法(如右图),则可以使梯度在接近悬崖时降低步伐(学习率衰减),如果不使用梯度截断法(如左图),则可能由于过大的学习率使当前的参数被”抛出“曲面。

7、LSTM(Long Short-Term Memory) 

LSTM是一种时间循环神经网络,是为了解决一般的RNN存在的梯度消失问题而专门设计出来的。

输入门:对输入的信息进行选择性的输入;遗忘门:对前一状态的信息进行选择性的记忆;输出门:对当前状态的信息进行选择性的输出;记忆单元:存储历史信息。

 

LSTM向前传递的更新公式:

整体的LSTM序列:

一个LSTM单元的内部详细结构图: 

 

8、GRU(Gated Recurrent Unit)

门控循环单元(GRU)旨在解决标准RNN中出现的梯度消失问题。CRU背后的原理很LSTM非常相似,可以看作LSTM的变体。

CRU有两个门:重置门(reset gate)和更新门(update gate)。重置门决定了如何将新的输入信息与前面的记忆结合,更新门定义了前面记忆保存到当前时间步的量。

 

9、Bidirectional RNN

在电影点评的情感分类任务中,有评论:the movie was terribly exciting!当RNN只有一个方向,从左往右读取时,terribly则会被理解成负面评论,然后真实情况是 terribly exciting = very exciting。由此,我们不仅仅需要考虑过去的信息,也需要考虑未来的信息。由此,双向RNN被提出。对于双向的RNN,需要输出的是完整的句子,而语言模型任务只有左边的信息不是完整的句子,故而不适用双向RNN。

10、Multi-layer RNN

11、RNN小例子:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

#载入数据集
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)

#输入图片是28*28
n_inputs = 28 #输入一行,一行有28个数据
max_time = 28 #一共28行
lstm_size = 100#隐层单元
n_classes  = 10 #10个分类
batch_size = 50#每个批次50个样本
n_batch = mnist.train.num_examples //batch_size #计算一共有多少批次

#这里的none表示第一个维度可以是任意长度
x = tf.placeholder(tf.float32,[None,784])
#正确的标签
y = tf.placeholder(tf.float32,[None,10])

#初始化权值
weights = tf.Variable(tf.truncated_normal([lstm_size,n_classes],stddev=0.1))
#初始化偏置值
biases = tf.Variable(tf.constant(0.1,shape=[n_classes]))

#定义RNN网络
def RNN(X, weights, biases):
    #inputs=[batch_size, max_time, n_inputs]
    inputs = tf.reshape(X,[-1,max_time,n_inputs])
    #定义LSTM基本CELL
    lstm_cell = tf.contrib.rnn.core_rnn_cell.BasicLSTMCell(lstm_size)
    #final_state[state,batch_size,cell.state_size]
    #final_state[0]是cell state
    #final_state[1]是hidden_state
    #outputs:The RNN output 'Tensor'
    #  If time_major == False(default), this will be a 'Tensor' shaped:
    #      [batch_size,max_time,cell.output_size]
    #  If time_major == Ture, this will be a 'Tensor' shaped:
    #      [max_time,batch_size,cell.output_size]
    outputs,final_state= tf.nn.dynamic_rnn(lstm_cell,inputs,dtype=tf.float32)
    results = tf.nn.softmax(tf.matmul(final_state[1],weights)+biases)
    return results

#计算RNN的返回结果
prediction = RNN(x,weights,biases)

#损失函数
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y))
#使用AdamOpimizer进行优化
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#argmax返回一维张量中最大值的位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#把correct_prediction变为float32类型

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(6):
        for batch in range(n_batch):
            batch_xs,batch_ys = mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})

        acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
        print("Iter"+str(epoch)+",Testing Accuracy="+str(acc))

参考资料:

https://zhuanlan.zhihu.com/p/101928642

https://www.bilibili.com/video/av46216519?p=7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值