首页 > 解决方案 > 从 word2vec 过滤词嵌入

问题描述

我在这里下载了谷歌的预训练词嵌入作为二进制文件 (GoogleNews-vectors-negative300.bin.gz)。我希望能够根据一些词汇过滤嵌入。

我首先尝试将 bin 文件加载为 KeyedVector 对象,然后创建一个字典,将其词汇表与另一个词汇表一起用作过滤器。然而,这需要很长时间。

  # X is the vocabulary we are interested in 
  embeddings = KeyedVectors.load_word2vec_format('GoogleNews-vectors- 
  negative300.bin.gz', binary=True) 

  embeddings_filtered = dict((k, embeddings[k]) for k in X if k in list(embeddings.wv.vocab.keys()))

运行需要很长时间。我不确定这是否是最有效的解决方案。我应该先在 load_word2vec_format 步骤中过滤掉它吗?

标签: pythongensim

解决方案


dict不会拥有KeyedVectors对象的所有功能,也不会紧凑地存储。KeyedVectors 将所有向量存储在一个大的连续原生 2D 数组中,其中 dict 指示每个单词向量的行。您的第二个字典,每个单词都有一个单独的向量,将涉及更多开销。(此外,由于您从中返回的向量embeddings[k]将是完整向量的“视图”——因此您的子集实际上可能会间接保留较大的数组,即使您尝试丢弃KeyedVectors.)

由于您可能只想要原始向量的一个子集的一个原因可能是原始集合太大,dict因此占用尽可能多或更多内存的 a 可能并不理想。

您应该考虑两种选择:

  • load_word2vec_format()包括一个可选limit参数,该参数仅从提供的文件加载前 N 个单词。由于此类文件通常从最频繁到最不频繁的单词进行排序,而不太常用的单词的用处和向量质​​量都低得多,因此通常只使用前 100 万、500,000 或 100,000 个等条目以节省大量内存和速度。

  • 您可以尝试在负载上进行过滤。您需要调整加载代码来执行此操作。load_word2vec_format()幸运的是,您可以在本地 gensim 安装中查看完整的源代码(只有几十行),或者在项目源代码托管处在线查看:

https://github.com/RaRe-Technologies/gensim/blob/9c5215afe3bc4edba7dde565b6f2db982bba5113/gensim/models/utils_any2vec.py#L123

你会编写你自己的这个例程版本,跳过不感兴趣的单词。(它可能需要对文件进行两次传递,一次计算感兴趣的单词,然后第二次实际分配正确大小的内存数组并进行真正的读取。)


推荐阅读