Word2Vec简明教程:入门、原理及代码实现(下)

简介: Word2Vec简明教程:入门、原理及代码实现

4.1 SkipGram


(1)基本概念


Skip-gram模型从target word对context的预测中学习到word vector,该名称源于该模型在训练时会对上下文环境里的word进行采样。


20200813214642902.png


20200813214652466.png


按照上述思路产生的样本如下:

20200813214703667.jpg


 

针对上述模型,将预测相邻单词这一任务,转换为判断两个单词是否为相邻的单词的问题(0表示“不是邻居”,1表示“邻居”):


20200813214719555.png

20200813214725467.png

此时模型如下:


20200813214734762.jpg

将模型从神经网络改为逻辑回归模型——更简单,计算速度更快。但是此时所有单词都是相邻单词邻居(target=1),得到的训练模型可能永远返回1。

为了解决该问题,需要在数据集中引入负样本,即非相邻单词样本(target=0):


20200813214744117.jpg

这个想法的灵感来自噪声对比估计,将实际信号(相邻单词的正例)与噪声(随机选择的不是邻居的单词)进行对比,导致了计算和统计效率的巨大折衷。

word2vec训练过程中的两个关键超参数是窗口大小和负样本的数量,不同的任务适合不同的窗口大小。


(2)数据模型


SkipGram关注是给定中心词w生成背景词c cc的条件概率p ( c ∣ w ) 假设给定中心词的情况下背景词的生成相互独立,则


image.png

在跳字模型中,每个词被表示成两个d维向量,用来计算条件概率,词典索引集


V={0,1,…,∣V∣−1}。

假设这个词在词典中索引为i ,当它为中心词时向量表示为v i ∈ R d ,而为背景词时向量表示为u i ∈ R d 。 设中心词w 在词典中索引为w ,背景词c 在词典中索引为c ,给定中心词生成背景词的条件概率可以通过对向量内积做softmax运算而得到:

image.png

因此,Skip-gram模型的本质是计算输入word的input vector v w 与目标word的output vector u c 之间的余弦相似度,并进行softmax归一化,要学习的模型参数θ 正是这两类词向量。


此时

image.png

为了计算最大值,对其求导


image.png

它的计算需要词典中所有词以w 为中心词的条件概率,其他词向量的梯度同理可得。训练结束后,对于词典中的任一索引为i 的词,均得到该词作为中心词和背景词的两组词向量v i  和u i,一般使用跳字模型的中心词向量作为词的表征向量。


上述计算过程极其耗时,为此Mikolov引入了两种优化算法:层次Softmax(Hierarchical Softmax)和负采样(Negative Sampling),核心思想都是降低计算量。


4.2 CBoW


CBoW模型从context对target word的预测中学习到词向量的表达,等价于一个词袋模型的向量乘以一个Embedding矩阵,从而得到一个连续的embedding向量。这也是CBoW模型名称的由来。


20200813214833860.png

如:


20200813214843835.png


使用目标词的前两个词(“by”,“a”)与后两个词(“bus”,“in”),来预测目标词(“red”):


image.png


4.3 Negative Sampling


令P ( D = 1 ∣ w , c )表示中心词w 与背景词c同时出现(正例)的概率,P ( D = 0 ∣ w , w k )表示中心词w ww与背景词w k 不同时出现(负例)的概率,


image.png

此时,


image.png



需要最大化p ( c ∣ w ) ,由于上式的计算复杂度由K 个负采样决定,计算量大大降低。


4.4 Hierarchical Softmax


为了避免要计算所有词的softmax概率,word2vec使用Huffman树来代替从隐藏层到输出softmax层的映射,softmax概率计算只需要沿着树形结构进行。

如图,沿着霍夫曼树从根节点一直走到叶子节点的词w2


20200813214922313.png

Huffman树的所有内部节点类似神经网络隐藏层的神经元,根节点的词向量对应投影后的词向量,而所有叶子节点就类似于之前神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小。Huffman树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着霍夫曼树一步步完成,因此这种softmax名为"Hierarchical Softmax"。


word2vec中采用了二元逻辑回归的方法,即规定沿着左子树走,那么就是负类(Huffman树编码1),沿着右子树走,那么就是正类(Huffman树编码0),使用sigmoid函数判别正类和负类。


使用Hierarchical Softmax后,由于Huffman树是二叉树,计算量为由V 变成了log2V;此外,由于Huffman树是高频的词靠近树根,这样高频词被找到花费时间更短。


5. 使用gensim


gensim是一个很好用的Python NLP的包,封装了google的C语言版的word2vec,不只可以用于word2vec,还有很多其他的API可以用。可以使用

pip install gensim安装。


