2017-03-19 56 views
2

作为熟悉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]]) 

仍然没有相关性。

那么,我误解或做错了什么?

+0

作为一个完整性检查,计算几个众所周知的单词对之间的距离,例如,'猫狗'和'星期一 - 星期二'。如果你没有小写你的输入,也可以试试'Monday-Tuesday'。尝试绘制预测的和黄金标准的相似性:'plt.scatter(acts,press)' – mbatchkarov

+0

是的,我做了这个,结果看起来很理智。至少它们与word2vec_basic本身在训练时报告的一致(它使用余弦相似性显示16个选定单词中最接近的单词,每10000个时期)。不过,请参阅下面的答案。 – TheLifemakers

回答

1

回答我自己的问题:是的,结果令人沮丧,但那是因为模型太小而且训练数据太少。就如此容易。 The implementation I experimented with使用一个17M字的语料库,运行100K步,只需要两个相邻的上下文单词,嵌入大小为128.我得到一个更大的维基百科样本,包含124M个字,增加了24个字的上下文(每边12个),嵌入大小为256,并且训练了180万步,瞧!相关性(以我上面的问题衡量)增长到0.24。

然后,我执行in this tutorial所述频繁词的子采样,并将相关性进一步跳至0.33。最后,我把我的笔记本电脑留下了一个晚上,用36个字的上下文和320万步进行训练,一直到0.42!我想我们可以称之为成功。因此,对于像我一样玩这款游戏的玩家来说,这是一款需要大量数据,耐心和NVidia硬件的游戏(目前我还没有)。但是,它很有趣。

+0

我在玩同样的事情,你能分享你的代码吗? – Caner