因为在训练word2vec的时候采用了浅层神经网络方法,对所有的vocabulary 进行 one-hot 编码,这样输出层就是一层softmax layer。而计算softmax layer,必须要将该数据与其他的vocabulary的embedding进行重算,这样非常的耗时。(因为one-hot 的维度有可能是上百万的,计算量太大)
所以采用negative sampling 的方法解决这个问题。negative sampling 也就是近似softmax的形式解决这个问题。
例如 I love Beijing.
2gram 来遍历,正常来讲,训练数据:应该是 (I, love), (love, Beijing)
但是用了NCE来近似softmax 的结果,就是采用选择true+k个negative sample的方式来训练model。
(I, love, 1), (I, the, 0), (I, of, 0)......
(love, Beijing, 1), (love, of, 0) ......
例如计算(I, love)的binary logistic 1. (I, the) target 0。
cost function 则选择使用cross-entropy。
代码如下:
这里hidden_ vector 就是input word的embedding。
点击(此处)折叠或打开
-
real Model::negativeSampling(int32_t target, real lr) {
-
real loss = 0.0;
-
grad_.zero();
-
for (int32_t n = 0; n <= args_->neg; n++) {
-
if (n == 0) {
-
loss += binaryLogistic(target, true, lr);
-
} else {
-
loss += binaryLogistic(getNegative(target), false, lr);
-
}
-
}
-
return loss;
- }
binaryLogistic 就是cost的计算过程,如果label 是false的话, cost = (1-0)*LOG(1-score)
点击(此处)折叠或打开
-
real Model::binaryLogistic(int32_t target, bool label, real lr) {
-
real score = sigmoid(wo_->dotRow(hidden_, target));
-
real alpha = lr * (real(label) - score);
-
grad_.addRow(*wo_, target, alpha);
-
wo_->addRow(hidden_, target, alpha);
-
if (label) {
-
return -log(score);
-
} else {
-
return -log(1.0 - score);
-
}
- }