作为熟悉Tensorflow的一种方法,我试图验证在对照人类相似性分数检查时,由word2vec_basic.py
生成的单词嵌入(请参阅tutorial)有意义。然而,结果令人惊讶地令人失望。这就是我所做的。word2vec_basic输出:试图测试单词相似性与人类相似性分数
在word2vec_basic.py
,我在最后添加另一个步骤来保存的嵌入和反向字典到磁盘(所以我不必每次都重新生成):
with open("embeddings", 'wb') as f:
np.save(f, final_embeddings)
with open("reverse_dictionary", 'wb') as f:
pickle.dump(reverse_dictionary, f, pickle.HIGHEST_PROTOCOL)
在我自己的word2vec_test的.py,我加载它们并创建一个直接字典查找:
with open("embeddings", 'rb') as f:
embeddings = np.load(f)
with open("reverse_dictionary", 'rb') as f:
reverse_dictionary = pickle.load(f)
dictionary = dict(zip(reverse_dictionary.values(), reverse_dictionary.keys()))
我然后定义相似性的嵌入矢量之间的欧氏距离:
def distance(w1, w2):
try:
return np.linalg.norm(embeddings[dictionary[w1]] - embeddings[dictionary[w2]])
except:
return None # no such word in our dictionary
到目前为止,结果是有意义的,例如distance('before', 'after')
小于distance('before', 'into')
。
然后,我从http://alfonseca.org/pubs/ws353simrel.tar.gz(我从“模型动物园”借用了Swivel项目中的链接和代码)下载了人类得分。我比较了相似的人的得分和嵌入距离如下:
with open("wordsim353_sim_rel/wordsim_relatedness_goldstandard.txt", 'r') as lines:
for line in lines:
w1, w2, act = line.strip().split('\t')
pred = distance(w1, w2)
if pred is None:
continue
acts.append(float(act))
preds.append(-pred)
我用因为人的得分与增加的相似度增加,所以距离排序需要被倒相匹配(更小的距离意味着较大的相似性)。
然后我计算相关系数:
rho, _ = scipy.stats.spearmanr(acts, preds)
print(str(rho))
但事实证明非常小,就像0.006。我重新训练word2vec_basic与上下文和矢量长度为256的4个字,但它并没有改善。然后我用余弦相似度代替欧氏距离:
def distance(w1, w2):
return scipy.spatial.distance.cosine(embeddings[dictionary[w1]], embeddings[dictionary[w2]])
仍然没有相关性。
那么,我误解或做错了什么?
作为一个完整性检查,计算几个众所周知的单词对之间的距离,例如,'猫狗'和'星期一 - 星期二'。如果你没有小写你的输入,也可以试试'Monday-Tuesday'。尝试绘制预测的和黄金标准的相似性:'plt.scatter(acts,press)' – mbatchkarov
是的,我做了这个,结果看起来很理智。至少它们与word2vec_basic本身在训练时报告的一致(它使用余弦相似性显示16个选定单词中最接近的单词,每10000个时期)。不过,请参阅下面的答案。 – TheLifemakers