🐬语言模型和数据集
2021-12-1
| 2023-8-7
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
假设长度为的文本序列中的词元依次为。于是, 可以被认为是文本序列在时间步处的观测或标签。 在给定这样的文本序列时,语言模型(language model)的目标是估计序列的联合概率:
例如,只需要一次抽取一个词元, 一个理想的语言模型就能够基于模型本身生成自然文本。 与猴子使用打字机完全不同的是,从这样的模型中提取的文本都将作为自然语言(例如,英语文本)来传递。 只需要基于前面的对话片断中的文本, 就足以生成一个有意义的对话。 显然,我们离设计出这样的系统还很遥远, 因为它需要“理解”文本,而不仅仅是生成语法合理的内容。
尽管如此,语言模型依然是非常有用的。 例如,短语“to recognize speech”和“to wreck a nice beach”读音上听起来非常相似。 这种相似性会导致语音识别中的歧义,但是这很容易通过语言模型来解决, 因为第二句的语义很奇怪。 同样,在文档摘要生成算法中, “狗咬人”比“人咬狗”出现的频率要高得多。

学习语言模型

假设在单词级别对文本数据进行词元化, 我们可以对序列模型的分析。 从基本概率规则开始:
例如,包含了四个单词的一个文本序列的概率是:
为了训练语言模型,需要计算单词的概率, 以及给定前面几个单词后出现某个单词的条件概率。 这些概率本质上就是语言模型的参数。
这里假设训练数据集是一个大型的文本语料库。 比如,维基百科的所有条目、 古登堡计划, 或者所有发布在网络上的文本。 训练数据集中词的概率可以根据给定词的相对词频来计算。 例如,可以将估计值计算为任何以单词“deep”开头的句子的概率。 一种(稍稍不太精确的)方法是统计单词“deep”在数据集中的出现次数, 然后将其除以整个语料库中的单词总数。 这种方法效果不错,特别是对于频繁出现的单词。 接下来可以尝试估计:
其中分别是单个单词和连续单词对的出现次数。 不幸的是,由于连续单词对“deep learning”的出现频率要低得多, 所以估计这类单词正确的概率要困难得多。 特别是对于一些不常见的单词组合,要想找到足够的出现次数来获得准确的估计可能都不容易。 而对于三个或者更多的单词组合,情况会变得更糟。 许多合理的三个单词组合可能是存在的,但是在数据集中却找不到。 除非我们提供某种解决方案,来将这些单词组合指定为非零计数, 否则将无法在语言模型中使用它们。 如果数据集很小,或者单词非常罕见,那么这类单词出现一次的机会可能都找不到。
一种常见的策略是执行某种形式的拉普拉斯平滑(Laplace smoothing), 具体方法是在所有计数中添加一个小常量。 用 表示训练集中的单词总数,用 表示唯一单词的数量。 此解决方案有助于处理单元素问题,例如通过:
是超参数。
为例: 时,不应用平滑;接近正无穷大时, 接近均匀概率分布
然而,这样的模型很容易变得无效,原因如下: 首先,需要存储所有的计数; 其次,这完全忽略了单词的意思。 例如,“猫”(cat)和“猫科动物”(feline)可能出现在相关的上下文中, 但是想根据上下文调整这类模型其实是相当困难的。 最后,长单词序列大部分是没出现过的, 因此一个模型如果只是简单地统计先前“看到”的单词序列频率, 那么模型面对这种问题肯定是表现不佳的。
 

马尔可夫模型与n元语法

如果,则序列上的分布满足一阶马尔可夫性质。 阶数越高,对应的依赖关系就越长。 这种性质推导出了许多可以应用于序列建模的近似公式:
通常,涉及一个、两个和三个变量的概率公式分别被称为 “一元语法”(unigram)、“二元语法”(bigram)和“三元语法”(trigram)模型

自然语言统计

