【记录】Skipgram和CBow实现

  • numpy、tensorflow手写SkipGram(没有negative sampling)和cbow:

http://www.claudiobellei.com/2018/01/07/backprop-word2vec-python/

这两种实现都需要动手算梯度,手动实现梯度下降,且不没有使用negative sampling。

  • Pytorch版实现

不用Negative Sampling的话,理解了SkipGram的原理,用Pytorch来实现SkipGram非常简单。

输入的X就是中心词的one-hot-encoding(1*V维),X再与一个V*N的矩阵【在Pytorch里就是nn.Linear(V,N),或者nn.Embedding(V,N)】相乘,再与一个N*V的矩阵相乘,就得到一个1*V的预测输出y_hat,再把y_hat经过softmax,得到一个1*V的概率分布,再与x的任意一个上下文词y(也是one-hot-encoding形式)做CrossEntropyLoss,CrossEntropyLoss就是需要最小化的目标函数。再backward。如此将所有的中心词-上下文词pair都输入到Network中训练即可。代码见:https://www.cnblogs.com/aaronhoo/p/13205827.html

我试了一下,这种原始的、不用Nagative Sampling的方法简单,当词表小的时候,效果还可以,中心词和上下文词的词向量比较接近。但缺点是训练非常慢,主要是因为计算CrossEntropy时用到了Softmax,因此必须采用Nagative Sampling方法来加速。

  • NegativeSampling

NegativeSampling的思路与原始的SkipGram完全不同,NegativeSampling是将X、Y结成的pair做分类,而不是用X预测Y。如果X-Y对是中心词-上下文,则NegativeSampling输出1,否则输出0。loss function也是类似CrossEntropyLoss(用nn.functional.binary_cross_entropy_with_logits函数来计算),与上面类似,只不过这里是二分类,而不是V分类,因此用sigmoid函数来计算概率。具体做法是X,Y各自的one-hot-encoding分别与一个V*N的矩阵相乘(在Pytorch也就是各自代入nn.Embedding后,再做dot-product,dot-product的意义就是算两者之间的相似度),结果再输入sigmoid函数。如此重复可获得一个batch的XY对的sigmoid函数值,再与该batch的labels做二分类的cross-entropy就是作为目标函数。

注意,NegativeSampling的目标函数与逻辑回归不同:逻辑回归的目标函数是最大似然的负数,也就是所有样本的概率相乘再取负数。

  • Nagative Sampling的实现:推荐PyTorch版《动手学深度学习》Dive into DL-Pytorch.pdf 当中的实现。

你可能感兴趣的:(NLP自然语言处理,深度学习,机器学习,python,算法,人工智能)