A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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



2 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马