最近仔细看了一下Node2vec,这里汇总一下相关知识点。
首先Node2vec
和Deepwalk
都是NLP
中的word2vec
在图中的拓展应用,其中Node2vec
又是在Deepwalk
基础上的拓展,主要有以下两个方面的改进:
Node2vec
从Deepwalk
的无偏进阶到参数可控的有偏。Node2vec
采用Negtive Sampling
代替了Deepwalk
中的Hierarchical Sampling
word2vec
相关知识点:
SkipGram
CBOW (continuous bag of words)
Hierarchical Softmax
(如果只是想把word2vec用起来,这个知识点可以不看,因为目前已经差不多退出舞台)
Huffman Tree
Huffman Tree
,更新路径上的参数,将复杂度从kV
降低到klog(V)
,其中k
是词向量的维度,V
是词的个数Negtive Sampling
word2vec
理论相关博文:
https://blog.csdn.net/qq_38890412/article/details/107658406,这篇博文将Huffman Tree讲得很清楚。
https://zhuanlan.zhihu.com/p/56139075,这篇知乎推导了Huffman Tree中参数更新。
https://blog.csdn.net/BGoodHabit/article/details/106163130,这篇博文讲了模型训练和预测的具体细节。关于其中的label
和score
相乘部分,还没太理清楚,后续需要再看一下。
https://wmathor.com/index.php/archives/1430/,这篇博文写了word2vec
参数更新公式推导。
https://lonepatient.top/2019/01/18/Pytorch-word2vec,这篇博文的理论部分也写的比较仔细。
word2vec
实战相关博文:
https://wmathor.com/index.php/archives/1435/,pytorch实现word2vec,代码已经尝试过,可以跑出博主展示的效果。
其中一开始容易困惑的点,有两个参数矩阵,也就是两个embedding,第一个embedding是词作为中心词,第二个embedding是词作为背景词。
1,为什么用第一个参数矩阵,也就是词作为中心词的参数矩阵来作为学到的embedding
如果没有用hierarchical softmax或者negtive sampling这样的近似的话,两个矩阵都是可以的,但是用了这两种优化方法后,就不再完全计算或者更新第二个矩阵,所以使用第一个参数矩阵。
2,代码中是否可以用nn.Linear来代替nn.Embedding
可以,其实他们两个本质上做的是一样的事情,nn.Embedding是bias设置成0的nn.Linear。但是nn.Linear需要传入one-hot向量,而nn.Embedding只需要传入index。
3,向量dot相乘作为loss时需要注意的(这个是我自己在实现的过程中犯的一个错误,记录一下)
为了让正样本pair中的点向量距离相近,负样本pair的点向量距离更远,先计算内积,再用sigmoid函数,下面是伪代码:
pos_dot = dot(center_words, pos_words)
neg_dot = dot(center_words, neg_words)
pos_loss = F.logsigmoid(pos_dot)
neg_loss = F.logsigmoid(-neg_dot)
loss = - (pos_loss+neg_dot)
我自己在实现的过程里,调换了负号的顺序,写成了如下,就出现了loss为负的问题,因为logsigmoid
函数的结果一定是负的。
# 有问题
pos_dot = dot(center_words, pos_words)
neg_dot = dot(center_words, neg_words)
pos_loss = F.logsigmoid(-pos_dot)
neg_loss = F.logsigmoid(neg_dot)
loss = (pos_loss+neg_dot)