目录 |
---|
面板 | ||||
---|---|---|---|---|
| ||||
原文链接 : https://www.tensorflow.org/tutorials/recurrent 译文链接 : http://www.apache.wiki/pages/viewpage.action?pageId=10029465 校对:Ngxin |
语言模型
在本教程中,我们将展示如何在语言建模的挑战性任务上训练经常性神经网络。问题的目标是拟合一个将概率分配给句子的概率模型。它通过预测给定历史的历史的文本中的下一个单词来做到这一点。为此,我们将使用在本教程中,我们将展示如何在具有一定挑战性的语言模型任务上训练循环神经网络。该目标是拟合一个能确定语句概率的概率模型。它通过预测给定历史文本中的下一个单词来做到这一点。为此,我们将使用Penn Tree Bank (PTB)数据集,该数据集是测量这些模型质量的流行基准,同时小而且速度相对较快。 (PTB)数据集,该数据集是测量模型质量的常用基准,数据集小,训练速度相对较快。
语言建模是许多有趣的问题,如语音识别,机器翻译或图像字幕的关键。这也很有趣 语言建模是许多有趣问题的关键,如语音识别,机器翻译或图像字幕。这很有趣 - 看看这里。
为了本教程的目的,我们将重现 Zaremba等人,2014 (pdf)的结果,在PTB数据集上实现了非常好的质量。本教程的目的将重现 Zaremba et al., 2014 (pdf)的结果,在PTB数据集上实现了非常好的效果。
教程文件
本教程引用了TensorFlow模型回购本教程 以下文件来自TensorFlow models repo中的 models/tutorials/rnn/ptb 中的以下文件:ptb:
文件 | 目的 |
---|---|
ptb_word_lm.py | 在PTB数据集上训练语言模型的代码。 |
reader.py | 读取数据集的代码。 |
下载并准备数据
本教程所需的data/
数据位于Tomas Mikolov的网页PTB数据集的目录中:http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
数据集已经预处理并含有整体10000个不同的词,包括结束句子的标记和用于罕见词语的特殊符号(本教程所需的数据位于 PTB dataset from Tomas Mikolov's webpage的data/
目录中。数据集已经预处理并含有10000个不同的词,包括结束句子的标记和用于罕见词语的特殊符号(\ <UNK>)。在reader.py
,我们将每个单词转换为唯一的整数标识符,以便使神经网络容易处理数据。中,我们将每个单词转换为唯一的整数标识符,以便使神经网络容易处理数据。
模型
LSTM
模型的核心包括一次处理一个单词的LSTM单元,并计算句子中下一个单词的可能值的概率。网络的内存状态以零向量初始化,读取每个单词后更新。出于计算原因,我们将以小批量的尺寸处理数据模型的核心包括处理当前单词的LSTM单元,并计算句子中下一个单词的可能值的概率。网络的内存状态以零向量初始化,读取每个单词后更新。出于计算原因,我们将以batch_size
。小批量的规模处理数据。
基本的伪代码如下:
代码块 | ||
---|---|---|
| ||
lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size) # Initial state of the LSTM memory. state = tf.zeros([batch_size, lstm.state_size]) probabilities = [] loss = 0.0 for current_batch_of_words in words_in_dataset: # The value of state is updated after processing each batch of words. output, state = lstm(current_batch_of_words, state) # The LSTM output can be used to make next word predictions logits = tf.matmul(output, softmax_w) + softmax_b probabilities.append(tf.nn.softmax(logits)) loss += loss_function(probabilities, target_words) |
截断反向传播
通过设计,循环神经网络(RNN)的输出取决于任意远距离的输入。不幸的是,这使得反向传播计算困难。为了使学习过程易于处理,通常的做法是创建一个“展开式”版本的网络,其中包含一个固定数量的(通过设计,循环神经网络(RNN)的输出取决于任意距离的输入。糟糕的是,这使得反向传播计算困难。为了使学习过程易于处理,通常的做法是创建一个“展开式”版本的网络,其中包含一个固定数量的(num_steps
)LSTM输入和输出。然后对RNN的这种有限近似进行训练。这可以通过一次馈送长度的输入)LSTM输入和输出。然后模型训练无限接近于RNN。这可以通过输入num_steps
并且在每个这样的输入块之后执行后向通过来实现。长度并且在每个这样的输入块之后执行反向传播通过来实现。
这是一个用于创建执行截断反向传播的图形的简化代码块:这是一个用于创建执行截断反向传播图形的简化代码块:
代码块 | ||
---|---|---|
| ||
# Placeholder for the inputs in a given iteration. words = tf.placeholder(tf.int32, [batch_size, num_steps]) lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size) # Initial state of the LSTM memory. initial_state = state = tf.zeros([batch_size, lstm.state_size]) for i in range(num_steps): # The value of state is updated after processing each batch of words. output, state = lstm(words[:, i], state) # The rest of the code. # ... final_state = state |
这就是如何在整个数据集上实现一个迭代:
代码块 | ||
---|---|---|
| ||
# A numpy array holding the state of LSTM after each batch of words. numpy_state = initial_state.eval() total_loss = 0.0 for current_batch_of_words in words_in_dataset: numpy_state, current_loss = session.run([final_state, loss], # Initialize the LSTM state from the previous iteration. feed_dict={initial_state: numpy_state, words: current_batch_of_words}) total_loss += current_loss |
输入
在输入LSTM之前,单词ID将被嵌入密集表示(参见 之前,单词ID将被嵌入形成密集表示(参见 向量表示教程)。这使得模型能够有效地表达关于特定单词的知识。这也很容易写:)。这使得模型能够有效地表达关于特定单词的知识。这很容易:
代码块 | ||
---|---|---|
| ||
# embedding_matrix is a tensor of shape [vocabulary_size, embedding size] word_embeddings = tf.nn.embedding_lookup(embedding_matrix, word_ids) |
嵌入矩阵将被随机初始化,模型将通过查看数据来学习区分单词的含义。
损失函数
我们要最小化目标词的平均负对数概率:
这不是很难实现,但功能 这不是很难实现,且函数 sequence_loss_by_example
已经可用,所以我们可以在这里使用它。已经存在,所以我们可以在这里使用它。
报告中报告的典型措施是平均每字困惑(通常称为困惑),等于论文中的典型衡量标准是平均per-word困惑(通常称为困惑),等于
我们将在整个培训过程中监控其价值。我们将在整个训练过程中监控困惑值。
堆叠多个LSTM堆叠多个LSTM层
为了使模型更具表现力,我们可以添加多层LSTM来处理数据。第一层的输出将成为第二层的输入,依此类推。
我们有一个类叫做MultiRNNCell
实现无缝:为了使模型性能更加,我们可以添加多层LSTM来处理数据。第一层的输出将成为第二层的输入,依此类推。
我们有一个叫做MultiRNNCell的类
可以无缝实现:
代码块 | ||
---|---|---|
| ||
lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size, state_is_tuple=False) stacked_lstm = tf.contrib.rnn.MultiRNNCell([lstm] * number_of_layers, state_is_tuple=False) initial_state = state = stacked_lstm.zero_state(batch_size, tf.float32) for i in range(num_steps): # The value of state is updated after processing each batch of words. output, state = stacked_lstm(words[:, i], state) # The rest of the code. # ... final_state = state |
运行代码
首先从GitHub 克隆TensorFlow模型回购。您还需要下载PTB数据集,如本教程开头所述; 我们假设数据集位于/tmp/simple-examples/data
。
运行以下命令:
运行代码之前先下载PTB数据集,就像教程刚开始的说的那样,然后在你的主目录下解压该数据集,如下所示:
代码块 | ||
---|---|---|
| ||
tar xvfz simple-examples.tgz -C $HOME |
(注意:在windows操作系统中你需要使用其他工具)
现在,从GitHub 克隆TensorFlow models repo。运行以下命令:
代码块 | ||
---|---|---|
| ||
cd models/tutorials/rnn/ptb python ptb_word_lm.py --data_path=/tmp/simple-examples/data/ --model=small |
教程代码中有3种支持的型号配置:“small”,“medium”和“large”。它们之间的区别在于LSTM的大小和用于训练的一组超参数。
模型越大,应该得到的结果越好。该small
模型应该能够在测试集上达到低于120的困惑,80以下的模式可能会达到困难large
,尽管训练可能需要几个小时。
模型应该能够在测试集上达到低于120的困惑,large模式下该值会低于80
,但训练可能需要几个小时。
下一步?
有几个技巧,我们没有提到,使模型更好,包括:
- 降低学习率表,随时间降低学习率,
- LSTM层之间的差距。LSTM层间的dropout。
研究代码并进行修改,以进一步改进模型。研究代码并修改,以进一步改进模型。