在 TensorFlow 1.x 上用 LSTM 训练 PTB 语言模型:循环神经网络实战教程 文档开发工具教程【免费下载链接】docsTensorFlow documentation项目地址https://gitcode.com/gh_mirrors/doc/docs点击查看免费下载本篇技术指南以 TensorFlow 1.x 官方文档为骨架完整讲解如何基于 Penn Tree BankPTB语料训练一个循环神经网络RNN语言模型覆盖数据准备、LSTM 单元搭建、截断反向传播、嵌入层、损失函数与困惑度评估、多层 LSTM 堆叠以及最终的训练运行与调优适用于希望掌握序列建模与 TensorFlow 1.x RNN 编程实战的开发者。语言建模任务定义与价值语言建模Language Modeling的核心目标是拟合一个概率模型使其能够为句子分配概率。具体做法是给定一段历史词序列模型预测下一个词出现的概率分布。这一能力是语音识别、机器翻译、图像描述image captioning等众多任务的公共基础。本教程采用的基准数据集是Penn Tree BankPTB。它虽然体量较小、训练速度快却是评估语言模型质量的经典基准非常适合作为入门与复现实验的载体。教程的目标是复现 Zaremba 等人 2014 年论文Recurrent Neural Network Regularization中在 PTB 数据集上取得的高质量结果。教程文件一览本教程对应的完整可运行代码位于 TensorFlow models 仓库的models/tutorials/rnn/ptb目录包含两个核心文件文件用途ptb_word_lm.py在 PTB 数据集上训练语言模型的全部代码reader.py读取与预处理数据集的辅助代码其中ptb_word_lm.py负责构建计算图词嵌入、LSTM 单元、损失与优化器、驱动训练循环并按周期输出困惑度reader.py负责将原始文本文件切分成词序列、转换为整数 ID并以 batch 形式提供给训练过程。下载与准备 PTB 数据教程使用的数据位于 PTB 数据集simple-examples.tgz的data/目录中。该数据集已经完成预处理整体词表规模为10000 个不同的词其中包含句末标记end-of-sentence marker以及一个用于表示罕见词的专用符号unk。在reader.py中每个词都会被转换为一个唯一的整数标识符integer id。这种词 → 整数 ID的映射是后续嵌入层embedding layer工作的前提神经网络无法直接消费字符串必须先完成符号数字化。模型设计LSTM 逐词处理与批数据布局模型的核心是一个LSTM 单元tf.contrib.rnn.BasicLSTMCell它逐词处理输入序列并为句中的每个位置计算下一个词的候选概率分布。网络的记忆状态memory state初始化为全零向量并在每读取一个词之后被更新。出于计算效率考虑数据按大小为batch_size的小批量mini-batch处理。这里有一个极易混淆的关键点batch 中的词并不对应一个句子。准确地说batch 中每一列词应该对应同一个时间步t。TensorFlow 会自动为你完成每个 batch 的梯度求和。以一个直观的例子说明数据布局batch_size 2, time_steps 5t0 t1 t2 t3 t4 [The, brown, fox, is, quick] [The, red, fox, jumped, high] words_in_dataset[0] [The, The] words_in_dataset[1] [brown, red] words_in_dataset[2] [fox, fox] words_in_dataset[3] [is, jumped] words_in_dataset[4] [quick, high]也就是说words_in_dataset[t]是一个长度为batch_size的向量其所有元素都来自时间步t。这种按时间步切分、跨样本对齐的布局是 RNN 批处理的标准范式。基础实现伪代码words_in_dataset tf.placeholder(tf.float32, [time_steps, batch_size, num_features]) lstm tf.contrib.rnn.BasicLSTMCell(lstm_size) # Initial state of the LSTM memory. state lstm.zero_state(batch_size, dtypetf.float32) 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)代码要点words_in_dataset的形状为[time_steps, batch_size, num_features]第一个维度正是时间步与上述数据布局呼应每次调用lstm(current_batch_of_words, state)返回(output, state)其中更新后的state会作为下一次调用的输入形成时间维度上的状态传递LSTM 的output经线性变换softmax_w、softmax_b得到 logits再经tf.nn.softmax转为概率训练中真正使用的方式是逐时间步循环而不是一次性把整个序列塞入tf.placeholder后者在截断反向传播中另有讲究见下一节。截断反向传播Truncated Backpropagation从设计上看RNN 的输出依赖于任意久远的输入这使得标准反向传播的计算变得困难。为了让学习过程可行业界普遍采用一种常见做法构建一个**展开unrolled的有限版本网络**其中包含固定数量num_steps的 LSTM 输入与输出并在这段有限近似上训练。实现方式是每次喂入长度为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 lstm.zero_state(batch_size, dtypetf.float32) 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注意此处的words形状为[batch_size, num_steps]与上一节演示的[time_steps, batch_size, num_features]不同——它按words[:, i]取第i个时间步的所有 batch 样本。final_state是处理完num_steps个词之后的状态。在整个数据集上的迭代实现如下# 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关键设计由于截断反向传播只回溯num_steps步跨块的历史信息无法通过计算图自动传播。因此这里用initial_state.eval()把上一块的final_state保存为 numpy 数组并在下一块通过feed_dict重新注入。这样状态信息在块与块之间依然能够持续流动而梯度传播被限制在单块内部兼顾了长程记忆与训练可行性。输入词向量嵌入Embedding在送入 LSTM 之前词 ID 会被嵌入到一个稠密表示dense representation中原理可参考 词向量表示word2vec教程。嵌入允许模型高效地表达特定词的知识并且实现非常简洁# embedding_matrix is a tensor of shape [vocabulary_size, embedding size] word_embeddings tf.nn.embedding_lookup(embedding_matrix, word_ids)embedding_matrix会被随机初始化模型仅通过观察数据本身就能学会区分不同词的语义。这与仓库中 嵌入指南 的表述一致嵌入是将词等离散对象映射到实数向量训练结束后embedding_matrix中即存放词表中每个词的稠密向量。损失函数与困惑度Perplexity训练目标是最小化目标词的平均负对数概率$$ \text{loss} -\frac{1}{N}\sum_{i1}^{N} \ln p_{\text{target}_i} $$该函数实现并不困难但 TensorFlow 已提供现成的sequence_loss_by_example函数直接调用即可。论文中通常报告的指标是每个词的平均困惑度perplexity常简称 perplexity它与 loss 的关系为$$e^{-\frac{1}{N}\sum_{i1}^{N} \ln p_{\text{target}_i}} e^{\text{loss}}$$困惑度可以直观理解为模型在每个词位置上的平均候选词数不确定性困惑度越低模型对下一个词的预测越确定质量越高。训练全程需要持续监控该值。堆叠多层 LSTM为了赋予模型更强的表达能力可以在数据上叠加多个 LSTM 层第一层的输出成为第二层的输入依此类推。TensorFlow 提供的MultiRNNCell让这一过程无缝衔接def lstm_cell(): return tf.contrib.rnn.BasicLSTMCell(lstm_size) stacked_lstm tf.contrib.rnn.MultiRNNCell( [lstm_cell() for _ in range(number_of_layers)]) 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注意MultiRNNCell.zero_state返回的是多层状态的元组由stacked_lstm内部统一管理各层的隐藏状态与记忆状态调用方无需手动拆分。运行完整训练代码运行前先下载并解压 PTB 数据集到主目录下tar xvfz simple-examples.tgz -C $HOMEWindows 环境下可能需要借助其他解压工具。然后克隆 TensorFlow models 仓库进入 PTB 示例目录并启动训练cd models/tutorials/rnn/ptb python ptb_word_lm.py --data_path$HOME/simple-examples/data/ --modelsmall模型配置small / medium / large教程代码内置 3 种受支持的模型配置small、medium与large。它们的差异在于 LSTM 的尺寸以及训练所用的超参数集合。配置说明small尺寸最小、训练最快测试集上困惑度应能降到120 以下medium尺寸与超参数介于两者之间large尺寸最大测试集上困惑度应能降到80 以下但可能需要数小时训练总体上模型越大、效果越好small模型在测试集上的困惑度低于 120large模型低于 80后者需要数小时训练时间。这一预期与 Zaremba 等人论文的报告一致可作为复现实验的验收基准。进一步优化方向本教程尚未提及两个能显著改善模型的技巧递减学习率调度decreasing learning rate schedule在训练后期逐步降低学习率有助于模型收敛到更优解LSTM 层间 Dropout在多层 LSTM 之间引入 dropout 正则化可有效缓解过拟合。建议仔细研读ptb_word_lm.py的代码并动手修改以进一步改进模型效果。值得一提的是从本仓库的 TensorFlow 1.x 性能指南RNN Performance 一节 可以看出tf.contrib.rnn.BasicLSTMCell被视为参考实现在 NVIDIA GPU 上优先考虑tf.contrib.cudnn_rnn通常比BasicLSTMCell快一个数量级以上、内存占用少 3~4 倍在 CPU、移动设备上则可用tf.contrib.rnn.LSTMBlockFusedCell获得最佳速度与内存效率。理解这些取舍有助于在完成本教程后针对更大规模的序列任务做进一步工程优化。赞分享文档开发工具教程【免费下载链接】docsTensorFlow documentation项目地址https://gitcode.com/gh_mirrors/doc/docs点击查看免费下载相关推荐CANN驱动Ascend950网络工具Commands List Query Commands Querying hccn\_tool Help Information https://link.g驱动开发人工智能CANNAudacity 免费开源音频编辑器录音、降噪与导出完整实用手册Audacity 免费开源音频编辑器录音、降噪与导出完整实用手册 Audacity 是一款免费的开源音频软件与跨平台音频编辑器支持录音、音频降噪、多轨混音与音频处理桌面应用音视频gradient-checkpointing实战教程在TensorFlow中训练超大规模神经网络gradient checkpointing实战教程在TensorFlow中训练超大规模神经网络 想要训练超大规模神经网络却总是遇到内存不足的问题gradi上一篇突破最优传输效率瓶颈POT库中5类求解器的深度对比与实战指南下一篇sqlpp11项目深度解析高效使用预处理语句提升数据库操作性能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考