一、文本预处理
文本是一类序列数据,一篇文章可以看作是字符或单词的序列,本节将介绍文本数据的常见预处理步骤,预处理通常包括四个步骤:
- 读入文本
- 分词
- 建立字典,将每个词映射到一个唯一的索引(index)
- 将文本从词的序列转换为索引的序列,方便输入模型
其中建立字典需要经过的步骤为:
- 去重,统计词频
- 筛掉部分词
- 添加一些特殊的token
- 将token映射到唯一索引
- 将索引映射到token
二、语言模型
一段自然语言文本可以看作是一个离散时间序列,给定一个长度为T的词的序列w1,w2,…,wTw1,w2,…,wT,语言模型的目标就是评估该序列是否合理,即计算该序列的概率:
这里介绍基于统计的语言模型,主要是n元语法(nn-gram)。
假设每个词是依次出现的,则有:
语言模型的参数就是词的概率以及给定前几个词情况下的条件概率。设训练数据集为一个大型文本语料库,词的概率可以通过该词在训练数据集中的相对词频来计算:
n元语法
n元语法通过马尔可夫假设简化模型实现,马尔科夫假设是指一个词的出现只与前面n个词相关,即n阶马尔可夫链(Markov chain of order n),基于n−1阶马尔可夫链,我们可以将语言模型改写为:
然而n元语法存在的问题是:当n较小时结果不准确;当n较大时需要计算并存储大量的词频和多词相邻频率。并且n元语法往往是数据稀疏的。
如果序列的长度为T,时间步数为n,那么一共有T−n个合法的样本,但是这些样本有大量的重合,通常采用更加高效的采样方式。有两种方式对时序数据进行采样,分别是随机采样和相邻采样。
随机采用
每次从数据里随机采样一个小批量。其中批量大小batch_size
是每个小批量的样本数,num_steps
是每个样本所包含的时间步数。 在随机采样中,每个样本是原始序列上任意截取的一段序列,相邻的两个随机小批量在原始序列上的位置不一定相毗邻。
相邻采样
相邻的两个随机小批量在原始序列上的位置相毗邻。
三、循环神经网络基础
普适逼近定理
一个具有至少一层隐藏层的前馈神经网络,并且隐藏层包含有限的神经元,它可以以任意精度逼近一个定义在Rn的闭集里的连续函数。
前提是这个前馈神经网络的激活函数满足某些性质。比如Sigmoid函数,Tanh函数和Relu函数。
循环神经网络的构造
下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量H,用Ht表示H在时间步tt的值。Ht的计算基于Xt和Ht−1,可以认为Ht记录了到当前字符为止的序列信息,利用Ht对序列的下一个字符进行预测。
由于引入了Ht−1Whh,Ht能够捕捉截至当前时间步的序列的历史信息,就像是神经网络当前时间步的状态或记忆一样。由于Ht的计算基于Ht−1,上式的计算是循环的,使用循环计算的网络即循环神经网络(recurrent neural network)。
在时间步t,输出层的输出为:
剪裁梯度
循环神经网络中较容易出现梯度衰减或梯度爆炸,这会导致网络几乎无法训练。裁剪梯度(clip gradient)是一种应对梯度爆炸的方法。假设我们把所有模型参数的梯度拼接成一个向量 g,并设裁剪的阈值是θ。裁剪后的梯度为:
其中剪裁后梯度的L2范数不超过θ。
困惑度
困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,
- 最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
- 最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
- 基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。
显然,任何一个有效模型的困惑度必须小于类别个数。
定义模式训练函数
与之前的模型训练函数相比,这里的模型训练函数有以下几点不同:
- 使用困惑度评价模型。
- 在迭代模型参数前裁剪梯度。
- 对时序数据采用不同采样方法将导致隐藏状态初始化的不同。
当然,除了语言模型,循环神经网络还可以应用于其他任务,比如:
- 序列标注
- 文本分类
- 词和句子编码
- 文本生成