小白在使用Word2vec、glove、fasttext的理解及代码实现

小白在使用Word2vec、glove、fasttext中的理解
  这些天一直在研究不同模型训练词向量的问题,使用了三种模型,以下是我对这几种模型的粗浅的理解,参考了很多网上已有的资料,有错的地方欢迎留言指导交流。

1.Word2vec
  Word2Vec 的基本思想是把自然语言中的每一个词,表示成一个统一意义统一维度的短向量。Word2vec主要分为CBOW(Continuous Bag of Words)和Skip-Gram两种模式。CBOW是从原始语句推测目标字词;而Skip-Gram正好相反,是从目标字词推测出原始语句。CBOW对小型数据库比较合适,而Skip-Gram在大型语料中表现更好。
  Word2Vec 的训练模型,看穿了,是具有一个隐含层的神经元网络(如下图)。它的输入是词汇表向量,当看到一个训练样本时,对于样本中的每一个词,就把相应的在词汇表中出现的位置的值置为1,否则置为0。它的输出也是词汇表向量,对于训练样本的标签中的每一个词,就把相应的在词汇表中出现的位置的值置为1,否则置为0。那么,对所有的样本,训练这个神经元网络。收敛之后,将从输入层到隐含层的那些权重,作为每一个词汇表中的词的向量。比如,第一个词的向量是(w1,1 w1,2 w1,3 … w1,m),m是表示向量的维度。所有虚框中的权重就是所有词的向量的值。有了每个词的有限维度的向量,就可以用到其它的应用中,因为它们就像图像,有了有限维度的统一意义的输入。
在这里插入图片描述
1.1 skip-gram模型

它的做法是,将一个词所在的上下文中的词作为输出,而那个词本身作为输入,也就是说,给出一个词,希望预测可能出现的上下文的词。通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。如下图所示,第l个词的上下文词是i,j,k,那么i,j,k作为输出,它们所在的词汇表中的位置的值置为1。然后,输入是l,把它所在的词汇表中的位置的值置为1。训练完成后,就得到了每个词到隐含层的每个维度的权重,就是每个词的向量。
在这里插入图片描述
skip-gram模型
接下来我们来看下skip-gram神经网络模型,skip-gram的神经网络模型是从前馈神经网络模型改进而来,说白了就是在前馈神经网络模型的基础上,通过一些技巧使得模型更有效。我们先上图,看一波skip-gram的神经网络模型:
在这里插入图片描述
  在上图中,输入向量x代表某个单词的one-hot编码,对应的输出向量{y1,…,yC}。输入层与隐藏层之间的权重矩阵W的第i行代表词汇表中第i个单词的权重。接下来重点来了:这个权重矩阵W就是我们需要学习的目标(同W′),因为这个权重矩阵包含了词汇表中所有单词的权重信息。上述模型中,每个输出单词向量也有个N×V维的输出向量W′。最后模型还有N个结点的隐藏层,我们可以发现隐藏层节点hi的输入就是输入层输入的加权求和。因此由于输入向量x是one-hot编码,那么只有向量中的非零元素才能对隐藏层产生输入。因此对于输入向量x其中xk=1并且xk′=0,k≠k′。所以隐藏层的输出只与权重矩阵第k行相关,也就是如图所示
在这里插入图片描述从数学上证明如下:
在这里插入图片描述
因为输入时one-hot编码,所以这里是不需要使用激活函数的。同理,模型输出结点C×V的输入也是由对应输入结点的加权求和计算得到:

隐藏层产生的1×N的词向量将会传送到输出层,这个输出层是一个softmax regressio分类器,其要领就是每一个输出神经单元将会产生一个介于0到1的输出,并且所有输出值的和为1。
每个输出单元有一个权重矩阵N×V(这里的矩阵类似于输入层的权重矩阵没用于共享,只与对应的列相乘),然后与来自隐藏层的词向量相乘,然后对结果运用softmax函数产生第C个单词的分布。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
说白了,这个值就是第C个输出单词的第j个结点的概率大小。

