图学习参考资料 词向量word2vec( 四 )


假设有一个中心词$c$和一个上下文词正样本$t_p$ 。在Skip-gram的理想实现里,需要最大化使用$c$推理$t_p$的概率 。在使用softmax学习时,需要最大化$t_p$的推理概率,同时最小化其他词表中词的推理概率 。之所以计算缓慢,是因为需要对词表中的所有词都计算一遍 。然而我们还可以使用另一种方法,就是随机从词表中选择几个代表词,通过最小化这几个代表词的概率,去近似最小化整体的预测概率 。比如,先指定一个中心词(如“人工”)和一个目标词正样本(如“智能”),再随机在词表中采样几个目标词负样本(如“日本”,“喝茶”等) 。有了这些内容,我们的skip-gram模型就变成了一个二分类任务 。对于目标词正样本,我们需要最大化它的预测概率;对于目标词负样本,我们需要最小化它的预测概率 。通过这种方式,我们就可以完成计算加速 。上述做法,我们称之为负采样 。
在实现的过程中,通常会让模型接收3个tensor输入:

  • 代表中心词的tensor:假设我们称之为center_words $V$,一般来说,这个tensor是一个形状为[batch_size, vocab_size]的one-hot tensor,表示在一个mini-batch中每个中心词具体的ID 。
  • 代表目标词的tensor:假设我们称之为target_words $T$,一般来说,这个tensor同样是一个形状为[batch_size, vocab_size]的one-hot tensor,表示在一个mini-batch中每个目标词具体的ID 。
  • 代表目标词标签的tensor:假设我们称之为labels $L$,一般来说,这个tensor是一个形状为[batch_size, 1]的tensor,每个元素不是0就是1(0:负样本,1:正样本) 。
模型训练过程如下:
  1. 用$V$去查询$W_0$,用$T$去查询$W_1$,分别得到两个形状为[batch_size, embedding_size]的tensor,记为$H_1$和$H_2$ 。
  2. 点乘这两个tensor,最终得到一个形状为[batch_size]的tensor$O = [O_i = \sum_j H_0[i,j] × H_1[i,j]]_{i=1}^{batch_size}$ 。
  3. 使用sigmoid函数作用在$O$上,将上述点乘的结果归一化为一个0-1的概率值,作为预测概率,根据标签信息$L$训练这个模型即可 。
在结束模型训练之后,一般使用$W_0$作为最终要使用的词向量,可以用$W_0$提供的向量表示 。通过向量点乘的方式,计算两个不同词之间的相似度 。
3. 实现Skip-gram接下来我们将学习使用飞桨实现Skip-gram模型的方法 。在飞桨中,不同深度学习模型的训练过程基本一致,流程如下:
  1. 数据处理:选择需要使用的数据,并做好必要的预处理工作 。
  2. 网络定义:使用飞桨定义好网络结构,包括输入层,中间层,输出层,损失函数和优化算法 。
  3. 网络训练:将准备好的数据送入神经网络进行学习,并观察学习的过程是否正常,如损失函数值是否在降低,也可以打印一些中间步骤的结果出来等 。
  4. 网络评估:使用测试集合测试训练好的神经网络,看看训练效果如何 。
在数据处理前,需要先加载飞桨平台(如果用户在本地使用,请确保已经安装飞桨) 。
import osimport sysimport requestsfrom collections import OrderedDictimport mathimport randomimport numpy as npimport paddleimport paddle.fluid as fluidfrom paddle.fluid.dygraph.nn import Embedding3.1数据处理首先,找到一个合适的语料用于训练word2vec模型 。使用text8数据集,这个数据集里包含了大量从维基百科收集到的英文语料,我们可以通过如下代码下载数据集,下载后的文件被保存在当前目录的“text8.txt”文件内 。
def download():#可以从百度云服务器下载一些开源数据集(dataset.bj.bcebos.com)corpus_url = "https://dataset.bj.bcebos.com/word2vec/text8.txt"#使用python的requests包下载数据集到本地web_request = requests.get(corpus_url)corpus = web_request.content#把下载后的文件存储在当前目录的text8.txt文件内with open("./text8.txt", "wb") as f:f.write(corpus)f.close()download()

经验总结扩展阅读