使用预训练的word2vec词向量

以谷歌开源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[i] 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[i] = word_vecs[word]
        word_idx_map[word] = i
        i += 1
    return W, word_idx_map
 
5,在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


  • 8
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值