2017-03-19 58 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