在gensim中,word2vec 相关的API都在包gensim.models.word2vec中,和算法有关的参数都在类gensim.models.word2vec.Word2Vec中,主要参数如下:

  • sentences: 要分析的语料,可以是一个列表,或者从文件中遍历读出。
  • size: 词向量的维度,默认值是100。这个维度的取值一般与语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。
  • window:即词向量上下文最大距离,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。如果是小语料则这个值可以设的更小。对于一般的语料这个值推荐在[5,10]之间。
  • sg: word2vec两个模型的选择:如果是0(默认), 则是CBOW模型;是1则是Skip-Gram模型。
  • hs: word2vec两个解法的选择:如果是0(默认), 则是Negative Sampling;是1的话并且负采样个数negative大于0, 则是Hierarchical Softmax。
  • negative:即使用Negative Sampling时负采样的个数,默认是5。推荐在[3,10]之间。这个参数在我们的算法原理篇中标记为neg。
  • cbow_mean: 仅用于CBOW在做投影的时候,为0,则算法中的xw为上下文的词向量之和,为1则为上下文的词向量的平均值。
  • min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。
  • iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
  • alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为η,默认是0.025。
  • min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。


以《人民的名义》为语料,分析主要人物的特征:

  • 通过词云可以发现,主要有侯亮平、李达康、高育良、祁同伟四位主角
  • 使用model.wv.similarity方法计算相互之间相似度,发现侯亮平、李达康、祁同伟之间相似度较高
  • 使用wv.doesnt_match比较沙瑞金与四位主角相似度,发现沙瑞金更加不同于四位主角
%matplotlib inline
import jieba
import jieba.analyse
filePath = r'data/in_the_name_of_people.txt'
stopPath = r'data/stopword_cn.txt'
with open(filePath,encoding = 'utf-8') as file:
    mytext = file.read() #读取到string
with open(stopPath,encoding = 'utf-8') as file:
    word_list = file.read().split() #返回一个字符串,都是小写
person = ['沙瑞金','田国富','高育良','侯亮平','祁同伟',
          '陈海','钟小艾', '陈岩石','欧阳菁','易学习','程度',
          '王大路','蔡成功','孙连城','季昌明', '丁义珍', 
          '郑西坡','赵东来', '高小琴','赵瑞龙','田国富',
          '陆亦可', '刘新建', '刘庆祝','李达康']
for p in person:
    jieba.suggest_freq(p, True)    
result = " ".join(jieba.cut(mytext)) #string类型
from wordcloud import WordCloud
import matplotlib.pyplot as plt
wordcloud = WordCloud(font_path = "simsun.ttf",stopwords=word_list,max_words=30).generate(result)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")

输出如下:

20200813215314695.png

from gensim.models import word2vec
segPath = r'data/in_the_name_of_people_segment.txt'
with open(segPath, 'w',encoding = 'utf-8') as f:
    f.write(result)
sentences = word2vec.LineSentence(segPath) 
model = word2vec.Word2Vec(sentences, hs=1,min_count=1,window=3,size=100)
print(model.wv.similarity('侯亮平', '高育良')) #相似度0.93316543
print(model.wv.similarity('侯亮平', '祁同伟')) #相似度0.9705674
print(model.wv.similarity('侯亮平', '李达康')) #相似度0.96616036
print(model.wv.similarity('李达康', '高育良')) #相似度0.91774
print(model.wv.similarity('李达康', '祁同伟')) #相似度0.9734558
print(model.wv.similarity('高育良', '祁同伟')) #相似度0.9349903
print(model.wv.doesnt_match(u"沙瑞金 侯亮平 高育良 李达康 祁同伟".split()))


输出如下:


0.93316543

0.9705674

0.96616036

0.91774

0.9734558

0.9349903

沙瑞金

相关文章
|
3月前
|
存储 自然语言处理 Java
HanLP — 双数组字典树 (Double-array Trie) 实现原理 -- 代码 + 图文,看不懂你来打我
HanLP — 双数组字典树 (Double-array Trie) 实现原理 -- 代码 + 图文,看不懂你来打我
38 0
|
6月前
|
存储 C语言 C++
【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现
【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现
|
6月前
|
Web App开发 机器学习/深度学习 自然语言处理
Word2Vec简明教程:入门、原理及代码实现
Word2Vec简明教程:入门、原理及代码实现
|
存储 算法 C++
C++初阶之一篇文章让你掌握vector(模拟实现)(上)
模拟实现vector是为了深入理解和学习C++标准库中vector容器的工作原理和实现细节。 vector是C++标准库中最常用的容器之一,它提供了动态数组的功能,并且具有自动扩容和内存管理的特性,使得在使用时非常方便。 模拟实现vector有以下几个优点:
|
Python
Python实现word的基本操作
Python实现word的基本操作
115 0
|
自然语言处理 数据可视化 数据处理
基于gensim实现word2vec模型(附案例实战)
基于gensim实现word2vec模型(附案例实战)
902 1
基于gensim实现word2vec模型(附案例实战)
|
机器学习/深度学习 自然语言处理 算法
Word2Vec原理以及实战详解
Word2Vec原理以及实战详解
|
机器学习/深度学习 存储 自然语言处理
Word2Vec简明教程:入门、原理及代码实现(上)
Word2Vec简明教程:入门、原理及代码实现
Word2Vec简明教程:入门、原理及代码实现(上)
|
机器学习/深度学习 算法 搜索推荐
深入浅出理解word2vec模型 (理论与源码分析)
深入浅出理解word2vec模型 (理论与源码分析)
深入浅出理解word2vec模型 (理论与源码分析)