赞
踩
在语言模型任务中,给定特定的单词序列(句子片段),任务目标是预测该片段的下一个单词(或者符号)。传统的n-gram模型可以应用于该任务,但是它存在着许多难以解决的问题:假设预测序列为 Tom open his ___
①强假设问题:n-gram模型的构建依赖于过强的假设,即假设待预测的第n各单词只依赖于它之前的n-1个单词,即:
②稀疏问题:由于n-gram模型的预测靠的是第对条件概率:
如果分子统计量为0,则预测概率会被模型直接置为0;如果分母的统计量为0,则无法正确地计算预测概率。当我们试图通过增大n-gram模型中的参数n来扩展待预测单词的语境以达到更好的效果是,稀疏问题会变得愈发严重。
③存储问题:为了更好得到n-gram模型,我们需要对训练语料中的所有n元组进行计算并存储相关数据;当n或者语料增大时,模型大小也会随之增大。
面对传统n-gram模型的种种问题,我们希望得到一个不依赖于过强假设、不会出现稀疏问题、可以更好利用语境与句中的长距离依赖关系、且模型的大小不会随着输入的变化而变化的模型。由此引入RNN模型。
Recurrent Neural Networks(RNN)是一类神经网络结构,最基础的RNN结构如下:
最基础的RNN模型分为上中下三层。中间的红色部分称为隐藏层,每个红色方框表示一个隐藏状态。RNN的特点:每个隐藏状态的值都依赖于它前一个隐藏状态
和当前状态的输入值
,并且模型中很多参数都是共享的。所谓共享是指,虽然模型中不同的隐藏状态处于不同的位置,但是他们的输入、输出、以及状态转移时所使用的参数矩阵
是相同的。并且由于RNN结构中隐藏状态的处理在时间上是有先后顺序,只有处理完前一个隐藏状态才能处理当前的状态,因此隐藏状态又被称为时间步。
①首先,给定一个输入句子,可以通过查词库得到每个单词
的one-hot向量表示
;之后,利用词向量矩阵E得到每个单词对应的词向量
,d表示词向量的维度;
②然后,有了输入的词向量之后,按照顺序对每个隐藏状态进行计算:
其中,表示隐藏状态的维度,
表示隐藏状态间的转换矩阵,
表示输入与隐藏层间的转换矩阵;
③最后,通过softmax层给出模型对单词概率的预测,其中,U表示从隐藏层到输出之间的权重矩阵。
以任务预测句子 the student opened their ___ 的下一个单词为例,其过程如下图所示:
优点:
①可以处理任意长度的输入,且模型大小不会随着输入的增长而变化;模型中的参数量是固定的,与输入大小无关。
②理论上,对隐藏状态进行计算时,可以利用多步之前的信息。
缺点:
①计算缓慢:必须计算完迁移状态才能计算当前状态,我们只能序列化的计算所有状态而无法利用并行算法加速计算。
②虽然理论上RNN可以利用多步以前的信息,然而实践当中很难做到这一点。
梯度消失:随着反向传播的前进,梯度越来越小,小到几乎为0。这样远小于来自附近的梯度信息的来自远处的梯度信息就会丢失,模型的权重参数也就只受附近信息的影响,而不受远处信息的影响。
梯度爆炸:反向传播时梯度的数值迅速变得非常巨大。
对于梯度爆炸的解决方法:
假设对于代价函数J(W, b)的梯度图如图所示:
对于含有陡峭悬崖的梯度模型,需要进行梯度阶段(Gradient Clipping)。其中红色的点为最优值的位置,如果使用梯度截断法(如右图),则可以使梯度在接近悬崖时降低步伐(学习率衰减),如果不使用梯度截断法(如左图),则可能由于过大的学习率使当前的参数被”抛出“曲面。
LSTM是一种时间循环神经网络,是为了解决一般的RNN存在的梯度消失问题而专门设计出来的。
输入门:对输入的信息进行选择性的输入;遗忘门:对前一状态的信息进行选择性的记忆;输出门:对当前状态的信息进行选择性的输出;记忆单元:存储历史信息。
LSTM向前传递的更新公式:
整体的LSTM序列:
一个LSTM单元的内部详细结构图:
门控循环单元(GRU)旨在解决标准RNN中出现的梯度消失问题。CRU背后的原理很LSTM非常相似,可以看作LSTM的变体。
CRU有两个门:重置门(reset gate)和更新门(update gate)。重置门决定了如何将新的输入信息与前面的记忆结合,更新门定义了前面记忆保存到当前时间步的量。
在电影点评的情感分类任务中,有评论:the movie was terribly exciting!当RNN只有一个方向,从左往右读取时,terribly则会被理解成负面评论,然后真实情况是 terribly exciting = very exciting。由此,我们不仅仅需要考虑过去的信息,也需要考虑未来的信息。由此,双向RNN被提出。对于双向的RNN,需要输出的是完整的句子,而语言模型任务只有左边的信息不是完整的句子,故而不适用双向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))

参考资料:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。