前幾天一個同學在看一段代碼,內容是使用gensim包提供的Word2Vec方法訓練得到詞向量,里面有幾個變量code、count、index、point
看不懂,就向我求助,我大概給他講了下code是哈夫曼編碼,count應該是這個詞在訓練語料中出現的計數,point應該是在建樹的過程中 路徑的節點等等,這個算法我13、14年的時候就看過,所以他的問題沒把我難住。可是自己現在的工作內容和以前喜歡的NLP相關不大,為了給他講解一下算法同時也練一下手,就打算用TensorFlow實現一個簡化版的w2v,代碼在這里,實現的也算比較清晰。里面需要用到計算詞向量的相似度,我的方法得到的結果卻是一個大於1的實數,問題也不知道出現在哪里。誰能幫我指點一下,不勝感激=。=
首先我們先定義embedding矩陣
embedding = tf.Variable(
tf.random_uniform([vocab_size,embedding_size],-1.0,1.0),name='embedding')
接下來就是一些計算詞向量的方法 ,假設已經有了詞向量矩陣,那么我們如故計算向量之間的余弦相似度呢?
我們需要現對詞向量矩陣進行歸一化,假設有一個向量\(a=(x_1,x_2,x_3)\),求模
的公式就為\(\sqrt{x_1^2+x_2^2+x_3^2} \quad\),對應的代碼如下
norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keepdims=True))
需要注意的是reduce_sum
方法里面的參數,keepdims
的含義為retains reduced dimensions with length 1,即保持減少的那一個維度(axis)的值為1
x = tf.constant([[1, 1, 1], [1, 1, 1]])
tf.reduce_sum(x) # 6
tf.reduce_sum(x, 0) # [2, 2, 2]
tf.reduce_sum(x, 1) # [3, 3]
tf.reduce_sum(x, 1, keepdims=True) # [[3], [3]]
tf.reduce_sum(x, [0, 1]) # 6
再接下來就是求\(cos\theta\)
normalized_embeddings = embedding / norm
#對驗證集中的數據進行歸一化
valid_embeddings = tf.nn.embedding_lookup(
normalized_embeddings, valid_x)
#計算相似性
similarity = tf.matmul(valid_embeddings, tf.transpose(normalized_embeddings))