(参考:李沐:动手学深度学习第8章第3节)
在自回归模型的近似法中, 我们使用最后tau个值来预测下一个,而不是全部。 只要这种是近似精确的,我们就说序列满足马尔可夫条件。 特别是,如果tau=1,得到一个一阶马尔可夫模型。
现在我们把它应用于语言建模。 如果
则序列上的分布满足一阶马尔可夫性质,在语言建模中这就是二元语法。翻译成人话就是:我认为预测值只和前一个已知的值有关。阶数越高,对应的依赖关系就越长。 这种性质推导出了许多可以应用于序列建模的近似公式:
一元语法(相互独立):
二元语法(只和前一个有关):
三元语法(只和前两个有关):
代码实现解析:
(1)首先导入数据集并构建词表
import random
import torch
from d2l import torch as d2l
tokens = d2l.tokenize(d2l.read_time_machine())
# 因为每个文本行不一定是一个句子或一个段落,因此我们把所有文本行拼接到一起
corpus = [token for line in tokens for token in line] # 二重循环把文本生成list
vocab = d2l.Vocab(corpus) #生成词表
print(vocab.token_freqs[:10]) #调用.token_freqs类方法
(2)二元语法实现
bigram_tokens = [pair for pair in zip(corpus[:-1], corpus[1:])]
bigram_vocab = d2l.Vocab(bigram_tokens)
print(bigram_vocab.token_freqs[:10])
这里zip的过程解析如下:
corpus=['a','b','c','d','e','f']
print(corpus[:-1]) # 打印从索引0到最后一个(不含),也就是去掉最后一个
print(corpus[1:]) # 打印从索引1到最后,也就是去掉第一个
print(list(zip(corpus[:-1], corpus[1:]))) # 打包
['a', 'b', 'c', 'd', 'e']
['b', 'c', 'd', 'e', 'f']
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f')]
到此我们生成了二元词表。那么最后的运行结果打印频率最高的前10位:
[(('of', 'the'), 309),
(('in', 'the'), 169),
(('i', 'had'), 130),
(('i', 'was'), 112),
(('and', 'the'), 109),
(('the', 'time'), 102),
(('it', 'was'), 99),
(('to', 'the'), 85),
(('as', 'i'), 78),
(('of', 'a'), 73)]