根据Gensim关于WordEmbeddingKeyedVectors的页面,你可以逐步添加新的键值对新的词向量。但是,在使用预先训练的向量及其标签初始化 WordEmbeddingKeyedVectors 并向其添加新的看不见的模型推断词向量后,most_similar
方法无法再使用。
from gensim.models.keyedvectors import WordEmbeddingsKeyedVectors
test = WordEmbeddingsKeyedVectors(vector_size=3)
test.add(entities=["1", "2"], weights=[np.random.randint(5, size=3),
np.random.randint(5, size=3)])
test.most_similar("2") #THIS WORKS
test.add(entities=['3'], weights=[np.random.randint(5, size=3)])
test.most_similar("3") #THIS FAILS
我希望输出是与输入标签最相似的矢量标签列表,但输出是:
索引错误:索引 2 超出大小为 2 的轴 0 的界限
事实上,我已经找到了解决方案。
在gensim.models.keyedvectors
文件中,在 class WordEmbeddingKeyedVectors
下,我们可以从
def init_sims(self, replace=False):
"""Precompute L2-normalized vectors."""
if getattr(self, 'vectors_norm', None) is None or replace:
logger.info("precomputing L2-norms of word weight vectors")
self.vectors_norm = _l2_norm(self.vectors, replace=replace)
自
def init_sims(self, replace=False):
"""Precompute L2-normalized vectors."""
if getattr(self, 'vectors_norm', None) is None or replace:
logger.info("precomputing L2-norms of word weight vectors")
self.vectors_norm = _l2_norm(self.vectors, replace=replace)
elif (len(self.vectors_norm) == len(self.vectors)): #if all of the added vectors are pre-computed into L2-normalized vectors
pass
else: #when there are vectors added but have not been pre-computed into L2-normalized vectors yet
logger.info("adding L2-norm vectors for new documents")
diff = len(self.vectors) - len(self.vectors_norm)
self.vectors_norm = vstack((self.vectors_norm, _l2_norm(self.vectors[-diff:])))
本质上原始函数所做的是如果没有self.vectors_norm
,则通过L2归一化self.vectors
来计算。但是,如果self.vectors
中有任何新添加的向量尚未预先计算为 L2 归一化向量,我们应该预先计算它们,然后添加到self.vectors_norm
中。
我会将此作为评论发布到您的错误报告@gojomo并添加拉取请求!谢谢:)
add()
操作似乎没有清除由类似most_similar()
操作创建和重用的规范化到单位长度向量的缓存。
在执行add()
之前或之后,您可以使用以下命令显式删除该缓存:
del test.vectors_norm
然后,您的test.most_similar('3')
应该在没有IndexError
的情况下工作。
(我已经在gensim项目中添加了此问题的错误报告。