用tensorflow提取gensim预训练词向量模型并计算相似度
本文提供如何加载已经训练好的词向量模型并在tensorflow上计算常用词的相似度。
Step1. Import 一些package
import gensim
from gensim.models import word2vec
from gensim.similarities import WmdSimilarity
import tensorflow as tf
from tensorflow.python.keras.layers import Input, Dense, Embedding
from tensorflow.keras.models import Model
import numpy as np
Step2. word2vec模型加载:关于用gensim训练词向量甚至是句向量的方法,网路上有很多,大概20分钟就搞好了
model = word2vec.Word2Vec.load('models/word2vec.model')
Step3. 把wv向量转换成numpy矩阵以便于在Tensorflow和Keras model中使用
vector_dim = 300
embedding_matrix = np.zeros((len(model.wv.vocab), vector_dim))
Step4. 构造词嵌入矩阵
for i in range(len(model.wv.vocab)):
embedding_vector = model.wv[model.wv.index2word[i]]
if embedding_vector is not None:
embedding_matrix[i] = embedding_vector
Step5. 构造Validation Set:从前100名中最常用的单词中随机取16个单词作为验证集。
valid_window =100代表要从所有单词中取样的词频排名数量=100
valid_size=16 代表验证集的单词数量=16valid_expamles 是验证集的索引集合
valid_dataset 是把它变成tensor常数格式的验证集,以便于后面使用
numpy.random.choice(a, size=None, replace=True, p=None):从一个int数字或1-D array 中随机选取,返回一个n-D array为选取结果。
a:要采样的集合1-D array或int数字
size:要返回的内容大小这里有个小问题,就是词频排名前面的几乎都是标点符号,如果可以的话筛选掉那些word长度小于1的会比较有参考价值
valid_size = 16
valid_window = 1000
valid_examples = np.random.choice(valid_window, valid_size, replace=False)
valid_dataset = tf.constant(valid_examples, dtype=tf.int32)
Step6. 用trainable=False 冻结embedding layer weights,在训练时选择不去更新这些embeddings,共享相同的嵌入层
saved_embeddings = tf.constant(embedding_matrix)
embedding = tf.Variable(initial_value=saved_embeddings, trainable=False)
Step7. 计算余弦相似度
归一化最后的valid_embeddings
就是用验证集的索引对整个归一化过后的词向量进行查找的结果,使用tf.nn.embedding_lookup()可以轻松解决这件小事。
norm = tf.sqrt(tf.reduce_sum(tf.square(embedding), 1, keep_dims=True)) # 计算张量的平方和再开根号
normalized_embeddings = embedding / norm # 归一化的验证集张量valid_embeddings
tf.nn.embedding_lookup(normalized_embeddings, valid_dataset)
Step8. 用tf.matmul计算相似度验证集中每个词跟整个单词集合中其他词的相似度
# 返回一個(validation_size, vocabulary_size)大小的张量,该张量的每一行指代一个验证词,列则指验证词和词汇表中其他词的相似度。
similarity = tf.matmul(valid_embeddings, normalized_embeddings, transpose_b=True)
Step9. 建立Tensorflow model
# Add variable initializer.
init = tf.global_variables_initializer() # 用来初始化计算图中所有global variable的operation
graph = tf.get_default_graph()
with tf.Session(graph=graph) as sess:
sess.run(init) # 初始化模型的参数
sim = similarity.eval()
# 遍历验证集中每一个单词,找到最相近的单词
for i in range(valid_size):
valid_word = model.wv.index2word[i] # 原始Word2Vec模型中的词汇表存储在model.wv.index2word
top_k = 8 # 相似词的数量
nearest = (-sim[i, :]).argsort()[1:top_k+1]
log_str = 'Nearest to %s ' % valid_word
for k in range(top_k):
close_word = model.wv.index2word[nearest[k]]
log_str = '%s %s,' % (log_str, close_word)
print(log_str) # 印出相似度
以下是我的數據結果,由於我使用的數據是公司提供,所以不能在這裡放出來,大家可以找其他公開已訓練好的詞向量模型或是自己訓一個~
相似詞來源參考:
http://adventuresinmachinelearning.com/gensim-word2vec-tutorial/
https://www.jiqizhixin.com/articles/2017-11-20-3