【问题标题】:How to add new word vectors to gensim.models.keyedvectors and calculate most_similar如何将新词向量添加到 gensim.models.keyedvectors 并计算 most_similar
【发布时间】:2019-06-17 23:26:44
【问题描述】:

根据Gensim's page on 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

我希望输出是与输入标签最相似的向量标签列表,但输出是:

IndexError:索引 2 超出轴 0 的范围,大小为 2

【问题讨论】:

  • 格式化代码会对读者有所帮助
  • 感谢您的反馈!刚刚编辑。

标签: python gensim word2vec doc2vec


【解决方案1】:

事实上,我已经找到了解决方案。

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-normalizing self.vectors计算的。但是,如果self.vectors中有任何新添加的向量没有被预先计算成L2归一化向量,我们应该预先计算它们然后添加到self.vectors_norm

我会将此作为评论发布到您的错误报告@gojomo 并添加拉取请求!谢谢:)

【讨论】:

    【解决方案2】:

    似乎add() 操作没有清除由most_similar() 类似操作创建和重用的标准化到单位长度向量的缓存。

    在执行add() 之前或之后,您可以使用以下命令显式删除该缓存:

    del test.vectors_norm
    

    那么,您的test.most_similar('3') 应该可以在没有IndexError 的情况下工作。

    (我已经 added a bug-report for this problem 加入了 gensim 项目。)

    【讨论】:

    • 嘿,我已经添加了一个我想出的解决方案作为答案——虽然你的答案可能有效,但由于所有每次将新向量添加到键控向量后,缓存在 self.vectors_norm 中的 L2 归一化预计算向量都会被擦除。我的方法本质上是将额外的新向量预先计算为 L2 归一化的向量,然后简单地将其添加到 self.vector_norm 中,这样您就可以使用它们来获得更快的性能。
    猜你喜欢
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 2015-11-06
    • 2017-11-08
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多