公司动态
word2Vec初步理解(上)
一、Efficient Estimation of Word Representations in Vector Space论文中提到了skip-gram 和 CBOW这里重点理解skip-gram1.1原始Skip-gramimporttorchimporttorch.nnasnnclassSkipGram(nn.Module):def__init__(self,vocab_size,embed_dim):super().__init__()# Projection layerself.embeddingnn.Embedding(vocab_size,embed_dim)# Output layerself.outputnn.Linear(embed_dim,vocab_size)defforward(self,center_word):hself.embedding(center_word)logitsself.output(h)returnlogits训练skip-gramI love deep learning windows 2即中心词前一个词和后一个词center[love, love, deep, deep]target [I , deep, love, learning]训练代码modelSkipGram(vocab_size,300)criterionnn.CrossEntropyLoss()optimizertorch.optim.Adam(model.parameters(),lr1e-3)forcenter,targetinloader:logitsmodel(center)losscriterion(logits,target)optimizer.zero_grad()loss.backward()optimizer.step()logits model(center) 中的logits 是 词汇表中每个词出现的概率target 是 词汇表中第几个词如果窗口变成5 例如 0:I 1:love 2:deep 3:learning 4:and 5:neural 6:networks 7:very 8:much以 neural 为中心词windows 5 可以生成10个样本(neural , I) (neural , love ) (neural , deep ) (neural , learning) (neural , and )(neural , networks ) (neural , very ) (neural , much)如果是 CBOW模式只能生成1个样本[w0 w1 w2 w3 w4,w6 w7 w8 w9 w10],w5在word2Vec 中windows5指的是左右各5个根据上面的例子可以看到CBOW的基本思想是根据上下文预测中心词所以训练样本是中心词的左右各5个词目标是中心词Skip-Gram 是根据中心词预测周围词所以输入样本是这样的[中性词左边第3个]、[中性词左边第2个]、[中性词左边第1个]、[中性词右边第1个]、[中性词右边第2个]、[中性词右边第3个]二、 Distributed Representations of Words and Phrasesand their Compositionality观察上面的网络模型发现例如词向量的维度300如果词汇表是10w那么网络每次都输出10w x 300然后softmax(10w个词计算量很大从我们的认知来说其实每次预测根本就不用将词汇表里面的词汇都预测一遍词与之间是有联系的真正需要更新的其实只是一个正样本词和少量负样本词。2.1 Negative Sampling正常情况下skip-gram 中的 I love deep learning中心词love 上下文 I deep训练对input - target love - I love - deep预测这两个需要在整个词表中做softmax在 Negative Sampling 思想中正样本 (love, I)负样本love, apple(love, banana) (love, car) (love, tiger)(love, phone)变成了二分类是不是上下文词原来的损失函数−logP(wo∣wI)-logP(w_o|w_I)−logP(wo∣wI)变成了logσ(−vOTvI)∑i1klogσ(−vNiTvI)log\sigma(-v_O^Tv_I)\sum_{i1}^klog\sigma(-v_{N_i}^Tv_I)logσ(−vOTvI)i1∑klogσ(−vNiTvI)其中正样本1个负样本k个通常k5SkipGramNSimporttorchimporttorch.nnasnnimporttorch.nn.functionalasFclassSkipGramNS(nn.Module):def__init__(self,vocab_size,embed_dim):super().__init__()# syn0self.in_embednn.Embedding(vocab_size,embed_dim)# syn1negself.out_embednn.Embedding(vocab_size,embed_dim)defforward(self,center_words,pos_words,neg_words): center_words : [B] pos_words : [B] neg_words : [B,K] centerself.in_embed(center_words)posself.out_embed(pos_words)# 正样本pos_scoretorch.sum(center*pos,dim1)pos_lossF.logsigmoid(pos_score)# 负样本negself.out_embed(neg_words)neg_scoretorch.bmm(neg,center.unsqueeze(2)).squeeze(2)neg_lossF.logsigmoid(-neg_score).sum(1)loss-(pos_lossneg_loss)returnloss.mean()2.2、SkipGramNS我的理解之前的SkipGram的输入是中心词以及中心词的一个窗口内的上下文词SkipGramNS需要再输入k5该中心词的随机采样词例如一下center lovepositive Inegative [apple, car, banana, phone, tiger]有两个词向量nn.Embedding中心词独享一个正样本和负样本共享一个nn.Embedding正样本分数是正样本词向量和中心词向量的向量内积负样本分数是负样本词向量和中心词向量的向量内积模型需要拉进正样本和中心词之间的距离拉大负样本和中心词的距离因此模型的loss为loss−logσ(spos)−∑(logσ(−sneg))loss -log\sigma(s_{pos})-\sum(log\sigma(-s_{neg}))loss−logσ(spos)−∑(logσ(−sneg))从而推动正样本内积越来越大、负样本内积越来越小使中心词靠近真实上下文词远离随机采样词。2.3、SkipGramNS我的思考2.3.1 、为什么中心词一个nn.Embedding正样本和负样本一个为什么不能三个输入共享一个理论上正样本、负样本和中心词使用一个nn.Embedding也可以这里作者之所以使用两个是认为中心词和正负样本在整个优化过程中扮演不同的角色如果两种角色是相互矛盾的那么放到一起学习学到的向量必然是不好的分开学习可以让两种角色的特征都学的很好如果两种角色是相互依赖相互促进的那么三个共享一个nn.Embedding效果最好。有时候用几层卷积几个分支很多时候是根据设计者对当前任务的理解。2.3.2、原始的SkipGram的优化目标是为什么可以由预测词汇表中所有词的概率求最大的那个如此丝滑的将优化目标变为正样本与中心词相似度-负样本与中心词相似度呢这里有很多思考可以看初版的skip-gram 最后一层的思想所有词汇表中我的目标词汇的概率最大其实就是分类的思想但是这里词汇表类别是如此之大导致计算效率特别低1、导致计算量大的是词汇表的个数为什么会用到词汇表的个数呢因为最后一层使用softmax让目标词汇的概率最大从而逼迫网络学习的词汇向量逼近目标词汇远离非目标词汇2、经分析softmax的目的其实是学习词向量并不是真的去预测是哪个词汇那么是不是可以跳过softmax的方法于是NS顺势提取就是不绕弯子了之间在向量层上计算损失就是输入正样本的向量与中心向量距离近负样本向量与中心向量距离远3、对这个思想和人脸中的Triplet Loss三元组损失是一致的通过Triplet Loss训练后的人脸图片可以生成人脸特征向量用来做比对。2.3.3 word2vec 和 lstm 、transformer的区别1、skip-gram的目标函数是P(wo∣wc)P(w_o|w_c)P(wo∣wc)例如I love deep learning窗口2训练样本(love → I)(love → deep), (love → learning)所以skip-gram只关系哪些词经常一起出现但是它不关心语法顺序和长距离依赖本质上skip-gram学的是词共现统计而不是语言生成结构如下中心词id ↓ Embedding ↓ 词向量 vc ↓ 与目标词向量点积 ↓ sigmoid ↓ loss2、LSTM是语言模型P(wt∣w1,...,wt−1)P(w_t|w_1,...,w_{t-1})P(wt∣w1,...,wt−1)例如 I love deep ? 预测learning在lstm 中embedding 只是输入特征核心是隐藏层ttt_ttt携带的上下文信息结构如下Embedding ↓ LSTM ↓ Hidden State ↓ Linear ↓ Softmax ↓ 整个词表3、Transformer也是语言模型P(wt∣w1,...,wt−1)P(w_t|w_1,...,w_{t-1})P(wt∣w1,...,wt−1)但是上下文建模换成了self-Attention:HAttention(Q,K,V)H Attention(Q,K,V)HAttention(Q,K,V)所以transformer学到的特征更强2.3.4 lstm 、transformer都有自己的nn.Embedding, word2vec的作用是什么1、 在word2vec出现之前词用的ID来表示例如cat - 1001dog - 2003, apple - 501模型不知道cat 和 dog比较接近cat 和 apple 不接近2、 word2vec出来后cat , dog, apple 使用向量表示之后这些向量可以表示语义所以很多模型直接拿word2vec的结果来用例如后面之间接LSTM经常会看到embeddingnn.Embedding.from_pretrained(word2vec_weight)3、后来BERT 和 GPT 出现后发现模型完全可以自己学Embedding不需要先训练word2vec再训练模型直接端到端训练。现在大模型训练流程文本 ↓ Tokenizer ↓ 随机初始化Embedding ↓ Transformer ↓ 预测下一个Token4、之前说过word2vec提取的是静态词之前的关系后面会看到BERT Embedding GPT Embedding 等不是独立模型它们是Transformer训练过程中产生的表示。