那些牛了逼的embedding预训练 ----- word2vec 篇

此篇献给一直视自己为垃圾的喵主,喵呜?(It's a sad story)。

 

前言

阿正在某一天丢给我了几个预训练模型,有现在比较热门的,也有已经老得不行的然而还没有深入的,对就是那个word2vec。反正这一堆模型都没有细致接触过,主要的用途就是训练词向量,然后把这些词向量作为下一个任务的输入。趁着最近要需要预训练这个步骤做个任务,顺势把这些模型撸一遍吧。哎,kkkk,主要是学妹也在撸,喵主不得不拿鞭子抽自己啊,当然也没有这么可怕。毕竟还没有找到工作,ps:争取28岁之前撸完这几个模型。

其他模型链接:

glove: https://blog.youkuaiyun.com/mashutian/article/details/89815928

XXXX

XXXX

 

如有问题,特别是带*的部分,请大声告诉我,以及欢迎讨论?


word2vec

我的妈,说到word2vec,简直是好像过去四五年都在不停悔恨怎么还没有学会,怎么还没有动手撸代码,每天都因为这件事情让我活在悔恨中。现在随便一搜,简直了一堆讲解,解析。多的一批雕凿。一上来都是先说one-hot是啥,有啥缺点,为此我们要distributed representation。反正就是来个语料,跑了一下,每个词得到了对应的向量。这也是预训练想要做的事情了。distributed representation大概就是希望去model一件事情:a word is characterized by the company it keeps。其核心:一、选择一种方式描述上下文;二、选择一种模型刻画某个词(下文称“目标词”)与其上下文之间的关系。基于神经网络的分布式表示是其中的一类模型。

1. 相关文章,基本上就是下面几篇是必备原文吧。

  • Mikolov T, Chen K, Corrado G, et al. Efficient estimation of word representations in vector space[J]. arXiv preprint arXiv:1301.3781, 2013.
  • Mikolov T, Sutskever I, Chen K, et al. Distributed representations of words and phrases and their compositionality[C]//Advances in neural information processing systems. 2013: 3111-3119.
  • Le Q, Mikolov T. Distributed representations of sentences and documents[C]//International conference on machine learning. 2014: 1188-1196.

先看第一篇文章 Efficient estimation of word representations in vector space,介绍了基本原理啊什么的。这篇文章里说到两个工作NNLM和RNNLM,Mik他们的continuous bag-of-words(CBOW)模型就是来源于这个NNLM,所以这里简单提一下:

  • Bengio Y, Ducharme R, Vincent P, et al. A neural probabilistic language model[J]. Journal of machine learning research, 2003, 3(Feb): 1137-1155.

这个2003年的work,讲了下embedding初衷:ngram大法让我们在训练数据中算出一些一个词出现的时候另一个词出现的概率值,然后我们就能把这样的概率值用在生成模型里了。不过,ngram的信息不能就只拿来识别周围词是啥吧?离ngram的n更远的词语怎么办,不要了吗?猫猫和狗狗这样的在好多一样句式出现感觉有些相似的词语怎么办?然后文章就po了一个nutshell。


大概意思是,我们想把每个词映射到词特征空间呀,然后有了这些词的向量表示以后我们再去express我们的符合语言模型的词序列概率值,最后我们希望把词表示和概率都学出来咯,然后他们就po了神经网络结构

*我的理解:首先,我们有个大的mapping,就是词和词对应的embedding表C;然后来了一个函数g,可以干件了不起的大事情,就是把词Wt之前的词序列转换成,对于下一个词是Wt的其他词语的条件概率分布。而上图中,大概意思就是输入是词Wt的前后词,输出的时候第i个向量值是Wt-1这些都出现了以后,后面这个出现的词的概率。发现了吗,Bengio的工作实际上是在学习语言模型的时候,得到了词向量,就是这个embedding表C成为最后的亮点。

然后Mikolov这些人觉得Bengio的工作计算复杂度较高,每个词都有前N个词来encode,然后每个词的dimension是D的话进来就要N*D,然后再去过个隐藏层,就变成了N*D*H,那可是好麻烦了。于是乎他们就提出:我们不要隐藏层,我们还整些trick,比如hierarchical softmax,反正他们提出了两种思路CBOW和Skip-gram,是的,就是这两个牛逼的不行的模型。

  • Mikolov T, Chen K, Corrado G, et al. Efficient estimation of word representations in vector space[J]. arXiv preprint arXiv:1301.3781, 2013.

*文章理解:

CBOW:前四个和后四个上下词预测当前词,所有的词被average了,所以词序并不会有影响。(怎么average的呢?)

Skip-gram:当前词预测上下词,比如当前词和上下词距离最大是5的话,针对训练语料,我们随机取前几个和后几个词作为当前词的label(几个小于五个),然后就要做几个*2次分类才行哦,计算成本比CBOW高。

再然后的这一篇,他们想说刚刚那篇实验做下来发现这个skip-gram大法好啊,那我们再修正改进下呗。这一篇提到了好些trick:hierarchical softmax,替代hierarchical softmax的negative sampling还有subsampling。怎么想sampling这个也要写一篇,还有GibbsSampling呢,妈蛋。

  • Mikolov T, Sutskever I, Chen K, et al. Distributed representations of words and phrases and their compositionality[C]//Advances in neural information processing systems. 2013: 3111-3119.

好嘛,然后这一篇重新拎了一下skip-gram模型,我们的目标是,给了这一串词序列,我们希望最大化他的log概率哦,跟前面说的一样就是语言模型啦,人们就是这么讲话的“我爱你”,那就让“我”,“爱”,“你”在一起的概率大点呗!愿世界和平!

是的,公式的计算成本太高了,为啥呢?每个词有个脱了衣服的表示,还有个不停在换装以期望拿到创造101冠军的表示。每个词show up的时候希望身边站的都是跟他最好的小伙伴。要求多的一批。于是乎,参加比赛的词语太多了,而且每个词语还有两个表示vector。那我们要trick才行,不然就玩不下去了。这里先用大白话讲讲这些trick,回头再仔细撸一遍吧。

Hierarchical Softmax:用二叉树来表示output layer ?,对,就是类似这种呕吐物的形状,我才不会画个树?出来。叶子结点就是我们的词,每个结点都表示了他对于自己的孩子结点的概率,大概就是如果给左边的孩子70%的like,右边的孩子就剩下30%了。然后和上面softmax时每个词有两个表示不同的是,这里叶子结点就是词的一种表示,inner node是一种表示。大概就是inner node承载了一系列的语义的感觉吧。另外这个树吧会让我们的计算速度更快,因为父母总是偏爱更喜欢的孩子啊,生两个孩子的要注意啊。

Negtive Sampling:来自于Noise Contrastive Estimation (NCE),大概意思是好的模型可以区分数据中的噪音诶,用logistic regression。然而跟NCE有区别的地方是NCE需要sample和噪音分布的概率,negative sampling只要sample就行啦。光看文章,我只能说就是对于每个sample我们给他配k个负sample。怎么选,现在还不知道!!!

Subsampling of frequent words:这个好理解,经常出现的词反而提供不来什么信息,因此我们要解决rare和frequent词语的这种不均衡。

再后来,从词的表示扩展成了句子和段落。啦啦啦,就是下面这篇文章了。

  • Le Q, Mikolov T. Distributed representations of sentences and documents[C]//International conference on machine learning. 2014: 1188-1196.

**第一个模型Distributed Memory version of Paragraph Vector(PV-DM)利用paragraph的向量来进行下一个词语的预测任务,不同的是给了巨多的上下文,但是在同一段落里的上下文,然后词向量这边是用了拼接来得到的段落向量(咋拼接的呢?)。之前在word2vec里面是有个大的mapping,就是词和词对应的embedding表C,这边除了词mapping,还有个大的 matrix,是段落token到其表示的mapping。然后每三个词向量拼成的向量就是用来预测第四个词的向量了。paragraph vector就represents the missing information from the current context and can act as a memory of the topic of the paragraph. 主要的步骤如图:

*另一个模型Distributed Bag of Words version of Paragraph Vector(PV-DBOW),大概意思是我们希望利用paragraph vector作为输入,训练后使得分类器能够预测出paragraph中我们随机sample出来的词语,而不是下一个词语是什么。最后作者的实验中,他们把PV-DM和PV-DBOW学出来的两种paragraph vector结合(concatenation)以后作为最终的paragraph vector。看到这里我突然臆想到他们当时发现单个vector效果不好,但是拼起来以后效果惊人的那种喜悦之情。

大家另外还可以去看下这篇:word2vec explained Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method,最后的最后作者自问自答:

2. 接下来是别人的讲解分析,来自网络贴,谢谢各位了,真的讲的很好,如果讲的是对的的话。

CBOW:

  1. 输入层:上下文单词的onehot. {假设单词向量空间dim为V,上下文单词个数为C}
  2. 所有onehot分别乘以共享的输入权重矩阵W. {VN矩阵,N为自己设定的数,初始化权重矩阵W}
  3. 所得的向量 {因为是onehot所以为向量} 相加求平均作为隐层向量, size为1N.
  4. 乘以输出权重矩阵W' {NV}
  5. 得到向量 {1V} 激活函数处理得到V-dim概率分布 {PS: 因为是onehot嘛,其中的每一维斗代表着一个单词}
  6. 概率最大的index所指示的单词为预测出的中间词(target word)与true label的onehot做比较,误差越小越好(根据误差更新权重矩阵)

Skip-gram:

  1. 首先选句子中间的一个词作为我们的输入词,例如我们选取“dog”作为input word;
  2. 有了input word以后,我们再定义一个叫做skip_window的参数,它代表着我们从当前input word的一侧(左边或右边)选取词的数量。如果我们设置skip_window=2,那么我们最终获得窗口中的词(包括input word在内)就是['The', 'dog','barked', 'at']。skip_window=2代表着选取左input word左侧2个词和右侧2个词进入我们的窗口,所以整个窗口大小span=2x2=4。另一个参数叫num_skips,它代表着我们从整个窗口中选取多少个不同的词作为我们的output word,当skip_window=2,num_skips=2时,我们将会得到两组 (input word, output word) 形式的训练数据,即 ('dog', 'barked'),('dog', 'the')。
  3. 神经网络基于这些训练数据将会输出一个概率分布,这个概率代表着我们的词典中的每个词是output word的可能性。假如我们先拿一组数据 ('dog', 'barked') 来训练神经网络,那么模型通过学习这个训练样本,会告诉我们词汇表中每个单词是“barked”的概率大小。
  4. 模型的输出概率代表着到我们词典中每个词有多大可能性跟input word同时出现。

所以,需要定义loss function(一般为交叉熵代价函数),采用梯度下降算法更新W和W'。训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量(word embedding),这个矩阵(所有单词的word embedding)也叫做look up table(其实聪明的你已经看出来了,其实这个look up table就是矩阵W自身),也就是说,任何一个单词的onehot乘以这个矩阵都将得到自己的词向量。有了look up table就可以免去训练过程直接查表得到单词的词向量了。

再不懂的话直接去看这个crystalajj在知乎上的回答,看照片是个漂亮技术女生,我的妈真是羡慕的不行:https://www.zhihu.com/question/44832436/answer/266068967
另外,作者机器学习算法工程师在简书上总结了下,Word embedding的训练方法大致可以分为两类: 无监督或弱监督的预训练;端对端(end to end)的有监督训练,详情咨询:https://www.jianshu.com/p/cede3ae146bb

 无监督或弱监督的预训练端对端(end to end)的有监督训练
优点不需要大量的人工标记样本就可以得到质量还不错的embedding向量学习到的embedding向量也往往更加准确
缺点准确率有待提高(得到预训练的embedding向量后,用少量人工标注的样本再去优化整个模型)模型在结构上往往更加复杂
应用word2vec和auto-encoder
(这里解释一下AutoEncoder,AutoEncoder也可以用于训练词向量,先将one hot映射成一个hidden state,再映射回原来的维度,令输入等于输出,取中间的hidden vector作为词向量,在不损耗原表达能力的前提下压缩向量维度,得到一个压缩的向量表达形式。)

通过一个embedding层和若干个卷积层连接而成的深度神经网络以实现对句子的情感分类,可以学习到语义更丰富的词向量表达。

其他链接在这里?

三成功力还给了链接的:

https://www.jianshu.com/p/471d9bfbd72f

https://blog.youkuaiyun.com/itplus/article/details/37969979
3. 一些代码(最烦看源代码了,么么的,都是c写的,mikolov的:https://github.com/tmikolov/word2vec

源码部分:我先弱弱的看了下,我真的弱,喵的,感觉大致就是有这么几块内容,大致顺序:构建词汇文件(指定词库和从数据中构建词库),构建霍夫曼树,net初始化(输入层和输出层权重syn1,syn1neg),构建负采样概率表和sigmoid函数表,CBOW和SKIP训练,词向量存和聚类,多线程处理。构建词汇文件的时候对低频词处理了,还根据词频排序了。

我还得再仔细看看,代码解读的链接:

https://blog.youkuaiyun.com/jeryjeryjery/article/details/80245924

https://www.cnblogs.com/yangykaifa/p/7373419.html

https://blog.youkuaiyun.com/jingquanliang/article/details/82886645

tensorflow训练词向量:http://www.voidcn.com/code/p-exdfofao-m.html

开源工具:gensim来一波(https://radimrehurek.com/gensim/models/word2vec.html

from gensim.models import Word2Vec

sentences = []
with open('/Volumes/SaveMe/data/test_embeddings/text.txt', 'r') as f:
    for line in f:
        sentences.append(line.strip().split(' '))

model = Word2Vec(sentences, size=100, window=5, min_count=1, workers=4)
model.save("/Volumes/SaveMe/data/test_embeddings/text.model")
# binary is false and save in C text format, if true save in bin format
model.wv.save_word2vec_format("/Volumes/SaveMe/data/test_embeddings/text.c", binary=False)

# load part
# from gensim.test.utils import datapath
# from gensim.models import KeyedVectors
# wv_from_text = KeyedVectors.load_word2vec_format(datapath('text.c'), binary=False)  # C text format
# wv_from_bin = KeyedVectors.load_word2vec_format(datapath("text.bin"), binary=True)  # C bin format

github: https://github.com/3Top/word2vec-api/blob/master/word2vec-api.py

其他讲解材料:

链接: https://pan.baidu.com/s/1XNT0xbXSptrt_8iFqBlVBg 提取码: dgsi

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值