介绍词向量word2evc概念,及CBOW和Skip-gram的算法实现( 四 )


比如 , 先指定一个中心词(如“人工”)和一个目标词正样本(如“智能”) , 再随机在词表中采样几个目标词负样本(如“日本” , “喝茶”等) 。 有了这些内容 , 我们的skip-gram模型就变成了一个二分类任务 。 对于目标词正样本 , 我们需要最大化它的预测概率;对于目标词负样本 , 我们需要最小化它的预测概率 。 通过这种方式 , 我们就可以完成计算加速 。 上述做法 , 我们称之为负采样 。
在实现的过程中 , 通常会让模型接收3个tensor输入:代表中心词的tensor:假设我们称之为centerwords$V$ , 一般来说 , 这个tensor是一个形状为[batchsize,vocab_size]的one-hottensor , 表示在一个mini-batch中每个中心词具体的ID 。 代表目标词的tensor:假设我们称之为targetwords$T$ , 一般来说 , 这个tensor同样是一个形状为[batchsize,vocab_size]的one-hottensor , 表示在一个mini-batch中每个目标词具体的ID 。 代表目标词标签的tensor:假设我们称之为labels$L$ , 一般来说 , 这个tensor是一个形状为[batch_size,1]的tensor , 每个元素不是0就是1(0:负样本 , 1:正样本) 。
模型训练过程如下:用$V$去查询$W0$ , 用$T$去查询$W1$ , 分别得到两个形状为[batchsize,embeddingsize]的tensor , 记为$H1$和$H2$ 。 点乘这两个tensor , 最终得到一个形状为[batchsize]的tensor$O=[Oi=sumjH0[i,j]×H1[i,j]]{i=1}^{batch_size}$ 。 使用sigmoid函数作用在$O$上 , 将上述点乘的结果归一化为一个0-1的概率值 , 作为预测概率 , 根据标签信息$L$训练这个模型即可 。
在结束模型训练之后 , 一般使用$W0$作为最终要使用的词向量 , 可以用$W0$提供的向量表示 。 通过向量点乘的方式 , 计算两个不同词之间的相似度 。
3.实现Skip-gram
接下来我们将学习使用飞桨实现Skip-gram模型的方法 。 在飞桨中 , 不同深度学习模型的训练过程基本一致 , 流程如下:数据处理:选择需要使用的数据 , 并做好必要的预处理工作 。 网络定义:使用飞桨定义好网络结构 , 包括输入层 , 中间层 , 输出层 , 损失函数和优化算法 。 网络训练:将准备好的数据送入神经网络进行学习 , 并观察学习的过程是否正常 , 如损失函数值是否在降低 , 也可以打印一些中间步骤的结果出来等 。 网络评估:使用测试集合测试训练好的神经网络 , 看看训练效果如何 。
在数据处理前 , 需要先加载飞桨平台(如果用户在本地使用 , 请确保已经安装飞桨) 。
importio
importos
importsys
importrequests
fromcollectionsimportOrderedDict
importmath
importrandom
importnumpyasnp
importpaddle
importpaddle.fluidasfluid
frompaddle.fluid.dygraph.nnimportEmbedding
3.1数据处理
首先 , 找到一个合适的语料用于训练word2vec模型 。 使用text8数据集 , 这个数据集里包含了大量从维基百科收集到的英文语料 , 我们可以通过如下代码下载数据集 , 下载后的文件被保存在当前目录的“text8.txt”文件内 。
defdownload():
#可以从百度云服务器下载一些开源数据集(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文件内
withopen("./text8.txt","wb")asf:
f.write(corpus)
f.close()
download()
接下来 , 把下载的语料读取到程序里 , 并打印前500个字符查看语料的格式 , 代码如下:
#读取text8数据
defload_text8():
withopen("./text8.txt","r")asf: