团员分享_NLP基本功(3)——词向量&Word2vec_@Insight_20190329
2021年5月11日 更新
开启更多功能,提升办公效能

前言:本文是团员@Insight “NLP基本功”系列的第3篇分享,用非技术人员能看得懂的方式介绍NLP相关内容,非常赞。



写文章真的需要一些机缘巧合:挺久之前我就接触过 word2vec 算法,一开始没太搞明白,加上网上资料已经很多了,完全没有把它考虑写进 NLP 基本功系列里的想法。


恰好,最近我在啃词向量这一块,多花了些功夫希望吃透 word2vec 算法。

在这个逐步深入的过程中,遇到了不少困惑:

  1. 每篇文章侧重点、写作风格和受众基础不同——有些侧重代码讲解、有些侧重数学原理说明、有些侧重算法逻辑阐述 —— 再加上不同文章之间使用的符号也不一致,要想自己通过零散的文章构建成体系,门槛还是挺高的。
  1. 即使是侧重于阐述算法逻辑的文章,对算法的输入、输出、取值等的描述也大多“一笔带过”。更关键的是,我在阅读这类文章时,感觉很像以前看数学证明的答案:每一步都懂,每一步的逻辑都很严密,但还是有很多疑问 —— 为什么要这么做?为什么可以这么做?这么做有什么用?每个环节的输入输出到底是什么?
  1. 教程、教材类文章,一般都是平铺直叙、重点不突出。在没有老师的情况下,自己阅读效率很低。而且,教材讲解得比较系统,但我们作为PM,并不是要做学术研究,投入产出率就不合适了。


于是乎,就有了系列的第三辑,还是遵循以下原则:

  1. 算法本身足够经典,具备适用性广、基础原理不复杂、不需要特别深的数学知识、有启发性、能触类旁通等特点。
  1. 重视逻辑的美感,尽量多举例、多上图,尽量明确每个环节的输入、输出及取值,降低抽象概念的理解难度。
  1. 侧重对算法原理的讲解,不涉及编码(虽然为了搞懂一些细节,我自己啃了好多遍各种版本的源码及代码注释)。
  1. 尽量结合应用场景,哪怕手头没有直接相关的项目,至少能告诉大家业内的一些著名案例,让有兴趣的同学自行扩展阅读。

总之就是,本文的目标受众是 PM,尤其是非技术型 PM



一、名词解释

词嵌入(Word embedding)

词嵌入,简单来说,就是将词转化或映射为低维向量(一般几百维)的过程。


词向量

词向量,通常指的是进行词嵌入后得到的向量。

不特意注明的话,大家默认 “词向量” ≈ “词嵌入”


词向量的常见算法包括神经网络、Word2vec(CBOW 和 Skip-gram)、Glove,等等。

本文重点介绍 word2vec 算法,且对字向量、词向量、句向量等不做区分。


One-hot 编码

正式介绍词向量前,先介绍个必备的基础概念 —— one-hot 编码(独热编码)。


假设语料库总共有10个字 —— { 人 工 智 能 产 品 经 理 社 区 },那么,以字向量来说:

人 = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]

能 = [ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ]

理 = [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ]


也即:某字在语料库中排在第几位,则 one-hot 编码的第几位即为 1,其它维度均为0。

也即:one-hot 编码是对语料库中各词的索引,或者说它能表示某个词在语料库中的位置。


One-hot 编码当然也是词向量,但并非我们俗称的词向量,而且它有很多缺陷:

  1. 维度灾难 —— 向量维度 = 语料库大小,若语料库很大,向量维度则将会很高(十万、百万级语料库并不鲜见)。
  1. 向量稀疏 —— 几十万甚至几百万个维度,只有一个值为1,其它均为0,使得各词组成的矩阵极其稀疏,数学性质非常不好。
  1. 缺少关联(硬伤)—— 词与词之间完全独立,没有上下文关联,体现不出语义的“远近”。


分布假设(Distributed Representation)

分布假设最早由 Hinton 于 1986 年提出的,核心思路是:上下文相近的词,其语义应该也相似;反之亦然,语义相近的词,其上下文应该也相近


事实证明,分布假设在大多数语境中是成立的。

也即,基于分布假设得到的词向量,应该能体现出语义相似度或语义相关性。


语义相似度,表征的是即词语表达的含义是否接近。

例如,“NLP”和“自然语言处理”,关系非常亲密,上下文非常接近。因此,用 word2vec 生成的词向量也会非常相似(余弦相似度高)。而“NLP”和“文本挖掘”,也比较亲密,但不如前一组,在词向量的余弦相似度上会有所反映。


语义相关性,表征的是词语之间映射关系的强弱。

例如,“北京-中国” 和 “华盛顿-美国” 都是 “首都-国家” 映射,那么计算出来的词向量通常会呈现出 “北京 - 中国 = 华盛顿 - 美国” 的规律。



二、应用场景

因为 word2vec 在以上两方面均表现得非常出色,加上它本质上只是浅层(2层)神经网络,对计算资源需求不高(相比很多深度学习算法),因此成为了词向量领域的标配。


目前,word2vec 已在机器翻译、推荐系统、新闻聚类、话题挖掘等诸多领域均有广泛应用(当然,目前业界基于 word2vec 算法都进行了非常多的改良及衍伸,并且大多数模型都使用了复合算法,word2vec 只是其中一个预训练环节)。


有趣的是,Word2vec 不仅在字、词、句、文章等文本领域 “大杀四方”,在视频、音频、app 等看似与 word 无关的实体上,依然可以 “来者不拒”(网易云音乐就以 Word2vec 作为衡量歌曲相似度的核心算法,想深入了解的可参考 https://new.qq.com/omn/20180107/20180107A08O7T.html。抖音我没去查资料,但我估计也用到了类似的算法)。


大致来说,凡是可以形成序列的实体,基本都可以用 word2vec 建模得到向量,从而构建实体间的相似性或相关性。



三、算法流程&原理

Word2vec 算法有两大模型:一为 CBOW(连续词袋)模型,思路是通过上下文预测中心词;二为 skip-gram(跳字)模型,思路是通过中心词预测上下文。



我们用具体例子来讲解下 word2vec 算法中的 CBOW 模型(skip-gram 原理相同,细节稍有差异)。


假设语料库仍是 { 人 工 智 能 产 品 经 理 社 区 },one-hot 编码有10维,我们的目标是生成3维的字向量。


下图一展示了参与运算的矩阵(向量)及它们的形状;下图二用具体数值(虚构)例举了输入、输出及中间产物。


(图中最右侧是行向量,因为排版方便采用了竖直排列)



下图详细说明算法的流程:


第一步,列出上下文(不包括中心词 “智”)的 one-hot 编码(行向量),作为输入元素。


第二步,对这些 one-hot 编码求和取平均,得到 1x10 的行向量,此为输入层


第三步,将得到的输入层右乘 W1 权重矩阵,得到形状 1x3 的行向量,此为投影层,或者叫全连接层


其中,W1 就是神经网络中的权重矩阵( W1 中每一列的 10 个元素分别对应了 one-hot 编码中每一维的权重,不理解的话可以拉到本文最后一张图处),使用随机数作初值,整个迭代过程是收敛的


第四步,将得到的投影层右乘 W2 权重矩阵,得到形状 1x10 的行向量。


第五步,将此行向量进行 softmax 归一化,得到语料中各词的概率分布,此为输出层


其中,归一化指的是将向量各维度进行处理,使得该向量所有维度的值不小于0,且总和为1,其作用是 “将各维度的值视作各维度的取值概率”(比如上图右侧的向量,第 2 个维度的值是 0.6,表示取到第 2 个维度 { 工 } 的概率是 0.6)。


归一化的方法很多:

例如,将 [ 1, 1, 1, 1, 1, 1, 0, 3, 0, 1 ] 每个维度等比缩小,变为 [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0.3, 0, 0.1 ],使其各分量总和为1。


再例如,令 [ 1, 1, 1, 1, 1, 1, 0, 3, 0, 1 ] 的最大维度取值为 1,其余维度归零,得到 [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ]。这种方法相其实是一种“简单粗暴”的 max 算法,缺点很明显,丢失甚至扭曲了非常多的维度细节信息。


而 Softmax 归一化,则是在 “max” 的基础上,进行了 “soft” 处理,具体公式是用指数函数进行归一处理,公式如下:

i、j 表示向量的维度下标,Vi、Vj 表示相应维度的值,Si 表示向量第 i 维归一化后的值


第六步,因为已知空缺的是“智”,其 one-hot 编码为 [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, ]。因此,将归一化的结果与其进行比较,算出误差值。


理论上,误差值可以用欧氏距离或余弦相似度计算,但基于算法收敛速度等工程方面的考虑,word2vec 使用了用交叉熵损失函数作为误差值(这里用到了统计学和信息论的知识,有兴趣的可以阅读 https://zhuanlan.zhihu.com/p/38241764)。


第七步,利用梯度下降法更新 W1 W2 矩阵,使损失函数越来越小。


重复上述步骤,直到算法收敛。


训练完毕,得到最终的 W1 和 W2。


(咦?怎么就训练完毕了?词向量在哪呢?)


没错!上面的训练过程,本质上是在训练语言模型,词向量只是顺带产物而已(虽然现在很多时候,语言模型本身已不重要,词向量才是真的重要,构建完词向量后,语言模型可能就被丢在一边了)。


其实,W1 矩阵的每一行,就是一个词向量。


这里涉及到 W1 矩阵的一些有趣性质,我们一起来看看:

如下图,one-hot 编码第 4 位(“能”)为 1。它与 W1 相乘,得到的向量刚好就是 W1 第 4 行,也即“能”的词向量就是 [ 2, 2, 6 ]。

更一般地,one-hot 编码第 n 位为 1。它与 W1 相乘,得到的向量刚好就是 W1 第 n 行,也即语料库中第 n 个词的词向量。


因此,W1 的每一行就是一个词向量,或者说 one-hot 编码的索引值,其实也是 W1 矩阵的行索引值


有些文献省略了 one-hot 编码的输入层(这类文献都被我归类为 “无良文献”),直接随机初始化 W1 作为输入矩阵进行训练,最终得到的 W1 是一样的。因为 one-hot 编码的作用,本质上只是在 W1 矩阵中进行行索引(这个细节困扰了我挺久,直到我在某个知乎的 Q&A 中看到相关解释才释然)。


从算法结构来看,word2vec 其实是一个浅层(2层)的神经网络,且 W1 矩阵的每一列都都对应了 one-hot 编码每一维的权重(如下图)。这也是 W1 被叫做权重矩阵的原因。


另外,Word2vec 的词向量其实有两组,一组是【输入词向量】,也就是上面说到的 W1 中每一行对应的向量;另一组是【输出词向量】,指的是 W2 中每一列对应的列向量,但关于为什么大家都用输入词向量,我并没有查到太多资料,有线索的同学可以加我微信(116978517)交流。



四、一些脑洞

在写这篇文章期间,我突然想到之前公司一直想做的一件事 —— 建立行业相关性,甚至行业上下游的数值模型。


举个例子,招聘网站一般都会有这几个行业:IT、互联网、电子商务、网络游戏。这里面,有些是包含与被包含的关系,有些是并列的关系,有些又是聚合的形式(互联网/电子商务)。


换句话说,仅这几个行业,要人工定义它们的距离或相关性,都很难理出清晰的逻辑规则来,更不要说那么多行业千丝万缕、纷繁复杂的联系了。


这个时候,可以尝试将候选人履历中的行业,按照任职时间顺序排列。此时,这人的行业序列就相当于一个“句子”,每个行业相当于一个词。


它是符合分布假设的,因为 “上下文”(之前或之后任职的行业)类似的行业,自身也会非常相似或强相关;非常相似或强相关的行业,“上下文” 自然也会非常相似。


因此,按照 word2vec 的思路,可以构建出每个行业的向量,并在很大程度上刻画出行业之间的相似性或相关性。虽然最终还是缺少行业上下游的信息,但至少可以做到上下游行业之间距离会比较近。


而且,这种方法最大的好处,就是无需分析行业里的具体内容,也不需要去百科、行业资讯网站等开放领域爬取并分析大量数据。



五、一句话回顾

Word2vec 就是不断输入语料库中的词语及其上下文(one-hot 编码),利用梯度下降及损失函数最小化等方法,迭代得到最后的向量值。


有任何想法或疑问,欢迎加我微信(116978517)交流。

以上,感谢!



附:insight的前2篇文章在


-END-


以上内容,来自饭团“AI产品经理大本营”,点击这里可关注:http://fantuan.guokr.net/groups/219/ (如果遇到支付问题,请先关注饭团的官方微信服务号“fantuan-app”)


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

作者:黄钊hanniman,图灵机器人-人才战略官,前腾讯产品经理,6年AI实战经验,9年互联网背景,微信公众号/知乎/在行ID“hanniman”,饭团“AI产品经理大本营”,分享人工智能相关原创干货,200页PPT《人工智能产品经理的新起点》被业内广泛好评,下载量1万+。