# 使用循环神经网语言模型生成文本 语言模型(Language Model)是一个概率分布模型,简单来说,就是用来计算一个句子的概率的模型。利用它可以确定哪个词序列的可能性更大,或者给定若干个词,可以预测下一个最可能出现的词。语言模型是自然语言处理领域里一个重要的基础模型。 ## 应用场景 **语言模型被应用在很多领域**,如: * **自动写作**:语言模型可以根据上文生成下一个词,递归下去可以生成整个句子、段落、篇章。 * **QA**:语言模型可以根据Question生成Answer。 * **机器翻译**:当前主流的机器翻译模型大多基于Encoder-Decoder模式,其中Decoder就是一个待条件的语言模型,用来生成目标语言。 * **拼写检查**:语言模型可以计算出词序列的概率,一般在拼写错误处序列的概率会骤减,可以用来识别拼写错误并提供改正候选集。 * **词性标注、句法分析、语音识别......** ## 关于本例 本例实现基于RNN的语言模型,以及利用语言模型生成文本,本例的目录结构如下: ```text . ├── data │ └── train_data_examples.txt # 示例数据,可参考示例数据的格式,提供自己的数据 ├── config.py # 配置文件,包括data、train、infer相关配置 ├── generate.py # 预测任务脚本,即生成文本 ├── beam_search.py # beam search 算法实现 ├── network_conf.py # 本例中涉及的各种网络结构均定义在此文件中,希望进一步修改模型结构,请修改此文件 ├── reader.py # 读取数据接口 ├── README.md ├── train.py # 训练任务脚本 └── utils.py # 定义通用的函数,例如:构建字典、加载字典等 ``` ## RNN 语言模型 ### 简介 RNN是一个序列模型,基本思路是:在时刻$t$,将前一时刻$t-1$的隐藏层输出和$t$时刻的词向量一起输入到隐藏层从而得到时刻$t$的特征表示,然后用这个特征表示得到$t$时刻的预测输出,如此在时间维上递归下去。可以看出RNN善于使用上文信息、历史知识,具有“记忆”功能。理论上RNN能实现“长依赖”(即利用很久之前的知识),但在实际应用中发现效果并不理想,研究提出了LSTM和GRU等变种,通过引入门机制对传统RNN的记忆单元进行了改进,弥补了传统RNN在学习长序列时遇到的难题。本例模型使用了LSTM或GRU,可通过配置进行修改。下图是RNN(广义上包含了LSTM、GRU等)语言模型“循环”思想的示意图:
### 模型实现 本例中RNN语言模型的实现简介如下: - **定义模型参数**:`config.py`中定义了模型的参数变量。 - **定义模型结构**:`network_conf.py`中的`rnn_lm`**函数**中定义了模型的**结构**,如下: - 输入层:将输入的词(或字)序列映射成向量,即词向量层: `embedding`。 - 中间层:根据配置实现RNN层,将上一步得到的`embedding`向量序列作为输入。 - 输出层:使用`softmax`归一化计算单词的概率。 - loss:定义多类交叉熵作为模型的损失函数。 - **训练模型**:`train.py`中的`main`方法实现了模型的训练,实现流程如下: - 准备输入数据:建立并保存词典、构建train和test数据的reader。 - 初始化模型:包括模型的结构、参数。 - 构建训练器:demo中使用的是Adam优化算法。 - 定义回调函数:构建`event_handler`来跟踪训练过程中loss的变化,并在每轮训练结束时保存模型的参数。 - 训练:使用trainer训练模型。 - **生成文本**:`generate.py` 实现了文本的生成,实现流程如下: - 加载训练好的模型和词典文件。 - 读取`gen_file`文件,每行是一个句子的前缀,用[柱搜索算法(Beam Search)](https://github.com/PaddlePaddle/book/blob/develop/08.machine_translation/README.cn.md#柱搜索算法)根据前缀生成文本。 - 将生成的文本及其前缀保存到文件`gen_result`。 ## 使用说明 运行本例的方法如下: * 1,运行`python train.py`命令,开始train模型(默认使用RNN),待训练结束。 * 2,运行`python generate.py`运行文本生成。(输入的文本默认为`data/train_data_examples.txt`,生成的文本默认保存到`data/gen_result.txt`中。) **如果需要使用自己的语料、定制模型,需要修改`config.py`中的配置,细节和适配工作详情如下:** ### 语料适配 * 清洗语料:去除原文中空格、tab、乱码,按需去除数字、标点符号、特殊符号等。 * 内容格式:每个句子占一行;每行中的各词之间使用一个空格符分开。 * 按需要配置`config.py`中的如下参数: ```python train_file = "data/train_data_examples.txt" test_file = "" vocab_file = "data/word_vocab.txt" model_save_dir = "models" ``` 1. `train_file`:指定训练数据的路径,**需要预先分词**。 2. `test_file`:指定测试数据的路径,如果训练数据不为空,将在每个 `pass` 训练结束对指定的测试数据进行测试。 3. `vocab_file`:指定字典的路径,如果字典文件不存在,将会对训练语料进行词频统计,构建字典。 4. `model_save_dir`:指定模型保存的路径,如果指定的文件夹不存在,将会自动创建。 ### 构建字典的策略 - 当指定的字典文件不存在时,将对训练数据进行词频统计,自动构建字典`config.py` 中有如下两个参数与构建字典有关: ```python max_word_num = 51200 - 2 cutoff_word_fre = 0 ``` 1. `max_word_num`:指定字典中含有多少个词。 2. `cutoff_word_fre`:字典中词语在训练语料中出现的最低频率。 - 加入指定了 `max_word_num = 5000`,并且 `cutoff_word_fre = 10`,词频统计发现训练语料中出现频率高于10次的词语仅有3000个,那么最终会取3000个词构成词典。 - 构建词典时,会自动加入两个特殊符号: 1. `