week6-Word Embedding
Word Embedding
资料list:
- 理解 Word2Vec 之 Skip-Gram 模型 - 天雨粟的文章 - 知乎 https://zhuanlan.zhihu.com/p/27234078
- [NLP] 秒懂词向量Word2vec的本质 - 穆文的文章 - 知乎 https://zhuanlan.zhihu.com/p/26306795
- https://towardsdatascience.com/skip-gram-nlp-context-words-prediction-algorithm-5bbf34f84e0c
- https://towardsdatascience.com/word2vec-skip-gram-model-part-1-intuition-78614e4d6e0b
什么是 Word2vec ?
Word2vec就是word embdding的一种方法,通俗的说,就是将结构化数据转换成非结构化数据(转换成数值形式)。
假设全世界所有的词语总共有 V 个,这 V 个词语有自己的先后顺序,假设『吴彦祖』这个词是第1个词,『我』这个单词是第2个词,那么『吴彦祖』就可以表示为一个 V 维全零向量、把第1个位置的0变成1,而『我』同样表示为 V 维全零向量、把第2个位置的0变成1。这样,每个词语都可以找到属于自己的唯一表示。
Word2Vec模型中,主要有Skip-Gram和CBOW两种模型。
Skip-Gram是给定input word来预测上下文。而CBOW是给定上下文,来预测input word。
Word2Vec的整个建模过程实际上与自编码器(auto-encoder)的思想很相似,即先基于训练数据构建一个神经网络,当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐层的权重矩阵——后面我们将会看到这些权重在Word2Vec中实际上就是我们试图去学习的“word vectors”。基于训练数据建模的过程,我们给它一个名字叫“Fake Task”,意味着建模并不是我们最终的目的。
训练模型的真正目的是获得模型基于训练数据学得的隐层权重。
Word2vec之Skip-gram
模型任务是给定句子中间的特定单词(输入单词),查看附近的单词并随机选择一个。网络将告诉我们词汇表中每个单词成为我们选择的“附近单词”的概率。例如,如果您为经过训练的网络提供输入词“苏维埃”,则“联盟”和“俄罗斯”等单词的输出概率将比“西瓜”和“袋鼠”等不相关的单词高得多。
接下来我们来看看如何训练我们的神经网络。假如我们有一个句子**“The dog barked at the mailman”。**
首先我们选句子中间的一个词作为我们的输入词,例如我们选取“dog”作为input word;
有了input word以后,我们再定义一个叫做skip_window的参数,它代表着我们从当前input word的一侧(左边或右边)选取词的数量。如果我们设置skip_window=2,那么我们最终获得窗口中的词(包括input word在内)就是**[‘The’, ‘dog’,‘barked’, ‘at’]**。skip_window=2代表着选取左input word左侧2个词和右侧2个词进入我们的窗口,所以整个窗口大小span=2×2=4。另一个参数叫num_skips,它代表着我们从整个窗口中选取多少个不同的词作为我们的output word,当skip_window=2,num_skips=2时,我们将会得到两组 (input word, output word) 形式的训练数据,即 (‘dog’, ‘barked’),(‘dog’, ‘the’)。
另一个例子是“The quick brown fox jumps over the lazy dog.”used a small window size of 2 just for the example.以蓝色突出显示的单词是输入单词。
神经网络基于这些训练数据将会输出一个概率分布,这个概率代表着我们的词典中的每个词是output word的可能性。
这句话有点绕,我们来看个栗子。第二步中我们在设置skip_window和num_skips=2的情况下获得了两组训练数据。假如我们先拿一组数据 (‘dog’, ‘barked’) 来训练神经网络,那么模型通过学习这个训练样本,会告诉我们词汇表中每个单词是“barked”的概率大小。
也就是模型的输出概率代表着到我们词典中每个词有多大可能性跟input word同时出现。
神经网络架构如下图所示。最终模型的输出是一个概率分布。
一些补充:
首先,我们都知道神经网络只能接受数值输入,我们不可能把一个单词字符串作为输入,因此我们得想个办法来表示这些单词。最常用的办法就是基于训练文档来构建我们自己的词汇表(vocabulary)再对单词进行one-hot编码。
假设从我们的训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants=[0,0,1,0,…,0])。
还是上面的例子,“The dog barked at the mailman”,那么我们基于这个句子,可以构建一个大小为5的词汇表(忽略大小写和标点符号):(“the”, “dog”, “barked”, “at”, “mailman”),我们对这个词汇表的单词进行编号0-4。那么”dog“就可以被表示为一个5维向量[0, 1, 0, 0, 0]。
模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。
Skip-gram隐藏层
我们最终的目标就是学习这个隐层的权重矩阵。
如果我们现在想用300个特征来表示一个单词(即每个词可以被表示为300维的向量)。那么隐层的权重矩阵应该为10000行,300列(隐层有300个结点)。词向量的维度是一个可以调节的超参数(在Python的gensim包中封装的Word2Vec接口默认的词向量大小为100, window_size为5)。
看下面的图片,左右两张图分别从不同角度代表了输入层-隐层的权重矩阵。左图中每一列代表一个10000维的词向量和隐层单个神经元连接的权重向量。从右边的图来看,每一行实际上代表了每个单词的词向量。
所以我们最终的目标就是学习这个隐层的权重矩阵。
我们现在回来接着通过模型的定义来训练我们的这个模型。
上面我们提到,input word和output word都会被我们进行one-hot编码。仔细想一下,我们的输入被one-hot编码以后大多数维度上都是0(实际上仅有一个位置为1),所以这个向量相当稀疏,那么会造成什么结果呢。如果我们将一个1 x 10000的向量和10000 x 300的矩阵相乘,它会消耗相当大的计算资源,为了高效计算,它仅仅会选择矩阵中对应的向量中维度值为1的索引行(这句话很绕),看图就明白。
我们来看一下上图中的矩阵运算,左边分别是1 x 5和5 x 3的矩阵,结果应该是1 x 3的矩阵,按照矩阵乘法的规则,结果的第一行第一列元素为0×17+0×23+0×4+1×10+0×11=10,同理可得其余两个元素为12,19。如果10000个维度的矩阵采用这样的计算方式是十分低效的。
为了有效地进行计算,这种稀疏状态下不会进行矩阵乘法计算,可以看到矩阵的计算的结果实际上是矩阵对应的向量中值为1的索引,上面的例子中,左边向量中取值为1的对应维度为3(下标从0开始),那么计算结果就是矩阵的第3行(下标从0开始)—— [10, 12, 19],这样模型中的隐层权重矩阵便成了一个”查找表“(lookup table),进行矩阵计算时,直接去查输入向量中取值为1的维度下对应的那些权重值。隐层的输出就是每个输入单词的“嵌入词向量”。
Skip-gram隐藏层
经过神经网络隐层的计算,ants这个词会从一个1 x 10000的向量变成1 x 300的向量,再被输入到输出层。输出层是一个softmax回归分类器,它的每个结点将会输出一个0-1之间的值(概率),这些所有输出层神经元结点的概率之和为1。
下面是一个例子,训练样本为 (input word: “ants”, output word: “car”) 的计算示意图。
直觉上的理解
下面我们将通过直觉来进行一些思考。
如果两个不同的单词有着非常相似的“上下文”(也就是窗口单词很相似,比如“Kitty climbed the tree”和“Cat climbed the tree”),那么通过我们的模型训练,这两个单词的嵌入向量将非常相似。
那么两个单词拥有相似的“上下文”到底是什么含义呢?比如对于同义词“intelligent”和“smart”,我们觉得这两个单词应该拥有相同的“上下文”。而例如”engine“和”transmission“这样相关的词语,可能也拥有着相似的上下文。
实际上,这种方法实际上也可以帮助你进行词干化(stemming),例如,神经网络对”ant“和”ants”两个单词会习得相似的词向量。
词干化(stemming)就是去除词缀得到词根的过程。
如何在skip-gram模型上进行高效的训练
在第一部分讲解完成后,我们会发现Word2Vec模型是一个超级大的神经网络(权重矩阵规模非常大)。
举个栗子,我们拥有10000个单词的词汇表,我们如果想嵌入300维的词向量,那么我们的输入-隐层权重矩阵和隐层-输出层的权重矩阵都会有 10000 x 300 = 300万个权重,在如此庞大的神经网络中进行梯度下降是相当慢的。更糟糕的是,你需要大量的训练数据来调整这些权重并且避免过拟合。百万数量级的权重矩阵和亿万数量级的训练样本意味着训练这个模型将会是个灾难(太凶残了)。
- 将常见的单词组合(word pairs)或者词组作为单个“words”来处理。
- 对高频次单词进行抽样来减少训练样本的个数。
- 对优化目标采用“negative sampling”方法,这样每个训练样本的训练只会更新一小部分的模型权重,从而降低计算负担。
事实证明,对常用词抽样并且对优化目标采用“negative sampling”不仅降低了训练过程中的计算负担,还提高了训练的词向量的质量。
Word pairs and “phases”
对高频词抽样
在第一部分的讲解中,我们展示了训练样本是如何从原始文档中生成出来的,这里我再重复一次。我们的原始文本为“The quick brown fox jumps over the laze dog”,如果我使用大小为2的窗口,那么我们可以得到图中展示的那些训练样本。
但是对于“the”这种常用高频单词,这样的处理方式会存在下面两个问题:
- 当我们得到成对的单词训练样本时,(“fox”, “the”) 这样的训练样本并不会给我们提供关于“fox”更多的语义信息,因为“the”在每个单词的上下文中几乎都会出现。
- 由于在文本中“the”这样的常用词出现概率很大,因此我们将会有大量的(”the“,…)这样的训练样本,而这些样本数量远远超过了我们学习“the”这个词向量所需的训练样本数。
Word2Vec通过“抽样”模式来解决这种高频词问题。它的基本思想如下:对于我们在训练原始文本中遇到的每一个单词,它们都有一定概率被我们从文本中删掉,而这个被删除的概率与单词的频率有关。
如果我们设置窗口大小span=10(即skip_window=5),并且从我们的文本中删除所有的“the”,那么会有下面的结果:
- 由于我们删除了文本中所有的“the”,那么在我们的训练样本中,“the”这个词永远也不会出现在我们的上下文窗口中。
- 当“the”作为input word时,我们的训练样本数至少会减少10个。
这句话应该这么理解,假如我们的文本中仅出现了一个“the”,那么当这个“the”作为input word时,我们设置span=10,此时会得到10个训练样本 (“the”, …) ,如果删掉这个“the”,我们就会减少10个训练样本。实际中我们的文本中不止一个“the”,因此当“the”作为input word的时候,至少会减少10个训练样本。
上面提到的这两个影响结果实际上就帮助我们解决了高频词带来的问题。
加速训练 negative sampling
具体原理就是最大化正例概率,最小化负例出现的概率。
词汇单词的大小意味着我们的跳过神经网络具有大量的权重,所有这些都将由我们数十亿个培训样本中的每一个稍微更新!
Negative sampling通过让每个训练样本仅修改一小部分权重,而不是全部来解决这一问题。这就是它的工作原理。
When training the network on the word pair (“fox”, “quick”), recall that the “label” or “correct output” of the network is a one-hot vector. That is, for the output neuron corresponding to “quick” to output a 1, and for all of the other thousands of output neurons to output a 0.
当在单词对(“ FOX”,“快速”)上训练网络时,请回想网络的“标签”或“正确输出”是单热量向量。也就是说,对于对应于“快速”输出1的输出神经元,以及其他所有其他输出神经元输出0的输出神经元。
With negative sampling, we are instead going to randomly select just a small number of “negative” words (let’s say 5) to update the weights for. (In this context, a “negative” word is one for which we want the network to output a 0 for). We will also still update the weights for our “positive” word (which is the word “quick” in our current example).
通过否定采样,我们将仅随机选择少数“负”单词(例如5)来更新权重。(在这种情况下,“负”词是我们希望网络输出0的单词)。我们还将更新“正面”单词的权重(在当前示例中是“快速”一词)。
Essentially, the probability for selecting a word as a negative sample is related to its frequency, with more frequent words being more likely to be selected as negative samples.
本质上,选择单词作为负样本的概率与其频率有关,更频繁的单词更有可能被选为负样本。
其他
- skip-gram并没有考虑语序问题。
- 建模是fake task,真正目的是获得权重矩阵,权重矩阵的每行分别是每个单词的词向量。
- 在隐层只是用了矩阵乘法将高维onehot向量映射为一个低维稠密向量,这个向量就是中心词向量,并没有使用激活函数。
- 在输出层是将隐层输出的中心词向量和上下文词向量相乘后输入softmax分类器,最终输出的是概率分布。
- 在训练时每个词都会交替变成中心词向量和上下文词向量
Word2vec之CBOW
CBOW模型跟skip-gram的原理是一样的,只不过在输入的时候是该词周围的词向量加总作为输入。
现在有这样一句话:今天我和小明去北京玩
今天:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 记为x1
我 :[0, 1, 0, 0, 0, 0, 0, 0, 0, 0] 记为x2
和 :[0, 0, 0, 0, 0, 0, 0, 0, 1, 0] 记为x3
去 :[0, 0, 0, 0, 0, 0, 0, 1, 0, 0] 记为x4
北京:[0, 0, 0, 0, 0, 0, 1, 0, 0, 0] 记为x5
玩 :[0, 0, 0, 0, 0, 0, 1, 0, 0, 0] 记为x6
小明的向量表示为:
小明 :[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
我们的输入就是:
X = x1 + x2 + x3 + x4 + x5 + x6 = [1, 1, 0, 0, 0, 1, 1, 1, 1, 0]
这个输入是把‘小明’这个词的上下文全部作为输入,而如果我们只是要前后的一个,那就只要加总‘和’‘去’。其他的就跟skip-gram是一样的。
加速训练 Hierarchical softmax
- 首先,对于从输入层到隐藏层的映射,没有采取神经网络的线性变换加激活函数的方法,而是采用简单的对所有输入词向量求和并取平均的方法。比如输入的是三个4维词向量:(1,2,3,4),(9,6,11,8),(5,10,7,12),那么我们word2vec映射后的词向量就是(5,6,7,8)。这里是从多个词向量变成了一个词向量。
- 第二个改进就是从隐藏层到输出的softmax层这里的计算量个改进。为了避免要计算所有词的softmax概率,基于hierarchical Softmax 的采用了霍夫曼树来代替从隐藏层到输出softmax层的映射。
- word2vec在最后预测输出向量时候,大小是1*V的向量,本质上是个多分类的问题。通过hierarchical softmax的技巧,把V分类的问题变成了log(V)次二分类。
加速训练 negative sampling
【69-负采样和Hierarchical Softmax-词嵌入模型-自然语言处理-深度学习-pytorch】 https://www.bilibili.com/video/BV1d44y1N7gu?share_source=copy_web&vd_source=078ecc13a0655f48c14ea779210b8653
- 仅对K个参数进行采样
- 放弃softmax函数,采用sigmoid函数,这样就不存在先求一遍窗口中所有单词的‘“得分”的情况了。
关于Word2Vec若干问题的思考
Negative Sampling,对词频低的和词频高的单词有什么影响
通过负采样避免更新全部参数,对词频高的友好;Hierarchical Softmax的计算过程,怎么把 Huffman 放到网络中的?参数是如何更新的?对词频低的和词频高的单词有什么影响
Hierarchical Softmax利用了Huffman树依据词频建树,词频大的节点离根节点较近,词频低的节点离根节点较远,距离远参数数量就多,在训练的过程中,低频词的路径上的参数能够得到更多的训练,所以效果会更好。所以 Hierarchical Softmax 对词频低的单词效果会更好。Word2Vec有哪些参数,调参的建议
Skip-Gram 的速度比CBOW慢一点,小数据集中对低频次的效果更好;
Sub-Sampling Frequent Words可以同时提高算法的速度和精度,Sample 建议取值为 ;
Hierarchical Softmax对低词频的更友好;
Negative Sampling对高词频更友好;
向量维度一般越高越好,但也不绝对;
Window Size,Skip-Gram一般10左右,CBOW一般为5左右。Word2Vec有哪些局限性
Word2Vec只考虑到上下文信息,而忽略的全局信息;
Word2Vec只考虑了上下文的共现性,而忽略的了彼此之间的顺序性;
Documents to Vectors
doc2vec的目标是创建文档的向量化表示,而不管其长度如何。 但与单词不同的是,文档并没有单词之间的逻辑结构,因此必须找到另一种方法。
Nodes to Vectors
week6-Word Embedding相关推荐
- word2vec代码_TensorFlow2.0 代码实战专栏(四):Word2Vec (Word Embedding)
作者 | Aymeric Damien编辑 | 奇予纪出品 | 磐创AI团队 Word2Vec (Word Embedding) 使用TensorFlow 2.0实现Word2Vec算法计算单词的向 ...
- Word Embedding News|词嵌入新鲜事:六月刊:GPT-3来了
这里是 WEN(Word Embedding News)|词嵌入新鲜事. 作为起步,它将基于 Sebastian Ruder NLP News 的每月筛选,聚焦词嵌入领域.对涉及内容在本人阅读后的基础 ...
- Word Embedding List|ACL 2020 词嵌入长文汇总及分类
ACL 2020 于 5 月 17 日放榜啦,在此祝贺.羡慕每一位论文被接收的朋友.以下汇总并尝试按主题分类了 37 篇与 word embedding 有关的长文,让我们一起看看今年词嵌入的研究又有 ...
- Word Embedding News | 词嵌入新鲜事:COVID-19特刊
这里是 WEN(Word Embedding News)|词嵌入新鲜事. 作为起步,它将基于 Sebastian Ruder NLP News 的每月筛选,聚焦词嵌入领域.对涉及内容在个人阅读后的基础 ...
- 06_1.Pytorch中如何表示字符串、word embedding、One - hot、Embedding(Word2vec、BERT、Glove)【学习总结】
1.6.1.如何表示字符串 1.6.1.1.word embedding 1.6.1.1.1.文本表示(Representation) 1.6.1.1.2.独热编码 | one-hot represe ...
- 文本的表示-词嵌入(word embedding)
文本的理解 文本是常用的序列化数据类型之一.文本数据可以看作是一个字符序列或词的序列.对大多数问题,我们都将文本看作词序列. 深度学习序列模型(如RNN及其变体)能够较好的对序列化数据建模. 深度学习 ...
- 【李宏毅机器学习】Unsupervised Learning - Word Embedding 无监督学习 - 词嵌入(p22) 学习笔记
文章目录 Unsupervised Learning Word Embedding 用一个vector来表示一个word的几种方法 1-of-N Encoding Word Class Word Em ...
- 《How to Generate a Good Word Embedding?》导读(转)
http://licstar.net/archives/620 <How to Generate a Good Word Embedding?>导读 Posted on 2015 年 7 ...
- 【李宏毅2020 ML/DL】P22 Unsupervised Learning - Word Embedding
我已经有两年 ML 经历,这系列课主要用来查缺补漏,会记录一些细节的.自己不知道的东西. 已经有人记了笔记(很用心,强烈推荐):https://github.com/Sakura-gh/ML-note ...
- 关于词嵌入(Word Embedding)的一些总结
看了课程半天没搞懂词嵌入是啥,梳理一下相关知识.参考: https://www.jianshu.com/p/2fbd0dde8804 https://blog.csdn.net/m0_37565948 ...
最新文章
- golang中的socket
- 如何看待papi酱的个人平台papitube?
- java考察代码_一段简单的关于字符串的 Java 代码竟考察了这么多东西
- Index of c#
- 程序员35岁辞职后都做了什么工作三位过来人透露了实情,引热议
- Codeforces Round #186 (Div. 2) Problem D 动态规划
- Unity 两物体的碰撞 OnTriggerEnter和OnCollisionEnter
- 关闭(取消)windows 2003中ie增强的安全配置?
- LINUX---安装Hadoop集群时,把hadmin用户的shell脚本添加到开机自启动脚本
- 空间点集的三角剖分工具——四面体生成器(TetGen)和三维三角剖分包(CGAL)
- Python之marshmallow
- linux增加swap空间的方法
- Java计算10000天出生纪念日
- 为什么IT厂商争着向云计算厂商转型?
- Scanvenger游戏制作笔记(三)Unity3D创建对墙体的攻击
- 使用weixin-java-miniapp实现微信小程序登录接口
- 如何将Python脚本转换为exe,双击exe自动执行Python脚本功能
- Hadoop学习(1)--Hadoop介绍
- 区块链熊市交易量不减,市场为何需要OKEx合约交易?
- MySQL学生表、老师表、课程表和成绩表查询语句,全部亲测