前几天一个同学在看一段代码,内容是使用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))