原文发布在我的个人博客:Word2vec 实现小结(TensorFlow)
实现小结
- skip-gram 模型使用
tf.nn.nce_loss
;cbow 模型使用tf.nn.sampled_softmax_loss
- 两种 loss 的量级不同,
sampled_softmax_loss
要比nce_loss
小得多 - 效果在 text8 上看不出多少区别,cbow 模型要稍好一些
- 两种 loss 的量级不同,
- 使用
GradientDescentOptimizer
而不是AdadeltaOptimizer
,且学习率设大一点(比如 1.0)
AdadeltaOptimizer(1e-3)
时,“nearest top k” 测试几乎不变化,或者说训练太慢了AdadeltaOptimizer(1.0)
时,“nearest top k” 几乎都是高频词,比如 a, the, of, …GradientDescentOptimizer(1e-3)
时,“nearest top k” 的变化也很慢GradientDescentOptimizer(1.0)
是里面效果最好的,“nearest top k” 能看出确实有关
代码地址
代码参考自 tensorflow 官方教程,模型基本没变;
主要修改:
- 添加了 CBOW 模型
- 调整了代码结构,加强了可读性
- 重写了 data_helper,详细描述的 word2vec 的输入
- 用 Bunch 集中了所有参数
数据需要提前下载:test8
Nearest top k 计算方法
# ...
# 先对 embeddings 正则化
self.embeddings = tf.nn.l2_normalize(embeddings, axis=1)
# 获取需要测试的 words 的 embeddings
valid_embeddings = tf.nn.embedding_lookup(self.embeddings, config.valid_words)
self.similarity = tf.matmul(valid_embeddings, tf.transpose(self.embeddings))
# ...
# 获取 Nearest top k
sim = sess.run(model.similarity)
for i in range(config.valid_size):
valid_word = id2word[valid_data[i]]
top_k = 10
nearest = (-sim[i, :]).argsort()[1:top_k + 1]
log = 'Nearest to %s:' % valid_word
for k in range(top_k):
close_word = id2word[nearest[k]]
log = '%s %s,' % (log, close_word)
tf.logging.info(log)