用稀疏向量表示文本,即所谓的词袋模型在 NLP 有着悠久的历史。正如上文中介绍的,早在 2001年就开始使用密集向量表示词或词嵌入。Mikolov等人在2013年提出的创新技术是通过去除隐藏层,逼近目标,进而使这些单词嵌入的训练更加高效。虽然这些技术变更本质上很简单,但它们与高效的word2vec配合使用,便能使大规模的词嵌入训练成为可能。
0 前言:词袋模型
首先解释一下什么是词袋模型:
词袋模型(Bag-of-Words, BOW) 是最早、最经典的文本表示方法之一(1940左右出现,甚至比n-gram还要早,我愿称之为原始祖师爷)。它将一段文本看作一个「袋子」:里面盛放了这个文本所含的所有单词,但忽略了单词的顺序、句法结构等信息,只关注单词是否出现以及出现次数(或频率)。这就好比把句子里的单词都抓出来扔进一个袋子,摇匀后再数一数这些单词都有什么、各出现几次。
1.1 典型示例
假设我们的词表是 "I","like","apples","banana",大小 V=4(指的就是一共有4个词)。
有两句话:
- “I like apples”
- “I like banana apples”
那么在词袋表示下:
-
对于 “I like apples”:
- "I" 出现 1 次
- "like" 出现 1 次
- "apples"出现 1 次
- "banana"出现 0 次
向量表示可写作[1, 1, 1, 0]
-
对于 “I like banana apples”:
- "I" 出现 1 次
- "like" 出现 1 次
- "apples"出现 1 次
- "banana"出现 1 次
向量表示可写作[1, 1, 1, 1]
可以看到,这种表示只管词的出现情况,不会去记录 “banana”是在“apples”前还是后出现,也不会记录它们之间的距离。这样就得到最纯粹的词袋表示。
一、词向量引入
先来考虑一个问题:如何能将文本向量化呢?听起来比较抽象,我们可以先从人的角度来思考。
如何用一个数值向量描述一个人呢?只用身高或者体重,还是综合其各项指标呢?当然是综合各项指标能更加准确的描述一个人啦,具体什么指标还得看你能收集到什么指标。比如除了常规的身高、体重外,我们还可以用人的性格,从内向到外向设置为从-1到+1,人的性格让“专家”去打分,从而获取人性格的数值化数据。
只要有了向量,就可以用不同方法(欧氏距离、曼哈顿距离、切比雪夫距离、余弦相似度等)来计算两个向量之间的相似度了!
通常来说,向量的维度越高,能提供的信息也就越多,从而计算结果的可靠性就更值得信赖
现在回到正题,如何描述词的特征?通常都是在词的层面上来构建特征。Word2Vec就是要把词转化为向量。
下图展示了一个50维的词向量:
假设现在已经拿到了一份训练好的词向量,其中每一个词都表示为50维的向量,如下图所示:
如果将它们在热度图中显示,结果如下:
在结果中可以发现,相似的词在特征表达中比较相似,也就是说明词的特征是有实际意义的!
二、词向量模型
在词向量模型中输入和输出是什么?中间这个黑盒又是什么?
如下图所示,在词向量模型中,输入可以是多个词。例如下面所示的,输入是 Thou 和 shalt,模型的任务是预测它们的下一个词是什么。
早期的神经网络的词嵌入方法(word2vec出现之前使用n-gram去训练原始词表里面的300维向量 差不多2001年)
最后一层连接了 SoftMax,所以网络的输出是所有词可能是下一个词的概率。
那么有人就会问了,输入是文字,文字怎么输入到神经网络中啊 ?这个问题很好,我们通常会用一个 Embedding 层来解决这个问题。如下图所示,在神经网络初始化的时候,我们会随机初始化一个 N×K 的矩阵,其中 N 是 词典的大小,K 是词向量的维数(一个自行设定的超参数)。然后,我们会用一个 N×N 的矩阵和 N×K 的矩阵相乘,得到一个新的 N×K的矩阵向下进行前向传播。其中,N×N 的矩阵会在输入的文字的对应对角线上设置为1,其余位置均为0。N×K 的矩阵是随机初始化的,通过反向传播进行更新调整。
下面展示了一个例子(假设输入的两个词在词典中的位置是2和3处):
三、训练数据构建(还是早期的n-gram模型)
问:我们的训练数据应该从哪找呢?
答:一切具有正常逻辑的语句都可以作为训练数据。如小说、论文等。
如果我们有一个句子,那么我们可以按照下面你的方式构建数据集,选出前三个词,用前两个作为词模型的输入,最后一个词作为词模型输出的目标,继而进行训练。如下图所示: