word2vec(嵌入空间)

1  word2vec

本文会通过 图书馆 图书排布的例子引入词的表征,继而通过最小化借书成本过渡到skip-gram的模型,阐述word2vec训练和最小化信息熵的关联

词表征? 词嵌入 ? 词向量 ? word2vec ?

  • 词表征是比较宽泛的概念,词可以通过各种方式来表征,比如one-hot 比如 词嵌入 等等
  • 词嵌入特指由神经网络模型得到的低维实数向量表示
  • word2vec 用来训练词嵌入或者低维向量表示的工具,或者是指通过(cbow/skip-gram)训练词向量的工具

1.1  word2vec小例子

1.1.1  腾讯词向量

腾讯AI Lab此次公开的中文词向量数据包含800多万中文词汇,一共大约有6个多G,中每个词对应一个200维的向量。相比现有的中文词向量数据,腾讯AI Lab的中文词向量着重提升了以下3个方面,相比已有各类中文词向量大大改善了其质量和可用性

In [1]:

'''
加载预训练的词向量
'''
import gensim
model = gensim.models.KeyedVectors.load_word2vec_format('data/Tencent_AILab_ChineseEmbedding.txt',binary=False)
#model = gensim.models.KeyedVectors.load_word2vec_format('data/test.txt',binary=False)

#print(model['你好'])

In [79]:

# new_model = gensim.models.Word2Vec.load('./mymodel')

# 词向量展示


y0 = model[u'机器学习']
print "【机器学习】的词向量"
print y0
print "-----------------------------------------------------------------------\n"

# 计算两个词的相似度/相关程度
y1 = model.similarity(u"刀削面", u"拉面")
print u"【刀削面】和【拉面】的相似度:", y1
print "-----------------------------------------------------------------------\n"

# 计算某个词的相关词列表
y2 = model.most_similar(u"内马尔", topn=20)  # 20个最相关的
print u"和【内马尔】最相关的词有:\n"
for item in y2:
    print item[0], item[1]
print "----------------------------------------------------------------------\n"

# # 寻找对应关系
print ' "男人" is to "爸爸" as "女人" is to ...? \n'
y3 = model.most_similar([u'女人', u'爸爸'], [u'男人'], topn=1)
for item in y3:
    print item[0], item[1]
print "----------------------------------------------------------------------\n"

# more_examples = ["he his she", "big bigger bad", "going went being"]
# for example in more_examples:
#     a, b, x = example.split()
#     predicted = model.most_similar([x, b], [a])[0][0]
#     print "'%s' is to '%s' as '%s' is to '%s'" % (a, b, x, predicted)
# print "--------\n"

# 寻找不合群的词
y4 = model.doesnt_match(u"小花仙 赛尔号 摩尔庄园 花语学园 机器学习".split())
print "小花仙 赛尔号 摩尔庄园 花语学园 机器学习"
print u"不合群的词:", y4
print "----------------------------------------------------------------------\n"
【机器学习】的词向量
[ 0.268821  0.374011  0.048173 -0.084303  0.070437 -0.10764   0.33355
  0.579136  0.053251  0.34239  -0.318659 -0.160654 -0.132568  0.183226
 -0.314756  0.233036 -0.234871 -0.138369  0.024055 -0.258634 -0.438956
 -0.153926 -0.236948  0.127202  0.115107  0.069613 -0.218246  0.695834
  0.02518   0.456213  0.059061  0.139309 -0.136434 -0.13065   0.103284
 -0.238611  0.235508 -0.196108  0.028411  0.446873  0.279813 -0.398435
  0.712249  0.08959   0.233198 -0.213576 -0.567725 -0.327889 -0.238967
 -0.319057 -0.010598 -0.372302 -0.118541  0.131923  0.116723  0.004726
  0.288191  0.325959  0.286697 -0.44142   0.246276  0.619589  0.339279
 -0.038396 -0.397531 -0.186556 -0.160514  0.927275 -0.104519  0.396665
 -0.611046  0.013532  0.119666 -0.119613 -0.48777   0.501677 -0.287776
 -0.092307  0.291847 -0.10066   0.048965 -0.308137 -0.226268 -0.036458
  0.425515 -0.48655  -0.171464  0.067759 -0.205915  0.159558  0.185997
  0.14787  -0.131824  0.072403  0.090928  0.29442  -0.329456 -0.184774
 -0.518765 -0.188753  0.173868 -0.679649 -0.117254  0.39902  -0.270989
 -0.0569   -0.038573 -0.578323  0.566631  0.208982 -0.189936 -0.336658
  0.040923 -0.612761  0.023871 -0.067389  0.299926 -0.39063   0.077012
 -0.449197  0.422333 -0.784626  0.231474 -0.015135  0.011651 -0.414033
 -0.288822  0.101586 -0.394551  0.10625   0.117307  0.031459  0.095635
 -0.177649 -0.26475   0.201286 -0.137197 -0.190847 -0.021317 -0.186368
 -0.503478 -0.423046 -0.20934  -0.50306   0.046986 -0.185665  0.453788
  0.66856   0.248997 -0.192363  0.15279   0.092234  0.426745 -0.029228
 -0.416108  0.431325  0.022669  0.644072  0.174496  0.07909   0.715548
 -0.044993  0.0815    0.099158 -0.036515 -0.415035 -0.036643 -0.150027
  0.448151 -0.216194 -0.118068 -0.071207 -0.146923  0.478465 -0.226765
 -0.280362 -0.169532  0.122062 -0.616625  0.527443 -0.560551  0.014523
  0.420545  0.249857 -0.160652 -0.171614 -0.292688 -0.047544 -0.095934
  0.264333  0.141502  0.39602  -0.101499  0.287445  0.235788  0.329599
 -0.003271  0.218781 -0.031423  0.722968]
-----------------------------------------------------------------------

【刀削面】和【拉面】的相似度: 0.7829688360842704
-----------------------------------------------------------------------

和【内马尔】最相关的词有:

梅西 0.881669461727
巴萨 0.876953601837
c罗 0.87518632412
大巴黎 0.87434566021
姆巴佩 0.870280563831
皇马 0.864346623421
巴黎圣日耳曼 0.859097242355
伊涅斯塔 0.856794178486
格列兹曼 0.851144790649
卡瓦尼 0.840297698975
迪玛利亚 0.839150488377
哈梅斯 0.835917949677
库蒂尼奥 0.830202996731
迪马利亚 0.821282744408
阿尔维斯 0.820207297802
j罗 0.819675862789
克罗斯 0.818643033504
格里兹曼 0.818125545979
拉基蒂奇 0.816750466824
马竞 0.808085143566
----------------------------------------------------------------------

 "男人" is to "爸爸" as "女人" is to ...? 

妈妈 0.917139410973
----------------------------------------------------------------------

小花仙 赛尔号 摩尔庄园 花语学园 机器学习
不合群的词: 机器学习
----------------------------------------------------------------------

运行结果

1.1.2  词向量游戏

In [80]:

words = [u'汽车', u'人类', u'游戏', u'学校', u'微信',u'煤炭', u'赛尔号', u'河豚',u'海王', u'温泉', u'机器学习',u'阿森纳']

# 求解distance
def get_distance(left, right):
    return model.distance(left, right)


def guess_your_think(target_word):
    min_dis = 1.0
    sim_word = ""
    for word in words:
        dis = get_distance(word, target_word)
        # print word, dis
        if dis < min_dis:
            sim_word = word
            min_dis = dis
    return sim_word

print ("====================从里面选择一词,并填写一个你认为与它相关的词====================")
print "[" + " ".join(words) + "]"
word = raw_input()
guess_word = guess_your_think(word.decode('utf8'))

print u"=====================你想的词为[%s]=======================" % guess_word
====================从里面选择一词,并填写一个你认为与它相关的词====================
[汽车 人类 游戏 学校 微信 煤炭 赛尔号 河豚 海王 温泉 机器学习 阿森纳]
曼联
=====================你想的词为[阿森纳]=======================

1.2  词向量表征

1.2.1  one-hot表征

“话筒”表示为 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0...]

“麦克”表示为 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0...]

每个词都是茫茫 0 海中的一个 1。这种 One-hot Representation 如果采用稀疏方式存储,会是非常的简洁:也就是给每个词分配一个数字 ID。比如刚才的例子中,话筒记为 3,麦克记为 8(假设从 0 开始记)。

现在我们分析他的不当处。

  • 1、向量的维度会随着句子的词的数量类型增大而增大;
  • 2、任意两个词之间都是孤立的,根本无法表示出在语义层面上词语词之间的相关信息,而这一点是致命的。

1.2.2  嵌入低维度的空间

如果用传统的稀疏表示法表示词,在解决某些任务的时候(比如构建语言模型)会造成维数灾难。使用低维的词向量就没这样的问题。同时从实践上看,高维的特征如果要套用 Deep Learning,其复杂度几乎是难以接受的,因此低维的词向量比较常用(通常在50-300维)

1.3  从书本的向量表征到词向量表征

1.3.1  图书馆摆书的秘密

假如你是图书馆管理员,会怎么去摆放你的书? 目的是什么

图书馆一角落

放书的套路

其实不是哪本书,而是放书的套路

很明显,图书馆中书的摆放是有“套路”的:它们不是随机摆放的,而是分门别类地放置的,比如数学类放一个区,文学类放一个区,计算机类也放一个区;同一个类也有很多子类,比如数学类中,数学分析放一个子区,代数放一个子区,几何放一个子区

1.3.2  为什么要这么摆放呢

相近的书总是在一起

其实原因的核心在于:我们通常不只是借一本书。 这样一来,图书分类的作用就很明显了。图书分类就是把相近的书放在一起,而每个人同一次要借的书也会相近的,所以图书分类会让大多数人的找书、借书过程更加省力!这又是一个“偷懒攻略”。也就是说,将我们要处理的东西分类放好,相近的放在一起。生活中我们会将常用的东西分类放在触手可及的地方,也是基于同样的原理。图示为一个小朋友的借书单,借的书基本上都是很相似的,也就是我们把相似的书放在比较靠近的地方,可以节约借书成本

小盆友的借书单

1.3.3  借书成本最小化和最小熵

“最小熵原理”就是致力于降低学习成本,试图用最小的成本完成同样的事情

那么,借书成本最小化和最小熵有什么关系呢,熵是不确定性的度量,最大熵原理的意思是说我们在对结果进行预测的时候,要承认我们的无知,所以要最大化不确定性,才能达到最客观的结果,而对于最小熵, 可以从这两个角度来理解

  1. 直观的理解:文明的演化过程总是一个探索和发现的过程,经过我们的努力,越多越多的东西从不确定变成了确定,熵逐渐地趋于最小化。因此,要从一堆原始数据中发现隐含的规律(把文明重演出来),就要在这个规律是否有助于降低总体的信息熵,因为这代表了文明演化的方向,这就是“最小熵原理”。

  2. 稍严谨的理解:“知识”有一个固有信息熵,代表它的本质信息量。但在我们彻底理解它之前,总会有未知的因素,这使得我们在表达它的时候带有冗余,所以按照我们当前的理解去估算信息熵,得到的事实上是固有信息熵的上界,而信息熵最小化意味着我们要想办法降低这个上界,也就意味着减少了未知,逼近固有信息熵。

回到借书这个问题,假设刚开始我们对图书馆的书都不了解,就会随机分布,表示我们有很多的不确定,当有越来越多的人来借书后,我们积累了很多借书的记录,我们就会从中发现一些隐含的规律,比如借《机器学习》的书的人大部分会去借《统计学习方法》等等,这些信息有助于我们更新书的一个布局(把经常会一起借的书放在一起),从而降低了信息熵,也减少了借书的成本,也就是这里借书成本最小化是我们在掌握了很多人的借书记录后,优化书的布局,降低总体的借书成本,从而减少总体信息熵的过程

1.3.4  从book embedding 到 word embedding

我们再重新捋一下思路:是这样的,我们把每个词当作一本书,每个句子都可以看成每个人的“借书记录”,这样我们就能知道哪两本“书”经常被一起借了是吧?按照我们前面讨论了一大通的图书馆最佳放书方案,我们就可以把“书”的最佳位置找出来

反过来,找出一个最佳放书方案也就简单了,把图书馆的每个人的借书记录都当成一个句子,每本书当成一个词,设置词向量维度为3,送入Word2Vec训练一下,出来的词向量,就是最佳放书方案了。

那些doc2vec、node2vec、everything2vec,基本上都是这样做的。

所以,开始的问题就很清晰了:将图书馆的每本书的三维坐标记录下来,这不就是一个实实在在的“book embedding”?相近的书的向量也相近呀,跟词向量的特性完美对应~所以,自从有了图书馆,就有了embedding,尽管那时候还没有坐标系,当然也没有计算机。

1.4  word2vec在NLP中的重要意义

通常来说,NLP中监督任务的基本套路都可以用三个积木来进行归纳:

  • 文本数据搜集和预处理

  • 将文本进行编码和表征

  • 设计模型解决具体任务

NLP人也花了一些时间去思考NLP中究竟该如何设计一些更通用的可以迁移利用的东西,而不是所有的任务都要“from scratch”。 文本的编码和表征对于NLP任务,因为如何尽量利用已有的知识、经验和工具,避免重复造轮子,想尽一切办法“站在巨人的肩膀上”快速发展,我想大概也是最朴素的“发展是硬道理”的体现。这里文本的编码和表征相当于巨人的肩膀, 我们尽可能希望文本的表征能够携带更多的含义, 可以给后面的具体任务提供很好的支撑

浅层含义
假设每一词可以表征为三维空间的一个点,那么一句话,一段话就可以表征为这个空间里的一条曲线(或者曲面),这时候,我们可以通过求这个曲线(或者曲面)的重心(词向量的平均)来表征这个句子,如果我们需要求两个句子的相似度,就可以通过求解两个曲线(曲面)的重心的欧式距离。

更深层含义
word2vec的贡献远不止是给每一个词赋予一个分布式的表征,私以为,它带来了一种全新的NLP模型建立方法,在这之前,大多数NLP任务都要在如何挖掘更多文本语义特征上花费大量时间,甚至这一部分工作占去了整个任务工作量的绝大部分,而以word2vec为代表的distributed representation方法大量涌现后(尤其是因为大规模语料上的预训练词向量成为现实,并且被证明确实行之有效之后),算法人员发现利用word2vec在预训练上学习到的词向量,初始化他们自己模型的第一层,会带来极大效果的提升,以至于这五年以来,几乎一个业内的默认做法便是要用了无论word2vec还是GloVe预训练的词向量,作为模型的第一层,如果不这么做,大约只有两个原因:

  • 你很土豪,有钱标注大量监督数据;
  • 你在蛮干。

而这一个思想,绝不是如它表象所显示的一样,似乎和过去做文本特征没什么太大区别,是的,表象确实是这样,无非是把一个词用了一堆数字来表征而已,这和离散化的特征有什么本质区别吗?有,因为它开启了一种全新的NLP模型训练方式——迁移学习。基本思想便是利用一切可以利用的现成知识,达到快速学习的目的,这和人类的进化历程何其相似。 虽然咿咿呀呀囫囵吞枣似的刚开始能够说得三两个词,然而这是“NLP的一小步,人类AI的一大步”。正如人类语言产生之初,一旦某个原始人类的喉部发出的某个音节,经无比智慧和刨根问底考证的史学家研究证实了它具有某个明确的指代意义(无论它指代什么,即便是人类的排泄物),这便无比庄严的宣示着一个全新物种的诞生,我想迁移学习在NLP中的这一小步,大概与此同担当。

1.4.1  存在的问题

  • 无法处理语义的歧义问题, 因为每一个词被表征为空间中的一个点,如果一个词有多重含义,无法很好的表达

1.4.2  词表征优化, 以及最新的研究

1.4.3  参考

这篇jupyter借鉴了苏神的博客关于最小熵和word2vec的内容,感觉比较有启发

参考博客地址:https://spaces.ac.cn/archives/6191 安利下苏神的博客,里面有很多精彩的内容

猜你喜欢

转载自blog.csdn.net/wyq_wyj/article/details/86498646
今日推荐