通过BP(反向传播)算法及随机梯度下降来学习权重
前面我讲解了skip-gram模型的输入向量及输出的概率表达,以及我们学习的目标。接下来我们详细讲解下学习权重的过程。第一步就是定义损失函数,这个损失函数就是输出单词组的条件概率,一般都是取对数,如下所示:
E=−log(p(wO,1,wO,2,…,wO,C|wI))
在这里插入图片描述进而更新权重。

1.1 CBOW
它的做法是,将一个词所在的上下文中的词作为输入,而那个词本身作为输出,也就是说,看到一个上下文,希望大概能猜出这个词和它的意思。通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。如下图所示,第l个词的上下文词是i,j,k,那么i,j,k作为输入,它们所在的词汇表中的位置的值置为1。然后,输出是l,把它所在的词汇表中的位置的值置为1。训练完成后,就得到了每个词到隐含层的每个维度的权重,就是每个词的向量。
在这里插入图片描述代码实现

import logging
import os.path
import sys
import multiprocessing

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

if __name__ == '__main__':
    program = os.path.basename('model/')
    logger = logging.getLogger(program)

    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))
    #LineSentence('word/allword.txt')训练文本,已切好的词,size为维度大小,window表示窗口大小,iter表示迭代次数,sg=1表示skipgram,若为0表示CBOW,
    model = Word2Vec(LineSentence('word/allword.txt'), size=128, window=10,  iter=10, sg=1,
                     workers=multiprocessing.cpu_count())
    model.wv.save_word2vec_format('model/qiche_word2vec_128.model_' + str(128) + '.bin', binary=True)

2.glove

