《动手学深度学习》文本预处理、语言模型、循环神经网络基础
文本预处理、语言模型、循环神经网络基础
文本预处理
文本是一类序列数据,一篇文章可以看作是字符或单词的序列,本节将介绍文本数据的常见预处理步骤,预处理通常包括四个步骤:
1.读入文本
2.分词
3.建立字典,将每个词映射到一个唯一的索引(index)
4.将文本从词的序列转换为索引的序列,方便输入模型
现有工具
我们前面介绍的分词方式非常简单,它至少有以下几个缺点:标点符号通常可以提供语义信息,但是我们的方法直接将其丢弃了类似“shouldn’t", “doesn’t"这样的词会被错误地处理类似"Mr.”, "Dr."这样的词会被错误地处理我们可以通过引入更复杂的规则来解决这些问题,但是事实上,有一些现有的工具可以很好地进行分词:spaCy和NLTK。
语言模型与数据集
一段自然语言文本可以看作是一个离散时间序列,给定一个长度为的词的序列,语言模型的目标就是评估该序列是否合理,即计算该序列的概率:
假设序列中的每个词是依次生成的,我们有
如还有4个词的文本序列概率:
语言模型的参数就是词的概率以及给定前几个词情况下的条件概率。我们可以维护一个大型文本语料库,词的概率通过该词在语料库中的相对词频计算:
其中为语料库中以作为第一个词,作为第二个词的文本的数量。
n元语法
在此引入马尔科夫假设:一个词的出现只与前面个词相关,即阶马尔可夫链(Markov chain of order ),在语言模型中使用阶马尔科夫链,模型可改写为:
以上也叫元语法。如当,含有4个词的文本序列概率:
当分别为1、2和3时,我们将其分别称作一元语法(unigram)、二元语法(bigram)和三元语法(trigram)。
思考:元语法可能有哪些缺陷?
1.参数空间过大
2.数据稀疏
时序数据的采样
在训练中我们需要每次随机读取小批量样本和标签。
形式如:
:“想要有直升”,:“要有直升机”
:“要有直升机”,:“有直升机,”
:“有直升机,”,:“直升机,想”
…
:“要和你飞到”,:“和你飞到宇”
:“和你飞到宇”,:“你飞到宇宙”
:“你飞到宇宙”, :“飞到宇宙去”
其中时间步数为5,即每次取5个字符。其标签为向后走一步的5个字符,即预测字符数为1。
可以看到,如果序列的长度为,时间步数为,那么一共有个合法的样本,但是这些样本有大量的重合,我们通常采用更加高效的采样方式。
我们有两种方式对时序数据进行采样,分别是随机采样和相邻采样。
随机采样
在随机采样中,每个样本是原始序列上任意截取的一段序列,相邻的两个随机小批量在原始序列上的位置不一定相毗邻。
我们以,30个数字的序列为例,批量大小(batch_size)为2,时间步数(num_steps)为6。
首先按时间步数将序列分组:(向下取整),分为4组,丢弃后面其他数。其中为标签预留预测空间。
在分好的组中随机选择batch_size个样本,并取对应标签。
如第一批随机取到第2组和第3组,第二批随机取到第1组和第4组:
X: tensor([[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17]])
Y: tensor([[ 7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18]])
X: tensor([[ 0, 1, 2, 3, 4, 5],
[18, 19, 20, 21, 22, 23]])
Y: tensor([[ 1, 2, 3, 4, 5, 6],
[19, 20, 21, 22, 23, 24]])
相邻采样
在相邻采样中,相邻的两个随机小批量在原始序列上的位置相毗邻。
继续使用上面的例子,,30个数字的序列,。
首先按将原序列分为2组,每组个,向下取整其余从数列后面丢弃,每次取样在对应的组上按顺序取出。
则此处取处结果:
X: tensor([[ 0, 1, 2, 3, 4, 5],
[15, 16, 17, 18, 19, 20]])
Y: tensor([[ 1, 2, 3, 4, 5, 6],
[16, 17, 18, 19, 20, 21]])
X: tensor([[ 6, 7, 8, 9, 10, 11],
[21, 22, 23, 24, 25, 26]])
Y: tensor([[ 7, 8, 9, 10, 11, 12],
[22, 23, 24, 25, 26, 27]])
循环神经网络基础
任务目标
以周杰伦歌词为语料库,训练歌曲生成模型。实现随机输入汉字,生成歌词。在此使用循环神经网络实现。
循环神经网络
下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量,用表示在时间步的值。的计算基于和,可以认为记录了到当前字符为止的序列信息,利用对序列的下一个字符进行预测。
循环神经网络的构造
假设是时间步的小批量输入,是该时间步的隐藏变量,则:
其中:函数是非线性**函数。式子形如递推公式,则后一步记录了前一步的序列的历史信息,就像是神经网络当前时间步的状态或记忆一样。由于这种循环计算,运用此计算的网络即循环神经网络。
在输出层计算为:
其中
one-hot向量
我们使用汉字的索引值进行训练,而为了消除其大小等干扰信息,我们将对其进行重新编码 – one-hot编码。如数字,其编码为其编码长度由索引值总量决定。如本例*有不同字符1027个,则编码长度为1027,第个索引值对应的第位为(从梯度索引0开始)
剪裁梯度
循环神经网络中较容易出现梯度衰减或梯度爆炸,这会导致网络几乎无法训练。裁剪梯度(clip gradient)是一种应对梯度爆炸的方法。假设我们把所有模型参数的梯度拼接成一个向量,并设裁剪的阈值是。裁剪后的梯度
的范数不超过。
困惑度
我们通常使用困惑度(perplexity)来评价语言模型的好坏。困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,
最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。