最流行的词看起来很无聊, 这些词通常被称为停用词(stop words),因此可以被过滤掉。 尽管如此,它们本身仍然是有意义的,我们仍然会在模型中使用它们。 此外,还有个明显的问题是词频衰减的速度相当地快。 例如,最常用单词的词频对比,第10个还不到第1个的1/5。画出的词频图:
notion image
可以发现:词频以一种明确的方式迅速衰减。 将前几个单词作为例外消除后,剩余的所有单词大致遵循双对数坐标图上的一条直线。 这意味着单词的频率满足齐普夫定律(Zipf’s law), 即第个最常用单词的频率为:
等价于
其中α是刻画分布的指数,c是常数。 这告诉我们想要通过计数统计和平滑来建模单词是不可行的, 因为这样建模的结果会大大高估尾部单词的频率,也就是所谓的不常用单词。 那么其他的词元组合,比如二元语法、三元语法等等,又会如何呢? 我们来看看二元语法的频率是否与一元语法的频率表现出相同的行为方式
这里值得注意:在十个最频繁的词对中,有九个是由两个停用词组成的, 只有一个与“the time”有关。 我们再进一步看看三元语法的频率是否表现出相同的行为方式
直观地对比三种模型中的词元频率:一元语法、二元语法和三元语法
notion image
这张图非常令人振奋!原因有很多: 首先,除了一元语法词,单词序列似乎也遵循齐普夫定律, 尽管指数α更小 (指数的大小受序列长度的影响)。 其次,词表中n元组的数量并没有那么大,这说明语言中存在相当多的结构, 这些结构给了我们应用模型的希望。 第三,很多n元组很少出现,这使得拉普拉斯平滑非常不适合语言建模。 作为代替,我们将使用基于深度学习的模型。
 

读取长序列数据

由于序列数据本质上是连续的,因此在处理数据时需要解决这个问题。当序列变得太长而不能被模型一次性全部处理时, 我们可能希望拆分这样的序列方便模型读取。
总体策略: 假设使用神经网络来训练语言模型, 模型中的网络一次处理具有预定义长度 (例如n个时间步)的一个小批量序列。 现在的问题是如何随机生成一个小批量数据的特征和标签以供读取。
首先,由于文本序列可以是任意长的, 例如整本《时光机器》(The Time Machine), 于是任意长的序列可以被划分为具有相同时间步数的子序列。 当训练神经网络时,这样的小批量子序列将被输入到模型中。 假设网络一次只处理具有n个时间步的子序列。 下图出了 从原始文本序列获得子序列的所有不同的方式, 其中n=5,并且每个时间步的词元对应于一个字符。 因为可以选择任意偏移量来指示初始位置,所以有相当大的自由度。
notion image
因此,应该选择哪一个呢? 事实上,他们都一样的好。 然而,如果只选择一个偏移量, 那么用于训练网络的、所有可能的子序列的覆盖范围将是有限的。 因此可以从随机偏移量开始划分序列, 以同时获得覆盖性和随机性
 

随机采样

在随机采样中,每个样本都是在原始的长序列上任意捕获的子序列。 在迭代过程中,来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻。 对于语言建模,目标是基于到目前为止我们看到的词元来预测下一个词元, 因此标签是移位了一个词元的原始序列。
下面的代码每次可以从数据中随机生成一个小批量。 在这里,参数batch_size指定了每个小批量中子序列样本的数目, 参数num_steps是每个子序列中预定义的时间步数。
下面面生成一个从0到34的序列。 假设批量大小为2,时间步数为5,这意味着可以生成 个“特征-标签”子序列对。 如果设置小批量大小为2,我们只能得到33个小批量。

顺序分区

在迭代过程中,除了对原始序列可以随机抽样外, 还可以保证两个相邻的小批量中的子序列在原始序列上也是相邻的。 这种策略在基于小批量的迭代过程中保留了拆分的子序列的顺序,因此称为顺序分区。
基于相同的设置,通过顺序分区读取每个小批量的子序列的特征X和标签Y。 通过将它们打印出来可以发现: 迭代期间来自两个相邻的小批量中的子序列在原始序列中确实是相邻的。
 
将上面的两个采样函数包装到一个类中, 以便稍后可以将其用作数据迭代器
最后,定义了一个函数load_data_time_machine, 它同时返回数据迭代器和词表, 因此可以与其他带有load_data前缀的函数 (如 d2l.load_data_fashion_mnist)类似地使用。
 
 

小结

  • 语言模型是自然语言处理的关键
  • n元语法通过截断相关性,为处理长序列提供了一种实用的模型
  • 长序列存在一个问题:它们很少出现或者从不出现
  • 齐普夫定律支配着单词的分布,这个分布不仅适用于一元语法,还适用于其他n元语法
  • 通过拉普拉斯平滑法可以有效地处理结构丰富而频率不足的低频词词组
  • 读取长序列的主要方式是随机采样和顺序分区。在迭代过程中,后者可以保证来自两个相邻的小批量中的子序列在原始序列上也是相邻的
  • PyTorch
  • 文本预处理RNN模型
    目录