【ML】word2vector原理-应用-代码

一.前言

先回答下,为什么会出现word2vector这个算法。首先来看one-hot的不足。黑色加粗部分,导致word2vector出现的原因。

最基本的也是最简单的把word转换成vector的办法就是通过计数word在文档中出现的次数,这样的表达方式称为one hot或者count vectorizing。假设词典共有V个词,那么每一个单词都有一个V维度的向量来表示,向量中只有一个位置为非0(可以是1,也可以是出现次数),表示该词的编号,其余为0。这样的表示很容易带来维度灾难,而且表示非常的稀疏,一个普通的词典中可能就包含上百万个词。借助sklearn可以轻松的实现该表达。运行下面的代码,得到一个非常稀疏的矩阵,每行表示一个Document,每一列表示一个Word。

#word 2 vector
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
corpus = [
    'Text of first document.',
    'Text of the second document make longer.',
    'Number three.',
    'This is number four.',
]

# store CountVectorizer sparse matrix in X
# The column of matrix is words, rows are documents
X = vectorizer.fit_transform(corpus) #(4, 13)
print(vectorizer.get_feature_name())
print(X.toarray()) 

# Convert a new document to count representation
vectorizer.transform(['This is a new document'])

#结果X.toarray()
[[1 1 0 0 0 0 0 1 0 1 0 0 0]
 [1 0 0 0 1 1 0 1 1 1 1 0 0]
 [0 0 0 0 0 0 1 0 0 0 0 0 1]
 [0 0 1 1 0 0 1 0 0 0 0 1 0]]
<1x13 sparse matrix of type '<type 'numpy.int64'>'
	with 3 stored elements in Compressed Sparse Row format>

二.Word2Vec主要思想

Word2vec是在Google Tomas Mikolov在2013年提出来的,作用同样是将word转换成vector表达,但是这样的vector是低维度的实数值。学习到的这个vector就是Embedding/词嵌入向量。

word2vec背后的关键原则:一个词的含义可以从它的上下文语境中推断出来 。 更抽象的,文本实际上只是一个单词序列,一个单词的含义可以从这个单词之前和之后的几个单词中提取出来。

研究人员发现,在线用户活动的时间序列和从上下文推断单词的含义一致:当用户浏览并与之交互时,可以从用户前后交互的内容推断出一条抽象内容。 因此,ML团队可以应用词向量模型来学习产品,内容和广告等内容的向量表示。word2vec(或者其他词向量模型)相比过去的方法能提供更好的单词的向量表示,使得NLP发生重大的变革

Word2Vec包括两种模型,CBOW(continuous bag of words )与Skip-gram(continuous skip-gram words)。前者利用上下文预测单词,后者利用单词预测上下文。本文主要关注CBOW模型。

训练word2vec的过程中有很多工程技巧,比如用negative sampling或Hierarchical Softmax减少词汇空间过大带来的计算量,对高频词汇进行降采样避免对于这些低信息词汇的无谓计算等。

简单说下这两个优化框架,公式就不写了,是在有点记不住,先大致理解下原理。

1.基于Hierarchical Softmax框架的cbow模型

目标函数:

对数使然函数,我们希望预测的结果P(w|context(w))最大,目标函数是连乘的形式,这里取对数,便于计算。

关键点:如何求P(w|context(w))?

模型网络结构:

输入层:context(w)附近的2c个单词的向量。

投影层:将2c向量累加。

输出层:对应一个二叉树,以语料中出现的词作为叶子节点,已各个词出现的次数作为权值构造出来的huffuman树。

神经概率语言模型网络与CBOW的区别:

1.从输入层到投影层:前者通过拼接,后者通过累加求和。

2.隐藏层:前者有隐藏层,后者无隐藏层

3.输出层:前者是线性结构,后者是树形结构

在神经概率语言模型中,模型的大部分计算集中在隐藏层和输出层之间的矩阵向量运算,以及输出层上的softmax函数。

2.基于Hierarchical Softmax框架的skip-gram模型

目标函数:


还是看原著比较好^.^


 

1.正负样本怎么生成?

为了产生模型的正样本,我们选一个长度为2c+1(目标词前后各选c个词)的滑动窗口,从句子左边滑倒右边,每滑一次,窗口中的词就形成了我们的一个正样本。

2.有了训练样本之后我们就可以着手定义优化目标了,既然每个词 Wt 都决定了相邻词 Wt+j ,基于极大似然,我们希望所有样本的条件概率 p(Wt+j|Wt)之积最大,这里我们使用log probability。我们的目标函数有了:

接下来的问题是怎么定义 p(Wt+j|Wt) ,作为一个多分类问题,最简单最直接的方法当然是直接用softmax函数,我们又希望用向量 Vw 表示每个词w,用词之间的距离 ViTVj表示语义的接近程度,那么我们的条件概率的定义就可以很直观的写出。

看到上面的条件概率公式,很多同学可能会习惯性的忽略一个事实,就是

