https://blog.csdn.net/lics999/article/details/78696023
以谷歌开源google news(bin)为例。下载地址:https://code.google.com/p/word2vec 更多模型下载地址:https://github.com/xgli/word2vec-api
之前被这个问题困扰了挺长时间,一直找不到有效的方法,可能是我太菜…… 在网上找资料也只找到了一种把bin转换成txt 文件的方式,但是效率出奇的低,无法想象,本地一运行程序就死机,服务器上也得等很长时间。多亏了有一颗优化模型的心…… 山重水复疑无路,柳暗花明又一村啊。 在一篇paper里面,作者用theano直接对二进制bin文件进行了处理。速度上有天壤之别,一种是拖拉机,一种是火箭,遂把它进行改动用到了自己的模型里。 一、先介绍直接对txt进行处理的方法,该方法缺点,速度太慢,而且两篇博文里都是从placeholder里传入词向量数据,对于这种方式,我持保留意见。原因: 1,如果从placeholder里传入数据,那在实际应用中,每一个batch都要传入全部的词向量,这对于稍复杂的模型来说显然很吃力,额外增加了很多计算量。 2,在模型训练过程中可以控制词向量可训练与不可训练,从palceholdler传入,降低了灵活性。 3,bin文件转换成txt格式,文件大小变为原来的两倍,还需要解码,又增加了读取时间。 对于该方法不在赘述,将两篇博文地址粘贴到下面: http://blog.csdn.net/lxg0807/article/details/72518962(中文)[作者最后提到的unk情况,其实可有可无,看你在对数据进行预处理的时候是否考虑了这种情况,如果已经考虑到了unk则在此处不需要] https://ireneli.eu/2017/01/17/tensorflow-07-word-embeddings-2-loading-pre-trained-vectors/(英文) 二、直接对bin文件进行处理
1,这种方式跟上面的方式有很大不同,首先是在分离word的时候,是采用从每一行的开始挨个单词读到第一个空格处为止,便是一个单词,每一行都重复这种动作,直到整个文件读完。
for line in xrange(vocab_size):
word = []
while True:
ch = f.read(1)
#print ch
if ch == ' ':
word = ''.join(word)
#print 'single word:',word
break
if ch != '\n':
word.append(ch)
#print word
2,第二步是从大的词向量表中,来找到与单词相对应的词向量
if word in vocab:
word_vecs[word] = np.fromstring(f.read(binary_len), dtype='float32')
pury_word_vec.append(word_vecs[word])
if i==0:
print 'word',word
i=1
else:
f.read(binary_len)
3,对于词表中没有的单词进行处理,这里采用的是uniform随机初始化
def add_unknown_words(word_vecs, vocab, min_df=1, k=300):
"""
For words that occur in at least min_df documents, create a separate word vector.
0.25 is chosen so the unknown vectors have (approximately) same variance as pre-trained ones
"""
for word in vocab:
if word not in word_vecs and vocab[word] >= min_df:
word_vecs[word] = np.random.uniform(-0.25,0.25,k)
4,在应用之前,也就是传入embedding lookup之前,需要取出对应词表,并进行一定预处理。
def get_W(word_vecs, k=300): """ Get word matrix. W is the vector for word indexed by i """vocab_size = len(word_vecs) word_idx_map = dict() W = np.zeros(shape=(vocab_size+1, k), dtype='float32') W[0] = np.zeros(k, dtype='float32') i = 1 for word in word_vecs: W = word_vecs[word] word_idx_map[word] = i i += 1 return W, word_idx_map5,在main函数中调用的过程:
if __name__=="__main__":
w2v_file = "GoogleNews-vectors-negative300.bin"#Google news word2vec bin文件
print "loading data...",
vocab = Wordlist('vocab.txt')#自己的数据集要用到的词表
w2v,pury_word2vec = load_bin_vec(w2v_file, vocab.voc)
add_unknown_words(w2v, vocab.voc)
W, word_idx_map = get_W(w2v)
'''embedding lookup简单应用'''
Wa = tf.Variable(W)
embedding_input = tf.nn.embedding_lookup(Wa, [0,1,2])#正常使用时要替换成相应的doc
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
input = sess.run(Wa)
#print np.shape(Wa)
此处仅做了使用的简单示例,如果应用到自己的项目中去,还需要优化一下结构。以适应自己项目的需要。
刚开始写博客不久,发现在表达的时候会说不清楚,有不明白的地方,欢迎留言讨论。
补充:关于txt格式的文件,也找到了速度很快的处理方式,glove和word2vec只要是一样的格式,代码可以通用,可以移步这里:http://lichangsong.win/?post=22
文中相关代码,已经上传到github,欢迎大家相互交流,共同进步。 Github: https://github.com/pkulics/use-pretrained-word2vec
|