我已经在此处以二进制文件(GoogleNews-vectors-negative300.bin.gz)的形式下载了Google的预训练词嵌入。我希望能够根据一些词汇过滤嵌入。
我首先尝试将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
步骤中将其过滤掉吗?
答案 0 :(得分:0)
您的dict
将不具有KeyedVectors
对象的所有功能,并且不会紧凑地存储。 KeyedVectors将所有向量存储在一个大的连续本机2D数组中,字典指示每个单词的向量的行。您的第二个字典,每个单词带有单独的向量,将涉及更多的开销。 (此外,由于您从embeddings[k]
返回的向量将成为整个向量的“视图” –因此,即使您尝试丢弃KeyedVectors
,您的子集实际上也可能间接保留更大的数组。 )
由于您可能只想要原始向量的一个子集的原因可能是原始集合太大,因此dict
占用了更多或更多的内存可能并不理想。
您应该考虑两个选择:
load_word2vec_format()
包括一个可选的limit
参数,该参数仅加载提供的文件中的前N个字。由于此类文件通常是从频率最高的单词到频率最低的单词进行排序的,频率较低的单词都远没有那么有用,而且矢量质量较低,因此通常只使用前100万或500,000或100,000等等条目,以节省大量内存并节省速度。
您可以尝试在加载时进行过滤。您需要调整加载代码来执行此操作。幸运的是,您可以在本地gensim安装中查看load_word2vec_format()
的完整源代码(仅数十行),也可以在以下项目源代码托管处在线查看完整的源代码:
您将编写自己的例程版本,从而跳过不感兴趣的单词。 (它可能必须对文件进行两次遍历,一次遍历感兴趣的单词,然后第二遍实际分配合适大小的内存数组并进行实际读取。)