【问题标题】:Gensim Word2Vec select minor set of word vectors from pretrained modelGensim Word2Vec 从预训练模型中选择少量词向量
【发布时间】:2018-11-27 14:38:46
【问题描述】:

我在 gensim 中有一个大型的预训练 Word2Vec 模型,我想将预训练的词向量用于我的 Keras 模型中的嵌入层。

问题在于嵌入大小很大,我不需要大部分词向量(因为我知道哪些词可以作为输入出现)。所以我想摆脱它们以减小嵌入层的大小。

有没有办法根据单词白名单保留所需的词向量(包括对应的索引!)?

【问题讨论】:

    标签: python keras word2vec gensim word-embedding


    【解决方案1】:

    没有内置功能可以做到这一点,但它不需要太多代码,并且可以以现有的gensim 代码为模型。一些可能的替代策略:

    1. 加载完整的向量,然后以易于解析的格式保存 - 例如通过.save_word2vec_format(..., binary=False)。这种格式几乎是不言自明的;编写您自己的代码以删除此文件中不在您的白名单上的所有行(确保更新 entry-count 的前导行声明)。 load_word2vec_format() & save_word2vec_format() 的现有源代码可能具有指导意义。然后,您将拥有一个子集文件。

    2. 或者,假设您要训练一个新的 Word2Vec 模型,使用您感兴趣的语料库(仅包含有趣的单词)。但是,只创建模型并执行build_vocab() 步骤。现在,您拥有未经训练的模型,带有随机向量,但词汇量恰到好处。获取模型的 wv 属性 - 具有正确词汇的 KeyedVectors 实例。然后分别加载过大的向量集,并为正确大小的KeyedVectors 中的每个单词,从更大的集合中复制实际向量。然后保存大小合适的子集。

    3. 或者,查看 Word2Vec intersect_word2vec_format() 上的 (possibly-broken-since-gensim-3.4) 方法。它或多或少地尝试执行上面(2)中描述的操作:使用具有所需词汇表的内存模型,仅合并磁盘上另一个 word2vec 格式集的重叠单词。它既可以工作,也可以为您想要做的事情提供模板。

    【讨论】:

      【解决方案2】:

      感谢this answer(我稍微更改了代码以使其更好)。您可以使用此代码来解决您的问题。

      我们在restricted_word_set 中有我们所有的次要词集(它可以是列表或集合),w2v 是我们的模型,所以这里是函数:

      import numpy as np
      
      def restrict_w2v(w2v, restricted_word_set):
          new_vectors = []
          new_vocab = {}
          new_index2entity = []
          new_vectors_norm = []
      
          for i in range(len(w2v.vocab)):
              word = w2v.index2entity[i]
              vec = w2v.vectors[i]
              vocab = w2v.vocab[word]
              vec_norm = w2v.vectors_norm[i]
              if word in restricted_word_set:
                  vocab.index = len(new_index2entity)
                  new_index2entity.append(word)
                  new_vocab[word] = vocab
                  new_vectors.append(vec)
                  new_vectors_norm.append(vec_norm)
      
          w2v.vocab = new_vocab
          w2v.vectors = np.array(new_vectors)
          w2v.index2entity = np.array(new_index2entity)
          w2v.index2word = np.array(new_index2entity)
          w2v.vectors_norm = np.array(new_vectors_norm)
      

      警告:当您第一次创建模型时,vectors_norm == None 所以 如果你在那里使用这个函数,你会得到一个错误。 vectors_norm 第一次使用后将获得numpy.ndarray 类型的值。所以 在使用该功能之前尝试类似most_similar("cat") 这样 vectors_norm 不等于 None

      它会根据Word2VecKeyedVectors重写所有与单词相关的变量。

      用法:

      w2v = KeyedVectors.load_word2vec_format("GoogleNews-vectors-negative300.bin.gz", binary=True)
      w2v.most_similar("beer")
      

      [('啤酒', 0.8409687876701355),
      ('啤酒',0.7733745574951172),
      (“啤酒”,0.71753990650177),
      ('饮料',0.668931245803833),
      ('lagers', 0.6570086479187012),
      ('Yuengling_Lager', 0.655455470085144),
      ('微酿',0.6534324884414673),
      ('Brooklyn_Lager', 0.6501551866531372),
      (“泡沫”,0.6497018337249756),
      ('brewed_beer', 0.6490240097045898)]

      restricted_word_set = {"beer", "wine", "computer", "python", "bash", "lagers"}
      restrict_w2v(w2v, restricted_word_set)
      w2v.most_similar("beer")
      

      [('lagers', 0.6570085287094116),
      ('酒', 0.6217695474624634),
      ('bash', 0.20583480596542358),
      ('电脑', 0.06677375733852386),
      ('python', 0.005948573350906372)]

      它也可以用于删除一些单词。

      【讨论】:

      • 非常有帮助,请注意 index2entity 和 index2word 的类型似乎是 list 而不是 ndarray(这会在您之后调用 w2v.add() 等其他函数时出现问题)。
      【解决方案3】:

      几年前,我编写了一个名为 embfile 的实用程序包,用于处理“嵌入文件”(但我直到 2020 年才发布它)。支持多种格式:

      • .txt(带或不带“标题行”)
      • .bin,谷歌 Word2Vec 格式
      • .vvm,我使用的一种自定义格式(它只是一个 TAR 文件,在单独的文件中包含词汇表、向量和元数据,因此可以在几分之一秒内完全读取词汇表,并且可以随机访问向量)。

      我想介绍的用例是创建一个预训练的嵌入矩阵来初始化Embedding 层。我想通过尽可能快地加载我需要的词向量来做到这一点。

      import embfile
      
      with embfile.open(EMBEDDING_FILE_PATH) as f:
      
          emb_matrix, word2index, missing_words = embfile.build_matrix(
              f, 
              words=vocab,     # this could also be a word2index dictionary as well
              start_index=1,   # leave the first row to zeros 
          )
      

      此函数还处理文件词汇表之外的单词的初始化。默认情况下,它在找到的向量上拟合正态分布,并将其用于生成新的随机向量(这就是 AllenNLP 所做的)。我不确定这个功能是否仍然相关:现在您可以使用 FastText 或其他方式为未知单词生成嵌入。

      包是extensively documented 并经过测试。还有examples that show how to use it with Keras

      请记住,txt 和 bin 文件本质上是连续文件,需要进行全面扫描(除非您在结尾之前找到所有要查找的单词)。这就是我使用 vvm 文件的原因,它为向量提供随机访问。仅仅通过索引顺序文件就可以解决这个问题,但是 embfile 没有这个功能。尽管如此,您可以将顺序文件转换为 vvm(这类似于创建索引并将所有内容打包在一个文件中)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-17
        • 2017-11-25
        • 2020-09-30
        • 1970-01-01
        • 2022-01-03
        • 1970-01-01
        • 2019-10-15
        • 1970-01-01
        相关资源
        最近更新 更多