感谢这个答案(我稍微修改了代码使其更好)。你可以使用这段代码来解决你的问题。
我们将所有小词汇放在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")
restricted_word_set = {"beer", "wine", "computer", "python", "bash", "lagers"}
restrict_w2v(w2v, restricted_word_set)
w2v.most_similar("beer")
[('lagers', 0.6570085287094116),
('wine', 0.6217695474624634),
('bash', 0.20583480596542358),
('computer', 0.06677375733852386),
('python', 0.005948573350906372)]
它可以用于删除一些单词。
虽然没有内置功能可以做到这一点,但是不需要太多的代码,可以参考现有的gensim
代码进行建模。以下是几种可能的替代策略:
.save_word2vec_format(..., binary=False)
。这种格式几乎是自说明的;编写你自己的代码从该文件中删除不在你的白名单上的所有行(确保更新入口计数的前导行声明)。load_word2vec_format()
和 save_word2vec_format()
的现有源代码可能会起到指导作用。然后你就拥有了一个子集文件。build_vocab()
步骤。现在,你拥有一个未经训练的模型,具有随机向量,但是拥有正确的词汇表。获取模型的 wv
属性 - 具有正确词汇表的 KeyedVectors
实例。然后分别加载超大的向量集,并为右尺寸的每个单词在 KeyedVectors
中,复制来自更大集合的实际向量。然后保存正确大小的子集。intersect_word2vec_format()
。它更或多或少地尝试执行上述(2)中描述的操作:使用具有所需词汇表的内存模型,在磁盘上的另一个 word2vec 格式集合中仅合并重叠单词。它要么工作,要么提供你想要做的模板。几年前,我编写了一个名为embfile的实用程序包,用于处理“嵌入文件”(但我直到2020年才发布它)。它支持各种格式:
我想要覆盖的用例是创建一个预训练的嵌入矩阵,以初始化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或其他工具为未知单词生成嵌入。
该软件包有详细的文档和测试。还有示例展示如何与Keras一起使用。
请记住,txt和bin文件本质上是顺序文件,需要完全扫描(除非您在结束之前找到所有要查找的单词)。这就是为什么我使用vvm文件,它为向量提供了随机访问。可以通过索引顺序文件来解决问题,但embfile没有此功能。尽管如此,您可以将顺序文件转换为vvm(类似于创建索引并将所有内容打包到单个文件中)。