我们用 Wt 去预测 Wt+j ,但其实这二者的向量表达并不在一个向量空间内。Wt 是已知,作为模型的输入,在输入控件中;Wt+j是我们要预测的词,在输出空间中。

就像上面的条件概率公式写的一样, Vw` 和  Vw 分别是词w的输出向量表达和输入向量表达。那什么是输入向量表达和输出向量表达呢?我们画一个word2vec的神经网络架构图就明白了。

word2vec的算法架构

根据p(Wt+j|Wt)的定义,我们可以把两个vector的乘积再套上一个softmax的形式转换成上面的神经网络架构.这里有一个问题:需要非常注意的一点事hidden layer的激活函数,大家要思考一下,到底是sigmoid函数还是普通的线性函数,为什么?个人觉得不能改为线性函数,因为我们要求的是概率,sigmod函数有很好的概率意义,能将输入映射到(0,1)区间内。在训练过程中我们就可以通过梯度下降的方式求解模型参数了。那么上文所说的输入向量表达就是input layer到hidden layer的权重矩阵 Wv*n ,而输出向量表达就是hidden layer到output layer的权重矩阵 Wn*v 。

那么到底什么是我们通常意义上所说的词向量 Vw呢?

其实就是我们上面所说的输入向量矩阵 Wv*n  中每一行对应的权重向量。

于是这个权重矩阵自然转换成了word2vec的lookup table。每一个神经元都转化为Vw的一个元素,embeding的长度=神经元的个数。

那么问题也来了,我们能把输出矩阵Wn*v   的列向量当作word的vector表达吗?

【一个不准确的答案——答:不能。hiden layer的输入是词向量了,乘以一个输出矩阵,套上sigmod得到预测的概率。】

2.加速方法:

Hierarchical Softmax--缩短训练开销

对原模型的改进主要有两点,第一点是从输入层到隐藏层的映射,没有采用原先的与矩阵W相乘然后相加求平均的方法,而是直接对所有输入的词向量求和。假设输入的词向量为(0,1,0,0)和(0,0,0,1),那么隐藏层的向量为(0,1,0,1)。

Hierarchical Softmax的第二点改进是采用哈夫曼树来替换了原先的从隐藏层到输出层的矩阵W’。哈夫曼树的叶节点个数为词汇表的单词个数V,一个叶节点代表一个单词,而从根节点到该叶节点的路径确定了这个单词最终输出的词向量。

具体来说,这棵哈夫曼树除了根结点以外的所有非叶节点中都含有一个由参数θ确定的sigmoid函数,不同节点中的θ不一样。训练时隐藏层的向量与这个sigmoid函数进行运算,根据结果进行分类,若分类为负类则沿左子树向下传递,编码为0;若分类为正类则沿右子树向下传递,编码为1。

Negative Sampling--提高训练效率--

尽管哈夫曼树的引入为模型的训练缩短了许多开销,但对于一些不常见、较生僻的词汇,哈夫曼树在计算它们的词向量时仍然需要做大量的运算。

负采样是另一种用来提高Word2Vec效率的方法,它是基于这样的观察:训练一个神经网络意味着使用一个训练样本就要稍微调整一下神经网络中所有的权重,这样才能够确保预测训练样本更加精确,如果能设计一种方法每次只更新一部分权重,那么计算复杂度将大大降低。

将以上观察引入Word2Vec就是:当通过(”fox”, “quick”)词对来训练神经网络时,我们回想起这个神经网络的“标签”或者是“正确的输出”是一个one-hot向量。也就是说,对于神经网络中对应于”quick”这个单词的神经元对应为1,而其他上千个的输出神经元则对应为0。使用负采样,我们通过随机选择一个较少数目(比如说5个)的“负”样本来更新对应的权重。(在这个条件下,“负”单词就是我们希望神经网络输出为0的神经元对应的单词)。并且我们仍然为我们的“正”单词更新对应的权重(也就是当前样本下”quick”对应的神经元仍然输出为1)。

 

参考:

1.一般介绍:https://mp.weixin.qq.com/s/6lxL80a3Yih9dTFDGJuHaw

2.实际应用:https://blog.csdn.net/Amelie_ting/article/details/81779877

3.原理介绍:https://www.cnblogs.com/iloveai/p/word2vec.html

4.peghoty大神对word2vector的数学原理和部分代码讲解:word2vec 中的数学原理详解

5.找到一个拆解版本的数学原理讲解:https://blog.csdn.net/itplus/article/details/37969519

6.word2vec到item2vec的演变:https://lumingdong.cn/application-practice-of-embedding-in-recommendation-system.html#%E4%BB%8E%E6%9D%83%E9%87%8D%E7%9F%A9%E9%98%B5%E5%88%B0%E8%AF%8D%E5%90%91%E9%87%8F

7.得到词向量的例子:https://www.zhihu.com/question/44832436

8.基于hierarchical softmax的模型:https://blog.csdn.net/itplus/article/details/37969979

9.基于negative sample的模型:https://blog.csdn.net/itplus/article/details/37998797

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值