模型目标:进行词的向量化表示,使得向量之间尽可能多地蕴含语义和语法的信息。
输入:语料库
输出:词向量
方法概述:首先基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型学习词向量。
统计共现矩阵
设共现矩阵为X,其元素为X_{i,j},表示在整个语料库中,单词i和单词j共同出现在一个窗口中的次数。
使用GloVe模型训练词向量
模型公式
先看模型,损失函数长这个样子:
在这里插入图片描述
vi,vj是单词i和单词j的词向量,bi,bj是两个标量(作者定义的偏差项),f是权重函数(具体函数公式及功能下一节介绍),N是词汇表的大小(共现矩阵维度为N∗N)。
模型怎么来的
那么作者为什么这么构造模型呢?首先定义几个符号:
在这里插入图片描述其实就是矩阵单词i那一行的和;
在这里插入图片描述条件概率,表示单词k出现在单词i语境中的概率;
在这里插入图片描述两个条件概率的比率。
作者的灵感是这样的:
作者发现,ratioi,j,k这个指标是有规律的,如果单词i,k(不)相关且j,k(不)相关,则ratio趋近于1,如果只有一组相关,则ratio很小或很大。
思想:假设我们已经得到了词向量,如果我们用词向量vi、vj、vk通过某种函数计算ratioi,j,k,能够同样得到这样的规律的话,就意味着我们词向量与共现矩阵具有很好的一致性,也就说明我们的词向量中蕴含了共现矩阵中所蕴含的信息。
设用词向量vi、vj、vk计算ratioi,j,k的函数为g(vi,vj,vk)(我们先不去管具体的函数形式),那么应该有:
在这里插入图片描述
即二者应该尽可能地接近;
很容易想到用二者的差方来作为代价函数:
在这里插入图片描述
但是仔细一看,模型中包含3个单词,这就意味着要在N∗N∗N的复杂度上进行计算,太复杂了,最好能再简单点。

  1. 要考虑单词i和单词j之间的关系,那g(vi,vj,vk)中大概要有这么一项吧:vi−vj;嗯,合理,在线性空间中考察两个向量的相似性,不失线性地考察,那么vi−vj大概是个合理的选择;
  2. ratioi,j,k是个标量,那么g(vi,vj,vk)最后应该是个标量啊,虽然其输入都是向量,那內积应该是合理的选择,于是应该有这么一项吧:(vi−vj)Tvk
  3. 然后作者又往(vi−vj)Tvk的外面套了一层指数运算exp(),得到最终的g(vi,vj,vk)=exp(((vi−vj)Tvk);
    最关键的第3步,为什么套了一层exp()?
    套上之后,我们的目标是让以下公式尽可能地成立:
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    然后就发现找到简化方法了:只需要让上式分子对应相等,分母对应相等,即:
    在这里插入图片描述
    然而分子分母形式相同,就可以把两者统一考虑了,即:
    在这里插入图片描述
    两边取对数
    在这里插入图片描述
    那么损失函数就可以简化为:
    在这里插入图片描述
    现在只需要在N∗N的复杂度上进行计算,而不是N∗N∗N,现在关于为什么第3步中,外面套一层exp()就清楚了,正是因为套了一层exp(),才使得差形式变成商形式,进而等式两边分子分母对应相等,进而简化模型。
    然而,出了点问题。
    仔细看这两个式子:
    在这里插入图片描述
    等式左边不相等,但是等式右边相等,即等式左侧不具有对称性,但是右侧具有对称性。
    数学上出了问题。
    补救一下好了。
    现将代价函数中的条件概率展开:
    在这里插入图片描述
    即为:
    在这里插入图片描述
    将其变为:
    在这里插入图片描述
    即添了一个偏差项bj,并将log(Xi)吸收到偏差项bi中。
    于是损失函数就变成了:
    在这里插入图片描述
    然后基于出现频率越高的词对儿权重应该越大的原则,在损失函数中添加权重项,于是损失函数进一步完善:
    在这里插入图片描述
    具体权重函数应该是怎么样的呢?
    首先应该是非减的,其次当词频过高时,权重不应过分增大,作者通过实验确定权重函数为:
    在这里插入图片描述
$ git clone http://github.com/stanfordnlp/glove
$ cd glove && make
$ ./demo.sh

3.fasttext
fasttext提供了一种有效且快速的方式生成词向量以及进行文档分类。fasttext模型输入一个词的序列,输出这个词序列属于不同类别的概率。fasttext模型架构和Word2Vec中的CBOW模型很类似。不同之处在于,fasttext预测标签,而CBOW模型预测中间词。fasttext设计的初衷就是为了作为一个文档分类器,副产品是也生成了词向量。
首先,FastText主要是对文本进行分类的,其词嵌入是FastText分类的产物。于是fastText的核心思想就是:将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。使用词embedding而非词本身作为特征,这是fastText效果好的一个原因;另一个原因就是字符级n-gram特征的引入对分类效果会有一些提升 。
fasttext特性
n-gram
在词袋模型中,把单词当做独立的个体,没有考虑词前后的关系。比如"我打你"和“你打我“,使用词袋模型的话,这两句话是完全一样的。词袋的特征为:
在这里插入图片描述与Word2Vec使用词袋模型不同,fasttext使用了n-gram模型,因此fasttext可以更有效的表达词前后的之间的关系。fastText模型也只有三层:输入层、隐含层、输出层(Hierarchical Softmax),输入都是多个经向量表示的单词,输出都是一个特定的target,隐含层都是对多个词向量的叠加平均。
CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档;CBOW的输入单词被onehot编码过,fastText的输入特征是被embedding过;CBOW的输出是目标词汇,fastText的输出是文档对应的类标。词向量是无监督方法,无需标签的,并且fasttext里的词向量训练也即是word2vec中的cbow,skip-gram.
代码实现

from gensim.models import FastText
from gensim.models.word2vec import LineSentence
model = FastText(LineSentence('word/allword.txt'), size=100, window=3, min_count=1, iter=10,min_n = 3 , max_n = 6,word_ngrams = 0)
print(model['喜欢']) # 词向量获得的方式
model.save('model/fasttext_model.bin')

三种模型的调用方式相同

model=gensim.models.KeyedVectors.load_word2vec_format(modelfile, binary=True)#orbinary=False
similar=model.similarity(string,String)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值