精华内容
参与话题
问答
  • 理解GloVe模型(+总结)

    万次阅读 多人点赞 2018-03-21 16:36:00
    系列目录(系列更新中) 第二讲 cs224n系列之word2vec & 词向量 word2vec进阶之skim-gram和CBOW模型(Hierarchical Softmax、Negative Sampling) 第三讲 cs224n系列之skip-...

    系列目录(系列更新中)

    概述

    • 模型目标:进行词的向量化表示,使得向量之间尽可能多地蕴含语义和语法的信息。
    • 输入:语料库
    • 输出:词向量
    • 方法概述:首先基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型学习词向量。
      ** 开始 -> 统计共现矩阵 -> 训练词向量 -> 结束**

    统计共现矩阵

    设共现矩阵为X,其元素为Xi,jX_{i,j}
    Xi,jX_{i,j}的意义为:在整个语料库中,单词i和单词j共同出现在一个窗口中的次数。
    举个栗子:
    设有语料库:

    i love you but you love him i am sad
    

    这个小小的语料库只有1个句子,涉及到7个单词:i、love、you、but、him、am、sad。
    如果我们采用一个窗口宽度为5(左右长度都为2)的统计窗口,那么就有以下窗口内容:

    窗口标号 中心词 窗口内容
    0 i i love you
    1 love i love you but
    2 you i love you but you
    3 but love you but you love
    4 you you but you love him
    5 love but you love him i
    6 him you love him i am
    7 i love him i am sad
    8 am him i am sad
    9 sad i am sad

    窗口0、1长度小于5是因为中心词左侧内容少于2个,同理窗口8、9长度也小于5。
    以窗口5为例说明如何构造共现矩阵:
    中心词为love,语境词为but、you、him、i;则执行:

    Xlove,but+=1X_{love,but}+=1
    Xlove,you+=1X_{love,you}+=1
    Xlove,him+=1X_{love,him}+=1
    Xlove,i+=1X_{love,i}+=1

    使用窗口将整个语料库遍历一遍,即可得到共现矩阵X。

    使用GloVe模型训练词向量

    模型公式

    先看模型,代价函数长这个样子:

    J=i,jNf(Xi,j)(viTvj+bi+bjlog(Xi,j))2J=\sum_{i,j}^Nf(X_{i,j})(v_{i}^Tv_{j}+b_{i}+b_{j}-log(X_{i,j}))^2

    viv_{i}vjv_{j}是单词i和单词j的词向量,bib_{i}bjb_{j}是两个标量(作者定义的偏差项),f是权重函数(具体函数公式及功能下一节介绍),N是词汇表的大小(共现矩阵维度为N*N)。
    可以看到,GloVe模型没有使用神经网络的方法。

    模型怎么来的

    那么作者为什么这么构造模型呢?首先定义几个符号:

    Xi=j=1NXi,jX_{i}=\sum_{j=1}^NX_{i,j}

    其实就是矩阵单词i那一行的和;
    Pi,k=Xi,kXiP_{i,k}=\dfrac{X_{i,k}}{X_{i}}

    条件概率,表示单词k出现在单词i语境中的概率;
    ratioi,j,k=Pi,kPj,kratio_{i,j,k}=\dfrac{P_{i,k}}{P_{j,k}}

    两个条件概率的比率。
    作者的灵感是这样的:
    作者发现,ratioi,j,kratio_{i,j,k}这个指标是有规律的,规律统计在下表:

    ratioi,j,kratio_{i,j,k}的值 单词j,k相关 单词j,k不相关
    单词i,k相关 趋近1 很大
    单词i,k不相关 很小 趋近1

    很简单的规律,但是有用。
    思想:假设我们已经得到了词向量,如果我们用词向量viv_{i}vjv_{j}vkv_{k}通过某种函数计算ratioi,j,kratio_{i,j,k},能够同样得到这样的规律的话,就意味着我们词向量与共现矩阵具有很好的一致性,也就说明我们的词向量中蕴含了共现矩阵中所蕴含的信息。
    设用词向量viv_{i}vjv_{j}vkv_{k}计算ratioi,j,kratio_{i,j,k}的函数为g(vi,vj,vk)g(v_{i},v_{j},v_{k})(我们先不去管具体的函数形式),那么应该有:

    Pi,kPj,k=ratioi,j,k=g(vi,vj,vk)\dfrac{P_{i,k}}{P_{j,k}}=ratio_{i,j,k}=g(v_{i},v_{j},v_{k})

    即:
    Pi,kPj,k=g(vi,vj,vk)\dfrac{P_{i,k}}{P_{j,k}}=g(v_{i},v_{j},v_{k})

    即二者应该尽可能地接近;
    很容易想到用二者的差方来作为代价函数:
    J=i,j,kN(Pi,kPj,kg(vi,vj,vk))2J=\sum_{i,j,k}^N(\dfrac{P_{i,k}}{P_{j,k}}-g(v_{i},v_{j},v_{k}))^2

    但是仔细一看,模型中包含3个单词,这就意味着要在NNN的复杂度上进行计算,太复杂了,最好能再简单点。
    现在我们来仔细思考g(vi,vj,vk)g(v_{i},v_{j},v_{k}),或许它能帮上忙;
    作者的脑洞是这样的:

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

    即:
    Pi,kPj,k=exp((vivj)Tvk)\dfrac{P_{i,k}}{P_{j,k}}=exp((v_{i}-v_{j})^Tv_{k})

    即:
    Pi,kPj,k=exp(viTvkvjTvk)\dfrac{P_{i,k}}{P_{j,k}}=exp(v_{i}^Tv_{k}-v_{j}^Tv_{k})

    即:
    Pi,kPj,k=exp(viTvk)exp(vjTvk)\dfrac{P_{i,k}}{P_{j,k}}=\dfrac{exp(v_{i}^Tv_{k})}{exp(v_{j}^Tv_{k})}

    然后就发现找到简化方法了:只需要让上式分子对应相等,分母对应相等,即:
    Pi,k=exp(viTvk){P_{i,k}}={exp(v_{i}^Tv_{k})}并且Pj,k=exp(vjTvk){P_{j,k}}={exp(v_{j}^Tv_{k})}

    然而分子分母形式相同,就可以把两者统一考虑了,即:
    Pi,j=exp(viTvj){P_{i,j}}={exp(v_{i}^Tv_{j})}

    本来我们追求:
    Pi,kPj,k=g(vi,vj,vk)\dfrac{P_{i,k}}{P_{j,k}}=g(v_{i},v_{j},v_{k})

    现在只需要追求:
    Pi,j=exp(viTvj){P_{i,j}}={exp(v_{i}^Tv_{j})}

    两边取个对数:
    log(Pi,j)=viTvjlog(P_{i,j})=v_{i}^Tv_{j}

    那么代价函数就可以简化为:
    J=i,jN(log(Pi,j)viTvj)2J=\sum_{i,j}^N(log(P_{i,j})-v_{i}^Tv_{j})^2

    现在只需要在NN的复杂度上进行计算,而不是NN*N,现在关于为什么第3步中,外面套一层exp()就清楚了,正是因为套了一层exp(),才使得差形式变成商形式,进而等式两边分子分母对应相等,进而简化模型。
    然而,出了点问题。
    仔细看这两个式子:
    log(Pi,j)=viTvjlog(Pj,i)=vjTvilog(P_{i,j})=v_{i}^Tv_{j}和log(P_{j,i})=v_{j}^Tv_{i}

    log(Pi,j)log(P_{i,j})不等于log(Pj,i)log(P_{j,i})但是viTvjv_{i}^Tv_{j}等于vjTviv_{j}^Tv_{i};即等式左侧不具有对称性,但是右侧具有对称性。
    数学上出了问题。
    补救一下好了。
    现将代价函数中的条件概率展开:
    log(Pi,j)=viTvjlog(P_{i,j})=v_{i}^Tv_{j}

    即为:
    log(Xi,j)log(Xi)=viTvjlog(X_{i,j})-log(X_{i})=v_{i}^Tv_{j}

    将其变为:
    log(Xi,j)=viTvj+bi+bjlog(X_{i,j})=v_{i}^Tv_{j}+b_{i}+b_{j}

    即添了一个偏差项bjb_{j},并将log(Xi)log(X_{i})吸收到偏差项bib_{i}中。
    于是代价函数就变成了:
    J=i,jN(viTvj+bi+bjlog(Xi,j))2J=\sum_{i,j}^N(v_{i}^Tv_{j}+b_{i}+b_{j}-log(X_{i,j}))^2

    然后基于出现频率越高的词对儿权重应该越大的原则,在代价函数中添加权重项,于是代价函数进一步完善:
    J=i,jNf(Xi,j)(viTvj+bi+bjlog(Xi,j))2J=\sum_{i,j}^Nf(X_{i,j})(v_{i}^Tv_{j}+b_{i}+b_{j}-log(X_{i,j}))^2

    具体权重函数应该是怎么样的呢?
    首先应该是非减的,其次当词频过高时,权重不应过分增大,作者通过实验确定权重函数为:
    f(x)={(x/xmax)0.75,if x<xmax1,if x>=xmaxf(x) = \begin{cases} (x/xmax)^{0.75}, & \text{if $x < xmax$} \\ 1, & \text{if $x >= xmax$} \end{cases}

    到此,整个模型就介绍完了。

    Glove和skip-gram、CBOW模型对比

    Cbow/Skip-Gram 是一个local context window的方法,比如使用NS来训练,缺乏了整体的词和词的关系,负样本采用sample的方式会缺失词的关系信息。
    另外,直接训练Skip-Gram类型的算法,很容易使得高曝光词汇得到过多的权重

    Global Vector融合了矩阵分解Latent Semantic Analysis (LSA)的全局统计信息和local context window优势。融入全局的先验统计信息,可以加快模型的训练速度,又可以控制词的相对权重。

    我的理解是skip-gram、CBOW每次都是用一个窗口中的信息更新出词向量,但是Glove则是用了全局的信息(共线矩阵),也就是多个窗口进行更新

    实战教程

    GloVe 教程之实战入门+python gensim 词向量

    参考链接:
    理解GloVe模型

    展开全文
  • GloVe模型介绍

    千次阅读 2019-07-30 11:11:23
    GloVe 本模型结合了以下两个主要模型族的优点:全局矩阵分解和局部上下文窗口方法。我们的模型只训练单词-单词共现矩阵中的非零元素,而不是整个稀疏矩阵或单个上下文窗口的大型语料库,从而有效地利用统计信息。该...

    GloVe

    本模型结合了以下两个主要模型族的优点:全局矩阵分解局部上下文窗口方法。我们的模型只训练单词-单词共现矩阵中的非零元素,而不是整个稀疏矩阵或单个上下文窗口的大型语料库,从而有效地利用统计信息。该模型生成了一个具有意义子结构的向量空间,其在最近的一次单词类比任务中的性能为75%。在相似性任务和命名实体识别方面,它也优于相关模型。

    1 介绍

    大多数的词向量方法都依赖于词向量对之间的距离或角度作为评价这类词表示的本质质量的主要方法。目前有一种新的基于词的类比的方法,通过考察词向量之间的标量距离,而不是词向量之间的各种维数的差异,来研究词向量空间的精细结构。例如:“king is to queen as man is to woman”可表示为king −queen = man – woman

     

    如潜在语义分析(LSA)和本地上下文窗口的方法,如skip-gram模型。目前,这两个方法都存在明显的缺陷。虽然像LSA这样的方法有效地利用了统计信息,但它们在单词类比任务上的表现相对较差,表明向量空间结构不够理想。像skip-gram这样的方法可能在类比任务上做得更好,但是它们不能很好地利用语料库的统计数据,因为它们是在单独的本地上下文窗口上训练的,而不是在全局共现计数上。

     

    在这项工作中,我们分析了产生线性意义方向所必需的模型性质,并认为全局对数-双线性回归模型适合于这样做。提出了一种特殊的加权最小二乘模型,用于训练全局词与词的共现计数,从而有效地利用统计量。

    2 相关工作

    2.1 矩阵分解方法

    用于生成低维单词表示的矩阵分解方法可以追溯到LSA。这些方法利用低秩近似来分解大型矩阵,从而获取语料库的统计信息。这些矩阵捕获的特定信息类型因应用程序的不同而不同。在LSA中,矩阵属于“term-document”类型,即,行对应单词或术语,列对应语料库中的不同文档。相反,超空间类比语言(HAL)利用“term-term”类型的矩阵,即,行和列对应单词,条目对应给定单词在另一个给定单词上下文中出现的次数。

     

    HAL和相关方法的主要问题是最常见的单词贡献不成比例的相似性测量:两个词与and或者the共现的次数,将会对它们的相似性产生很大的影响,尽管表达的语义相关度相对较少。有许多技术可以解决HAL的这一缺点,比如COALS ,其中共现矩阵首先通过基于熵或相关关系的归一化进行转换。这种类型转换的一个优点是对原始的共现计数进行压缩,以便在更小的间隔内更均匀地分布。对于大小合理的语料库,共现计数可能跨越8或9个数量级。

    2.2 基于窗口的方法

    另一种方法是学习有助于在本地上下文窗口中进行预测的单词表示。与矩阵因子分解方法不同,基于窗口的方法的缺点是不能直接对语料库的共现统计量进行操作。相反,这些模型在整个语料库中扫描上下文窗口,这无法利用数据中大量的重复。

    举例:假设有如下语料库,构建基于窗口的共现矩阵

     

     

    3 GloVe 模型

    词出现在语料库的统计数据是信息的主要来源,所有非监督方法学习单词的问题在于如何从这些统计数据生成意义,以及由此产生的词向量可能代表的意义。于是构造了一种新的单词表示模型,我们称之为GloVe ,用于全局向量,因为全局语料库统计数据是由该模型直接捕获的。

     

    一些概念及符号:

    X:词与词的共现计数用表示

    :将单词j在单词i上下文中出现的次数列成表

    :是任何单词在单词i上下文中出现的次数

    :为单词j出现在单词i上下文中的概率

    我们从一个简单的例子开始,它展示了如何从共现概率中直接提取意义的某些方面。例如,考虑两个单词i和j,我们可以取i =冰,j =蒸汽。这些词之间的关系可以通过研究它们与各种探测词k的共出现概率的比值来检验。对于与冰有关而与蒸汽无关的词k,比如k = solid,我们预计的比值会很大。同样,对于与蒸汽相关而与冰无关的单词k,比如k =gas,这个比例应该很小。对于像时尚这样既与冰又与蒸汽有关,或者两者都不相关的单词k,这个比例应该接近于1

    上述论证表明,单词矢量学习的合适起点应该是共现概率的比值而不是概率本身。注意到的比值取决于i、j和k三个单词,最一般的模型采用这种形式:

     (1)

    其中:

    :是单词向量

    :是独立的上下文单词向量

    F可能依赖于一些尚未指定的参数。

     

    F的可能性是巨大的,但是通过强制执行一些操作,我们可以得到一个唯一的选择。

    • 首先,我们希望F编码的信息在向量空间中以的比例表示。由于向量空间本质上是线性结构,因此最自然的方法是使用向量差。在此基础上,我们可以将考虑范围限制在仅依赖于两个目标词的差值的函数F上,即修改上述等式为:

      (2)

    • 接下来,我们注意到上式中的F的自变量是向量,而右边是标量。虽然F可以被看作是一个复杂的函数参数化,例如,一个神经网络,这样做会混淆我们试图捕捉的线性结构。为了避免这个问题,我们可以先取参数的点积,这可以防止F以不合适的方式混合向量维数:

      (3)

    • 接下来,注意对于单词-单词共现矩阵,单词和上下文单词之间的区别是任意的,我们可以自由地交换这些单词。这样做,我们不仅必须交换还有。在这种重新标记下,最终的模型应该是不变的,但是Eqn(3)不是。然而,对称可以通过两个步骤恢复。首先,我们要求F是组之间的同态,即:

    (4)

    • 由Eqn(3)求出:

    (5)

    • Eqn(4)的解是F 为:

    (6)

    • 接下来,我们注意到,如果不是右边的, Eqn(6)将显示交换对称性。然而,这一项与k无关,所以它可以被吸收到偏置,为了。最后,添加一个额外的偏置恢复对称性

    (7)

     

    Eqn(7)是对Eqn(1)的一个极大的简化,但实际上它的定义是错误的,因为对数在参数为0时发散。解决这个问题的一个方法是在对数中添加一个移位,它在保持X的稀疏性的同时避免了分歧。该模型的一个主要缺点是,它对所有同时发生的事件都具有同等的权重,即使是那些很少发生或从未发生的事件。

     

    • 针对这些问题,提出了一种新的加权最小二乘回归模型。将Eqn(7)转化为最小二乘问题,在代价函数中引入加权函数,得到了该模型:

    (8)

    其中:

    V:词汇表的大小

    函数f应遵循如下规则:

    1. f(0) = 0。如果f是连续的函数,它应该在x→0时快速消失,足够使是有限的。
    2. f (x)应该是不递减的,这样就不会出现罕见的共现。
    3. 对于较大的x值,f (x)应该相对较小,这样就不会对频繁出现的共存项进行加权。

    当然,很多函数都满足这些性质,但是我们发现有一类函数可以很好地参数化:

    (9)

    3.1 与其他模型的关系

    skip-gram或ivLBL方法的起点是一个模型,表示单词j出现在单词i上下文中的概率。

    • 假设是一个softmax函数:

    (10)

    • 全局目标函数可以写成:

    (11)

    • 然而,Eqn(11)中的和可以更有效地计算,如果我们首先把i和j值相同的项放在一起:

    (12)

    其中X表示共现矩阵。

    • 由于,我们可以将Eqn(12)重写为:

    (13)

    其中:是pi和qi分布的交叉熵,我们用xi来类比。该目标作为交叉熵误差的加权和,与Eqn(8)的加权最小二乘目标具有一定的形式化相似性。

    首先,交叉熵误差只是概率分布之间许多可能的距离度量之一,它对不太可能发生的事件给予了过多的权重。此外,要使测度有界,需要对模型分布Q进行适当的归一化。这提出了一个计算瓶颈,由于整个词汇在Eqn(10)求和,它将需要考虑不同的距离测量。一个自然的选择是一个最小二乘目标,其中Q和P中的归一化因子被丢弃:

    (14)

    其中,

    • 由于通常是非常大的值,又带来了新的问题,使得优化变得复杂,一个方式是使用对数的平方误差来代替

    (15)

    • 最后,我们观察到,虽然权重因子xi是由skip-gram和ivLBL模型固有的在线训练方法预先设定的,但它并不能保证是最优的。事实上,Mikolov等人观察到,可以通过过滤数据来提高性能,从而降低频繁单词权重因子的有效值。考虑到这一点,我们引入了一个更一般的加权函数,我们也可以自由地使用它来依赖上下文单词。其结果是:

    (16)

    它等价于我们之前推导出的Eqn(8)的代价函数。

    3.2 模型的复杂性

    根据Eqn(8)可知,模型的复杂性取决于共现矩阵X中非零元素的数目。然而,典型的词汇有成千上万的单词,因此可以对X的非零元素的数量进行更严格的限制。为了对X中非零元素的数量作出任何具体的说明,有必要对单词共现的分布做一些假设。

     

    • 特别地,我们假设单词i与单词j共出现的次数可以建模为该词对频率秩的幂函数:

    (17)

    • 语料库中的单词总数与共现矩阵X中所有元素的和成正比:

    (18)

    以下推导有些复杂,不再赘述

    4 实验

    4.1 评价方法

    • 词的类比:“a is to b as c is to ?”

    语义问题:典型的人或地方的类比,like “Athens is to Greece as Berlin is to ?”

    语法问题:动词时态或形容词的形式,like “dance is to dancing as fly is to ?”

    我们根据余弦相似度,通过找到表示最接近的单词d来回答“a is to b as c is to ?”的问题。

    • 词汇相似度
    • 命名实体识别

    四种实体类型:人员、位置、组织和杂项

    • 语料库和训练细节

    我们标记和小写与斯坦福记号赋予器每个语料库,构建一个最频繁的词汇的400000字,然后构造一个矩阵的共存计数X。在构造X时,我们需要考虑要选择多大的上下文窗口以及是否要区分窗口左边和右边的单词。我们将在下面探讨这些选择的效果。在所有的情况下,我们都使用一个递减加权函数,这样的话,单词对中间隔为d个单词的单词对占总数的1/d。这是一种解释这一事实的方法,即非常遥远的词对应该包含关于单词之间关系的相关信息较少

     

    对于我们所有的实验,我们设置,α= 3/4,和训练模型使用AdaGrad ,随机抽样的非零元素x,最初的学习速率为0.05。我们对小于300维的向量执行50次迭代,否则执行100次迭代。除非另有说明,我们使用的上下文是左边十个单词和右边十个单词。

     

    该模型生成了两组词向量,W和,当X对称时,W和是等价的,只是由于它们的随机初始化而不同;这两组向量应该相等。另一方面,有证据表明,对于某些类型的神经网络,对网络的多个实例进行训练,然后将结果结合起来,可以帮助减少过拟合和噪声,总体上提高结果。考虑到这一点,我们选择用W + 的和作为单词向量。这样做通常会在性能上有一个小的提升,其中语义类比任务的提升最大。

     

    4.2 模型分析

    • 向量长度和上下文大小

    1. 观察到大于200维的向量的准确率提升效果变差
    2. 我们研究了改变对称和非对称上下文窗口的窗口大小的影响。对于小而不对称的上下文窗口,语法子任务的性能更好,这与直觉一致,即语法信息主要来自即时上下文,并且可以强烈依赖于词序。另一方面,语义信息通常是非本地的,并且更多的信息是用更大的窗口大小捕获的
    • 语料库的大小

    句法子任务,随着语料库规模的增大,其性能呈单调增长。这是意料之中的,因为较大的语料库通常会产生更好的统计数据。有趣的是,同样的趋势在语义子任务上并不成立,在较小的Wikipedia语料库上训练的模型比在较大的Gigaword语料库上训练的模型做得更好。这可能是由于类比数据集中有大量基于城市和国家的类比,而且维基百科对大多数这样的地点都有相当全面的文章。此外,维基百科的条目是为了吸收新知识而更新的,而Gigaword是一个固定的新闻存储库,其中包含过时的、可能不正确的信息。

    • 运行时间
    • 与word2vec对比

    总运行时间被划分为填充(构造)X所需时间和训练模型所需时间。前者取决于许多因素,包括窗口大小、词汇量大小和语料库大小。

    我们注意到,如果负样本数超过10,word2vec的性能实际上会下降。这可能是因为负抽样法不能很好地逼近目标概率分布。

    在相同的语料库、词汇量、窗口大小和训练时间下,GloVe始终优于word2vec

     

    5 结论

    最近,相当多的注意力集中在分布式单词表示是否是最好的学习方法,是基于计数的方法还是基于预测的方法。基于预测的模型获得了大量支持,基于计数的方法捕获全局统计的效率可能是有利的。但是。我们构建了一个模型,该模型利用计数数据的这一主要优点,同时捕获最近流行的基于对数双线性预测的方法(如word2vec)中有意义的线性子结构。结果,Glove是一个新的全局对数双线性回归模型,用于无监督学习的单词表示,它优于其他模型在单词类比,单词相似性,和命名实体识别任务

     

    ------------------------------------------------------------------------------------------------

    参考资料:https://nlp.stanford.edu/pubs/glove.pdf

    展开全文
  • 【NLP】词嵌入之GloVe详解

    千次阅读 2019-06-21 15:55:47
    什么是GloVeGloVe的全称叫Global Vectors for Word Representation,称为全局词向量,是与word2vec相似的一种词向量表达。 GloVe是如何实现的? GloVe的实现分为以下三步: 根据语料库(corpus)构建一个共现...

    什么是GloVe?

    GloVe的全称叫Global Vectors for Word Representation,称为全局词向量,是与word2vec相似的一种词向量表达。

    GloVe是如何实现的?

    GloVe的实现分为以下三步:

    • 根据语料库(corpus)构建一个共现矩阵(Co-ocurrence Matrix)XX(什么是共现矩阵?),矩阵中的每一个元素Xij代表单词i和上下文单词j在特定大小的上下文窗口(context window)内共同出现的次数。一般而言,这个次数的最小单位是1,但是GloVe不这么认为:它根据两个单词在上下文窗口的距离dd,提出了一个衰减函数(decreasing weighting):decay=1/ddecay=1/d用于计算权重,也就是说距离越远的两个单词所占总计数(total count)的权重越小
    • 构建词向量(Word Vector)和共现矩阵(Co-ocurrence Matrix)之间的近似关系,论文的作者提出以下的公式可以近似地表达两者之间的关系:
      有了公式1之后我们就可以构造它的loss function了:

    • 这个loss function的基本形式就是最简单的mean square loss,只不过在此基础上加了一个权重函数f(Xij),那么这个函数起了什么作用,为什么要添加这个函数呢?我们知道在一个语料库中,肯定存在很多单词他们在一起出现的次数是很多的(frequent co-occurrences),那么我们希望:

      • 1.这些单词的权重要大于那些很少在一起出现的单词(rare co-occurrences),所以这个函数要是非递减函数(non-decreasing);
      • 2.但我们也不希望这个权重过大(overweighted),当到达一定程度之后应该不再增加;
      • 3.如果两个单词没有在一起出现,也就是Xij=0Xij=0,那么他们应该不参与到loss function的计算当中去,也就是f(x)f(x)要满足f(0)=0f(0)=0

       

    GloVe是如何训练的?

    虽然很多人声称GloVe是一种无监督(unsupervised learing)的学习方式(因为它确实不需要人工标注label),但其实它还是有label的,这个label就是公式2中的log(Xij),而公式2中的向量ww和~ww~就是要不断更新/学习的参数,所以本质上它的训练方式跟监督学习的训练方法没什么不一样,都是基于梯度下降的。具体地,这篇论文里的实验是这么做的:采用了AdaGrad的梯度下降算法,对矩阵XX中的所有非零元素进行随机采样,学习曲率(learning rate)设为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。最终学习得到的是两个vector是ww和~ww~,因为XX是对称的(symmetric),所以从原理上讲ww和~ww~是也是对称的,他们唯一的区别是初始化的值不一样,而导致最终的值不一样。所以这两者其实是等价的,都可以当成最终的结果来使用。但是为了提高鲁棒性,我们最终会选择两者之和w+~ww+w~作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。在训练了400亿个token组成的语料后,得到的实验结果如下图所示:

    这个图一共采用了三个指标:语义准确度,语法准确度以及总体准确度。那么我们不难发现Vector Dimension在300时能达到最佳,而context Windows size大致在6到10之间。

    Glove与LSA、word2vec的比较

    LSA(Latent Semantic Analysis)是一种比较早的count-based的词向量表征工具,它也是基于co-occurance matrix的,只不过采用了基于奇异值分解(SVD)的矩阵分解技术对大矩阵进行降维,而我们知道SVD的复杂度是很高的,所以它的计算代价比较大。还有一点是它对所有单词的统计权重都是一致的。而这些缺点在GloVe中被一一克服了。而word2vec最大的缺点则是没有充分利用所有的语料,所以GloVe其实是把两者的优点结合了起来。从这篇论文给出的实验结果来看,GloVe的性能是远超LSA和word2vec的,但网上也有人说GloVe和word2vec实际表现其实差不多。

     

    转载自:https://blog.csdn.net/u014665013/article/details/79642083

    展开全文
  • 多种方法使用GloVe

    千次阅读 2019-06-23 21:05:30
    本文的写作参考可网上很多博客,再次感谢,参考到的博文列在下面,本文对Glove原理,纯Python实现,Pytorch实现,官方C语言方式编译,以及简单方式使用进行记录,方便后面学习的童鞋。 论文地址:GloVe: Global ...

    本文的写作参考可网上很多博客,再次感谢,参考到的博文列在下面,本文对Glove原理,纯Python实现,Pytorch实现,官方C语言方式编译,以及简单方式使用进行记录,方便后面学习的童鞋。

    论文地址:GloVe: Global Vectors for Word Representation
    论文解读:

    Python版实现的核心代码

    完整代码见glove-python

    def build_vocab(corpus):
        """
        Build a vocabulary with word frequencies for an entire corpus.
    
        Returns a dictionary `w -> (i, f)`, mapping word strings to pairs of
        word ID and word corpus frequency.
        """
    
        logger.info("Building vocab from corpus")
    
        vocab = Counter()
        for line in corpus:
            tokens = line.strip().split()
            vocab.update(tokens)
    
        logger.info("Done building vocab from corpus.")
        #{词:(id,词频)} e.g:{'human': (0, 2), 'interface': (1, 3),}
        return {word: (i, freq) for i, (word, freq) in enumerate(vocab.items())}
    
    
    
    @listify
    def build_cooccur(vocab, corpus, window_size=10, min_count=None):
        """
        Build a word co-occurrence list for the given corpus.
    
        This function is a tuple generator, where each element (representing
        a cooccurrence pair) is of the form
    
            (i_main, i_context, cooccurrence)
    
        where `i_main` is the ID of the main word in the cooccurrence and
        `i_context` is the ID of the context word, and `cooccurrence` is the
        `X_{ij}` cooccurrence value as described in Pennington et al.
        (2014).
    
        If `min_count` is not `None`, cooccurrence pairs where either word
        occurs in the corpus fewer than `min_count` times are ignored.
        
        a vocabulary (mapping words to integer word IDs), a corpus (a simple 
        iterator over sentences), and some optional parameters: a context window 
        size and a minimum count (used to drop rare word co-occurrence pairs). 
        """
    
        vocab_size = len(vocab)
        # {词:(id,词频)} e.g:{'human': (0, 2), 'interface': (1, 3),}->{(id,word)}
        id2word = dict((i, word) for word, (i, _) in vocab.items())
    
        # Collect cooccurrences internally as a sparse matrix for passable
        # indexing speed; we'll convert into a list later
        #lil_matrix:List of Lists format,使用两个列表保留非零元素。参看https://blog.csdn.net/nkwangjie/article/details/17502443
        #lil_matrix使用两个列表保存非零元素。data保存每行中的非零元素,rows保存非零元素所在的列。这种格式也很适合逐个添加元素,并且能快速获取行相关的数据。
        cooccurrences = sparse.lil_matrix((vocab_size, vocab_size),  
                                          dtype=np.float64)
    
        for i, line in enumerate(corpus):
            if i % 1000 == 0:  #每处理1000行预料,打印一次日志
                logger.info("Building cooccurrence matrix: on line %i", i)
    
            tokens = line.strip().split()
            # vocab:{词:(id,词频)} e.g:{'human': (0, 2), 'interface': (1, 3),}->{(id,word)}
            #对于语料库每一行,练成一个wordID列表
            token_ids = [vocab[word][0] for word in tokens]
            #or each word ID ii in the sentence, we’ll extract a window of context words to the left of the word
            #对于列表中的每一个wordID i,提取该词左侧window_size范围内词的ID
            for center_i, center_id in enumerate(token_ids):
                # Collect all word IDs in left window of center word
                context_ids = token_ids[max(0, center_i - window_size) : center_i]
                contexts_len = len(context_ids)
                
                #对于中心词i上下文中的每一个词j,将1/d的权重增加进Xij
                #left_i为context_ids中的索引序号,从0开始,left_id为context_ids[left_i]
                for left_i, left_id in enumerate(context_ids):
                    # Distance from center word
                    distance = contexts_len - left_i    #d
    
                    # Weight by inverse of distance between words
                    increment = 1.0 / float(distance)   #权重1/d
    
                    # Build co-occurrence matrix symmetrically (pretend we
                    # are calculating right contexts as well)
                    #左右对称的稀疏矩阵
                    cooccurrences[center_id, left_id] += increment
                    cooccurrences[left_id, center_id] += increment
    
        # Now yield our tuple sequence (dig into the LiL-matrix internals to
        # quickly iterate through all nonzero cells)
        #data保存每行中的非零元素,rows保存非零元素所在的列。
        for i, (row, data) in enumerate(zip(cooccurrences.rows,cooccurrences.data)):
            if min_count is not None and vocab[id2word[i]][1] < min_count:  #词频小于min_count的不予考虑
                continue
            
            for data_idx, j in enumerate(row):  #data_idx,j循环矩阵中每一行和列
                if min_count is not None and vocab[id2word[j]][1] < min_count:
                    continue
                #i:行,j:列,data[data_idx]:大于min_count的Xij值
                yield i, j, data[data_idx]
    
    

    pytorch版实现的核心代码

    from nltk.tokenize import word_tokenize
    from torch.autograd import Variable
    import matplotlib
    import matplotlib.pyplot as plt
    import numpy as np
    import torch
    import torch.optim as optim
    
    
    # 参数设置
    context_size = 3  # 设置窗口的大小
    embed_size = 2  # 词嵌入的维度
    xmax = 2
    alpha = 0.75   # 以上两个参数是定义权重函数是所需要的 可以自己随意设定
    batch_size = 20
    l_rate = 0.001
    num_epochs = 10
    
    # 打开文件 读取语料
    fr = open('short_story.txt', 'r')
    text = fr.read().lower()
    fr.close()
    
    # print(text)
    
    
    # 建立词表
    word_list = word_tokenize(text)   # 分词
    vocab = np.unique(word_list)    # 去重后的词表
    w_list_size = len(word_list)   # 语料中词的个数
    vocab_size = len(vocab)   # 词表的大小
    
    # 词到id的映射
    w_to_i = {word: ind for ind, word in enumerate(vocab)}
    # print(w_to_i)
    
    comat = np.zeros((vocab_size, vocab_size))
    for i in range(w_list_size):
        for j in range(1, context_size+1):
            ind = w_to_i[word_list[i]]  # 将语料中每次词拿出来  转为id
            if i - j > 0:    # 找去窗口内的左边词汇id
                lind = w_to_i[word_list[i-j]]
                comat[ind, lind] += 1.0/j   # 考虑的权重  你若越远 这个权重越低  你若越近 权重越高
            if i + j < w_list_size:    # 找去窗口内的左边词汇id
                rlid = w_to_i[word_list[i+j]]
                comat[ind, rlid] += 1.0/j
    
    print(comat)
    
    # np.nonzero()  输出为一个元组  第一个元组是非零元素所在的行  第二个元素是非零元素所在的列
    coocs = np.transpose(np.nonzero(comat))    # 现在 coocs的每一行就是非零元素所在的坐标
    
    
    # 权重函数
    def wf(x):
        if x < xmax:
            return (x/xmax) ** alpha
        return 1
    
    
    # 设定词向量 和 偏置项
    l_embed, r_embed = [
        [Variable(torch.from_numpy(np.random.normal(0, 0.01, (embed_size, 1))),
                  requires_grad=True) for j in range(vocab_size)] for i in range(2)]
    
    l_biases, r_biases = [
        [Variable(torch.from_numpy(np.random.normal(0, 0.01, 1)),
                  requires_grad=True) for j in range(vocab_size)] for i in range(2)]
    
    # 设定优化器
    optimizer = optim.Adam(l_embed + r_embed + l_biases + r_biases, lr=l_rate)
    
    
    # 产生批数据
    def gen_batch():
        sample = np.random.choice(np.arange(len(coocs)), size=batch_size, replace=False)   # 从中选取batch_size条数据
        l_vecs, r_vecs, covals, l_v_bias, r_v_bias = [], [], [], [], []
        for chosen in sample:
            ind = tuple(coocs[chosen])   # 取出当前所选样本的坐标
            l_vecs.append(l_embed[ind[0]])
            r_vecs.append(r_embed[ind[1]])
            covals.append(comat[ind])
            l_v_bias.append(l_biases[ind[0]])
            r_v_bias.append(r_biases[ind[1]])
        return l_vecs, r_vecs, covals, l_v_bias, r_v_bias
    
    
    # 模型的训练
    for epoch in range(num_epochs):
        num_batches = int(w_list_size/batch_size)   # 看一下一批需去多少数据
        avg_loss = 0.0
        for batch in range(num_batches):
            optimizer.zero_grad()
            l_vecs, r_vecs, covals, l_v_bias, r_v_bias = gen_batch()
            # 定义损失函数
            # For pytorch v2 use, .view(-1) in torch.dot here. Otherwise, no need to use .view(-1).
            loss = sum([torch.mul((torch.dot(l_vecs[i].view(-1), r_vecs[i].view(-1))
                                   + l_v_bias[i] + r_v_bias[i] - np.log(covals[i]))**2, wf(covals[i])) for i in range(batch_size)])
    
            avg_loss += loss.data[0]/num_batches
            loss.backward()   # 反向传播
            optimizer.step()
        print("per epoch average loss:"+str(epoch+1)+": ", avg_loss)
    
    # 这里设置的嵌入维度是2  可以进行可视化
    if embed_size == 2:
        # 从词表中随机选取10个词
        word_inds = np.random.choice(np.arange(len(vocab)), size=10, replace=False)
        for word_ind in word_inds:
            # Create embedding by summing left and right embeddings
            w_embed = (l_embed[word_ind].data + r_embed[word_ind].data).numpy()
            x, y = w_embed[0][0], w_embed[1][0]
            plt.scatter(x, y)
            plt.annotate(vocab[word_ind], xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
        plt.savefig("glove.png")
    

    编译Glove官方代码

    一.编译

    编译需要在Linux下进行,我这里使用的是Ubuntu18.04

    • 获取GloVe,命令:wget http://www-nlp.stanford.edu/software/GloVe-1.2.zip
    • 解压缩:unzip GloVe-1.2.zip
    • cd GloVe-1.2
    • make
      注意,由于我的Linux环境是 ISO C90 and C++98,提示了一大堆的诸如 ISO C90 does not support XXX之类的,网上查了看是long long type 是在 ISO C90 and C++98.才加入的。
      这里在makefile的CFLAGS中加入-std=c99,网上说gcc >3.0都支持C99的。

    二.训练中文的glove词向量

    使用经过jieba分词和去除停用词后的最新维基中文百科文本
    具体操作见:使用中文维基百科进行GloVe实验,GloVe在Linux下的安装与使用

    1.下载中文语料

    中文的语料可以从维基百科下载,这些语料库经常会更新,下载地址,我这里下载的是 ,发布于2019.6.4,大小为1.636GB。

    2. 数据抽取

    #程序名:process_wiki.py
    # -*- coding:utf-8 -*-
    # Author:cskywit
    import logging
    import os.path
    import six
    import sys
    import warnings
    
    warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
    from gensim.corpora import WikiCorpus
    
    if __name__ == '__main__':
     program = os.path.basename(sys.argv[0])
     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))
     # check and process input arguments
     if len(sys.argv) != 3:
         print("Using: python process_wiki.py enwiki.xxx.xml.bz2 wiki.en.text")
         sys.exit(1)
     inp, outp = sys.argv[1:3]
     space = " "
     i = 0
     output = open(outp, 'w',encoding='utf-8')
     wiki = WikiCorpus(inp, lemmatize=False, dictionary={})
     for text in wiki.get_texts():
         output.write(space.join(text) + "\n")
         i=i+1
         if (i%10000==0):
             logger.info("Saved " + str(i) + " articles")
     output.close()
     logger.info("Finished Saved " + str(i) + " articles")
    

    命令行运行:python process_wiki.py zhwiki-latest-pages-articles.xml.bz wiki.zh.text

    3. 繁简转换

    下载opencc工具,opencc-1.0.1-win64解压后在命令行输入命令:

    opencc -i wiki.zh.txt  -o wiki.zh.jianti.txt   -c  t2s.json
    

    4.语料清洗

    经过简体化的文档,仍然有很多脏信息。如数字、标点符号、非中文语言字符等,并且文档中的句子是不能用来训练的,需要进行分词处理。故编写代码,进行非中文字符串的清除,以及分词。这个博客有整理好的停用词。分词及文本清洗的代码如下,此处使用jieba分词工具。每一行为一篇文档,每个文档被分为许多词语的组合,且以空格分开。 这里我建立了一个名为‘zh_simplify’的文件夹,里面存放有几个文本文件,代码中迭代地处理这些文件,并将语料都存于最终的一个文档中。 整个清理过程大约40分钟。

    #程序名:clean_jieba.py
    import jieba
    import os
    import codecs 
    from tqdm import tqdm
    
    
    class MySentences(object):
         def __init__(self, dirname):
            self.dirname = dirname
         def __iter__(self):
            for fname in os.listdir(self.dirname):
                for line in open(os.path.join(self.dirname, fname),'rb'):
                    if len(line) > 0:
                        yield [segment.strip() for segment in jieba.cut(line.strip(), cut_all=False)
                               if segment not in stoplist and len(segment) > 0]
    
    def is_ustr(instr):
        out_str = ''
        for index in range(len(instr)):
            if is_uchar(instr[index]):
                out_str = out_str + instr[index].strip()
        return out_str
    
    
    def is_uchar(uchar):
        # """判断一个unicode是否是汉字"""
        if u'\u4e00' <= uchar <= u'\u9fff':
            return True
    
    if __name__ == '__main__':
        #待分词文件夹
        dirname = 'zh_simplify'
        #用户词典
        user_dict = 'userdict.txt'
        # 读取停用词;
        stop_f = codecs.open('stopwords.txt', 'r', encoding='utf-8')
        stoplist = {}.fromkeys([line.strip() for line in stop_f])
        #加载用户词典
        jieba.load_userdict(user_dict)   
        # 进行jieba分词
        sentences = MySentences(dirname)
        # 分词结果写入文件
        f = codecs.open('wiki_jieba.txt', 'w', encoding='utf-8')
        i = 0
        j = 0
        w = tqdm(sentences, desc=u'分词句子')
        for sentence in w:
            if len(sentence) > 0:
                output = " "
                for d in sentence:
                    # 去除停用词;
                    if d not in stoplist:
                        output += is_ustr(d).strip() + " "
                f.write(output.strip())
                f.write('\r\n')
                i += 1
                if i % 10000 == 0:
                    j += 1
                    w.set_description(u'已分词: %s万个句子'%j)
        f.close()   
    
    

    5.用自己的语料训练

    修改demo.sh即可:

    #if [ ! -e text8 ]; then
    #  if hash wget 2>/dev/null; then
    #    wget http://mattmahoney.net/dc/text8.zip
    #  else
    #    curl -O http://mattmahoney.net/dc/text8.zip
    #  fi
    #  unzip text8.zip
    #  rm text8.zip
    #fi
    //下面为Glove的相关参数
    CORPUS=wiki_jieba.txt            // 这里是已经分好词的文件路径
    VOCAB_FILE=vocab.txt    //#输出的字典
    COOCCURRENCE_FILE=cooccurrence.bin
    COOCCURRENCE_SHUF_FILE=cooccurrence.shuf.bin
    BUILDDIR=build 
    SAVE_FILE=vectors
    VERBOSE=2
    MEMORY=4.0
    VOCAB_MIN_COUNT=5
    VECTOR_SIZE=100        //  词向量维度
    MAX_ITER=15  
    WINDOW_SIZE=15      // 窗口大小
    BINARY=2           //生成二进制文件
    NUM_THREADS=8
    X_MAX=100
    

    在这里插入图片描述
    训练完毕后在vectors.txt就可以看到训练得到的词向量结果。

    6.在gesim中加载和使用

    这里注意word2Vec和glove词向量文件的不同点只需要在vectors.txt这个文件的最开头,加上两个数,第一个数指明一共有多少个向量,第二个数指明每个向量有多少维,就能直接用word2vec的load函数加载了。Gesim中的glove2word2vec已经实现了该转换

    #coding=utf8
    import gensim
    from gensim.test.utils import datapath, get_tmpfile
    from gensim.models  import KeyedVectors
    from gensim.scripts.glove2word2vec import glove2word2vec
    # 输入文件
    glove_file = "G:\\development_workspace\\vscode_workspace\\glove使用\\vectors.txt"
    # 输出文件
    tmp_file = get_tmpfile("G:\\development_workspace\\vscode_workspace\\glove使用\\Wikiglove_word2vec.txt")
    
    # call glove2word2vec script
    # default way (through CLI): python -m gensim.scripts.glove2word2vec --input <glove_file> --output <w2v_file>
    # 开始转换
    glove2word2vec(glove_file, tmp_file)
    # 加载转化后的文件
    #Linux下训练的词向量,在Windows下使用,不加encoding='utf-8', unicode_errors='ignore'会报错
    model = KeyedVectors.load_word2vec_format(tmp_file,encoding='utf-8', unicode_errors='ignore')
    model.save("Wikiglove_word2vec.model")
    word1 = u'阿鲁举'
    if word1 in model:
        print (u"'%s'的词向量为: " % word1)
        print (model[word1])
    else:
        print (u'单词不在字典中!')
    
    

    7.TSNE降维展示

    # encoding:utf8
    import gensim
    import numpy as np
    from sklearn.manifold import TSNE
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import *
    from gensim.models  import KeyedVectors
    
    plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
    plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
    
    w2v_modelName = 'Wikiglove_word2vec.model'
    
    def loadVectors(w2v_modelName,word,top_n):
        model =  gensim.models.Word2Vec.load(w2v_modelName)
        if word in model:
            # print (u"'%s'的词向量为: " % word)
            # print (model[word])
            wordList=[]
            vectorList=[]
            result = model.most_similar(word,topn=top_n)
            print(u"\n与'%s'最相似的词为:\n" % word)
            for e in result:
                print ('%s\t\t相似度概率:%f' % (e[0], e[1]))
            for e in result:
                wordList.append(e[0])
                vectorList.append(model.wv[e[0]])
            wordList.append(word)
            vectorList.append(model.wv[word])
            return wordList,vectorList
        else:
            print (u'单词不在字典中!')
            return None
    
    
    def draw_picture(wordList,vectorList,n_components=2):
        tsne = TSNE(n_components=n_components)
        x_tsne = tsne.fit_transform(vectorList)
        embedding = tsne.embedding_
        print(embedding.shape)
        plt.figure(figsize=(16,16))
        plt.scatter(embedding[:,0],embedding[:,1])
        for i in range(len(x_tsne)):
            x = x_tsne[i][0]
            y = x_tsne[i][1]
            plt.text(x,y,wordList[i])
        plt.show()
    
    if __name__ == '__main__':
        wordList,vectorList = loadVectors(w2v_modelName,u'阿鲁',50)
        draw_picture(wordList,vectorList)
            
    

    glove-python

    GitHub,使用较简单,见极简使用︱Glove-python词向量训练与使用

    展开全文
  • GloVe学习笔记

    千次阅读 2017-05-24 21:50:33
     GloVe是一种用于获取词汇向量表示的无监督学习算法。 对来自语料库的聚合全局字词同现统计进行训练,并且所得到的表示展示了字矢量空间的有趣的线性子结构。   官网主页地址:...
  • GloVe: Global Vectors for Word Representation

    千次阅读 2018-12-17 12:00:51
    学习词的向量空间表示可以很好捕获语法和语义规则信息,但是这些规则的起源并不透明。我们分析和阐明模型需要的这些规则。这是logbilinear regression模型,集合了全局矩阵分解和本地窗口大小的方法。...
  • Glove--入门

    千次阅读 2018-06-11 17:05:53
    一、原理Glove原理部分有大神已经写好的,此处给出链接方便查看:https://blog.csdn.net/coderTC/article/details/73864097Glove和skip-gram、CBOW模型对比Cbow/Skip-Gram 是一个local context window的方法,比如...
  • GloVe原理介绍

    万次阅读 2019-07-24 19:27:53
    1. 引言 当前,学习词向量表示的方法主要有两种类型:一种是基于全局矩阵分解的方法,如LSA,另一种是局部上下文窗口的方法,如Mikolov在2013年提出来的CBOW和skip-gram方法。但是这两种方法都有各自的缺陷,其中,...
  • 理解GloVe模型(Global vectors for word representation)

    万次阅读 多人点赞 2017-06-28 21:20:32
    理解GloVe模型概述 模型目标:进行词的向量化表示,使得向量之间尽可能多地蕴含语义和语法的信息。 输入:语料库 输出:词向量 方法概述:首先基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型学习词向量。...
  • glove 学习笔记

    千次阅读 2017-09-02 14:55:40
    话不多说,入正题。动机:现有的词向量模型, 1 局部上下文建模的方法 例如word2vector 用通俗的话来讲就是,如果两个词在训练语料中出现的上下文比较类似,比如“食堂”和“餐厅”,都在“我”,“去”,“吃饭”...
  • 有很多改进版的word2vec,但是目前还是word2vec最流行,但是Glove也有很多在提及,笔者在自己实验的时候,发现Glove也还是有很多优点以及可以深入研究对比的地方的,所以对其进行了一定的学习。 部分学习内容来源...
  • GloVe模型

    2020-07-09 22:41:20
    1、词向量学习算法有两个主要的模型族: 基于全局矩阵分解的方法,如LSA: 优点:能够有效的利用全局的统计信息; 缺点:在单词类比任务中(如国王VS王后类比于男人VS女人)中表现...2、GloVe模型原理 用P(wj∣wi)P(w
  • GloVe模型训练

    2020-05-26 15:53:09
    GloVe全称是Global Vectors,原文在这里,是2014年提出的模型。下面先对模型做一个大致的解释,然后讨论训练方法。有不当之处请指正。 两类学习词向量的家族: 1 全局矩阵分解方法:像LSA(latent semantic analysis)...
  • 和之前讲过的word2vec(SG和CBOW)一样,glove模型也是一种无监督的词嵌入方法,即词向量学习方法。 glove是一个全局对数双线性回归模型(global log bilinear regression model)。顾名思义,该模型用到了语料库的...
  • GloVe模型的理解及实践(1)

    千次阅读 2018-11-03 10:03:42
    一、GloVe模型的理解 1) 原理 功能:基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型对词汇进行向量化表示 输入:语料库 输出:词向量 2)与Skip-Gram、CBOW模型比较 例如:句子为"dog barked...
  • 学习:GloVe模型

    2019-02-03 10:20:50
    方法概述:首先基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型学习词向量。 统计共现矩阵 设共现矩阵为X,其元素为Xi,jX_{i,j}Xi,j​。 Xi,jX_{i,j}Xi,j​的意义为:在整个语料库中,单词i和单词j共同...
  • Glove模型的理解

    2020-09-24 09:42:01
    Glove模型的理解可以看如下的文章内容 Glove模型的理解 这里添加一些个人的理解,Glove模型主要是针对词频矩阵中的代价函数进行推导的,虽然没有使用神经网络,但是使用的仍然是神经网络的相关的方法,即求出对应的...
  • 深度学习-gloVe模型

    千次阅读 2016-12-16 14:19:50
    下面几篇是deeplearning4j在文本方面的例子,文本方面我还没有实战经验,只是大概看过...把句子的信息和全局的信息结合,目的是在语义和语句上都获得更好的表达效果,下面我们仅从使用的角度上看gloVe模型的代码 pub
  • 参考链接: https://github.com/maciejkula/glove-python ... 说明 本教程需调用glove_python这个包,而不采用Stanford的GloVe,因为前者是python的比较亲民。 天坑 glove_python只支持到Pyt
  • glove模型

    2018-12-05 21:11:13
    学习了word2vec,但是对另一神器glove还有些陌生,这篇文章旨在讲明glove模型。 看到一位大神讲解的GloVe,说的很好,这里直接将贴链接: http://www.fanyeong.com/2018/02/19/glove-in-detail/...
  • 前言 词向量的表示方法主要有两种代表算法,基于不同的思想: 一种是基于全局矩阵分解的方法,如LSA 一种是局部上下文窗口的方法,如Mikolov在2013年提出来的CBOW和skip-gram方法 但是这两种方法都有各自的缺陷,...
  • GloVe模型的理解及实践(2)

    千次阅读 2018-11-03 10:11:35
    一、运行环境 Ubuntu16.04 + python 3.5 二、安装gensim 两种安装方式 1)打开终端 ...sudo easy_install --upgrade gensim ...https://github.com/stanfordnlp/GloVe 四、生成词向量 1.在gl...
  • 加载GloVe模型和Word2Vec模型

    千次阅读 2018-08-29 14:07:45
    1 Google用word2vec预训练了300维的新闻语料的词向量googlenews-vecctors-negative300.bin,解压后3.39个G。 可以用gensim加载进来,但是需要内存足够大。 #加载Google训练的词向量 import gensim ...
  • Glove模型笔记

    2020-06-27 20:53:22
    Glove 优点:融合了矩阵分解Latent Semantic Analysis (LSA)的全局统计信息和local context window优势。融入全局的先验统计信息,可以加快模型的训练速度,又可以控制词的相对权重。 ​ 模型 词向量模型: wiTw~j+...
  • Glove模型训练词向量

    2020-06-04 10:56:07
    参考: https://blog.csdn.net/u014665013/article/details/79642083
  • 目前gensim官方已发布了支持glove格式的方法: 官网说明
  • 在进行自然语言处理中,需要对文章的中的语义进行分析,于是迫切需要一些模型去描述词汇的含义,很多人可能都知道word2vector算法,诚然,word2...今天我来为大家介绍一下GloVe模型,但是重点,还是放在实现上。 ...
  • 在“Word2Vec的实现”一节中,我们在小规模数据集上训练了一个 Word2Vec 词嵌入模型,并通过词向量的余弦相似度搜索近义词。虽然 Word2Vec 已经能够成功地将离散的单词转换为连续的词向量,并能一定程度上地保存词与...
  • word2vec以及GloVe总结

    万次阅读 2017-12-31 12:46:55
    词向量词向量,顾名思义,就是把一个单词或词语表示成一个向量的形式,这是因为在计算机中无法直接处理自然语言,需要把它转化为机器能够理解的语言,比如数值等。最简单的方式是把一个个单词表示成one-hot的形式。...
  • 理解GloVe模型

    千次阅读 2018-07-15 16:05:49
    理解GloVe模型概述模型目标:进行词的向量化表示,使得向量之间尽可能多地蕴含语义和语法的信息。输入:语料库输出:词向量方法概述:首先基于语料库构建词的共现矩阵,然后基于共现矩阵和GloVe模型学习词向量。开始...

空空如也

1 2 3 4 5 ... 20
收藏数 7,944
精华内容 3,177
关键字:

glove