语言模型
马尔可夫模型和n元语法
自然语言统计
读取长序列数据
由于序列数据本质上是连续的,因此我们在处理数据时需要解决这个问题。 在 8.1节中我们以一种相当特别的方式做到了这一点: 当序列变得太长而不能被模型一次性全部处理时, 我们可能希望拆分这样的序列方便模型读取。
在介绍该模型之前,我们看一下总体策略。 假设我们将使用神经网络来训练语言模型, 模型中的网络一次处理具有预定义长度 (例如n个时间步)的一个小批量序列。 现在的问题是如何随机生成一个小批量数据的特征和标签以供读取。
首先,由于文本序列可以是任意长的, 例如整本《时光机器》(The Time Machine), 于是任意长的序列可以被我们划分为具有相同时间步数的子序列。 当训练我们的神经网络时,这样的小批量子序列将被输入到模型中。 假设网络一次只处理具有n个时间步的子序列。图8.3.1画出了从原始文本序列获得子序列的所有不同的方式, 其中n=5,并且每个时间步的词元对应于一个字符。 请注意,因为我们可以选择任意偏移量来指示初始位置,所以我们有相当大的自由度。
因此,我们应该从 图8.3.1中选择哪一个呢? 事实上,他们都一样的好。 然而,如果我们只选择一个偏移量, 那么用于训练网络的、所有可能的子序列的覆盖范围将是有限的。 因此,我们可以从随机偏移量开始划分序列, 以同时获得覆盖性(coverage)和随机性(randomness)。
随机采样
在随机采样中,每个样本都是在原始的长序列上任意捕获的子序列。 在迭代过程中,来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻。 对于语言建模,目标是基于到目前为止我们看到的词元来预测下一个词元, 因此标签是移位了一个词元的原始序列。
下面的代码每次可以从数据中随机生成一个小批量。 在这里,参数batch_size
指定了每个小批量中子序列样本的数目, 参数num_steps
是每个子序列中预定义的时间步数。
def seq_data_iter_random(corpus, batch_size, num_steps): #@save """使用随机抽样生成一个小批量子序列""" # 从随机偏移量开始对序列进行分区,随机范围包括num_steps-1 corpus = corpus[random.randint(0, num_steps - 1):] # 减去1,是因为我们需要考虑标签 num_subseqs = (len(corpus) - 1) // num_steps # 长度为num_steps的子序列的起始索引 initial_indices = list(range(0, num_subseqs * num_steps, num_steps)) # 在随机抽样的迭代过程中, # 来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻 random.shuffle(initial_indices) def data(pos): # 返回从pos位置开始的长度为num_steps的序列 return corpus[pos: pos + num_steps] num_batches = num_subseqs // batch_size for i in range(0, batch_size * num_batches, batch_size): # 在这里,initial_indices包含子序列的随机起始索引 initial_indices_per_batch = initial_indices[i: i + batch_size] X = [data(j) for j in initial_indices_per_batch] Y = [data(j + 1) for j in initial_indices_per_batch] yield torch.tensor(X), torch.tensor(Y)
顺序分区
总结
-
语言模型是自然语言处理的关键。
-
n元语法通过截断相关性,为处理长序列提供了一种实用的模型。
-
长序列存在一个问题:它们很少出现或者从不出现。
-
齐普夫定律支配着单词的分布,这个分布不仅适用于一元语法,还适用于其他n元语法。
- 读取长序列的主要方式是随机采样和顺序分区。在迭代过程中,后者可以保证来自两个相邻的小批量中的子序列在原始序列上也是相邻的。
标签:机器,语言,模型,batch,小批量,num,steps,随机,序列 From: https://www.cnblogs.com/yccy/p/17825209.html