作爲熟悉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