Doc2Vec相似度小语料测试

Doc2Vec similarity small corpus test

对于一个非常小的语料库的文档相似性的 doc2vec 简单测试,我无法得到任何合理的响应。同一份文件,或使用一些独特的词,从不 returns 本身或任何接近的东西。

有像 this one 这样的代码,作者可以在其中检查:

greater than 95% of the inferred documents are found to be most similar to itself and about 5% of the time it is mistakenly most similar to another document.

以下代码基于 mishra.thedeepak

中的示例
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from nltk.tokenize import word_tokenize
from gensim.models.doc2vec import Doc2Vec

data = ["I love machine learning Its awesome",
        "I love coding in python",
        "I love building chatbots",
        "they chat amagingly well"]

tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(data)]

max_epochs = 100
vec_size = 20
alpha = 0.025

model = Doc2Vec(vector_size=vec_size,
                alpha=alpha, 
                min_alpha=0.00025,
                min_count=1,
                dm=1)

model.build_vocab(tagged_data)

for epoch in range(max_epochs):
    model.train(tagged_data, total_examples=model.corpus_count, epochs=model.iter)
    model.alpha -= 0.0002
    model.min_alpha = model.alpha

# Now testing the same doc, trying to find similarity to itself:

test_data = word_tokenize("I love coding in python".lower())
v1 = model.infer_vector(test_data)
similar_doc = model.docvecs.most_similar([v1], topn=len(model.docvecs))

# The high score
print("similar_doc", similar_doc)
print(data[int(similar_doc[0][0])])

相同的文档,但它 returns:

similar_doc [('3', 0.44355273246765137), ('2', 0.4423074722290039), ('0', 0.4166065454483032), ('1', 0.3881992995738983)]
they chat amagingly well

尝试了很多变体,例如短语 "building chatbots" 甚至 "python" 这个词 returns

similar_doc [('0', -0.09640596807003021), ('3', -0.16155308485031128), ('1', -0.1653675138950348), ('2', -0.1833440363407135)]
I love machine learning. Its awesome.

无论我尝试多少次,文档的正确匹配都是如此罕见,似乎与随机的机会相同。

有什么方法可以在像这样的简单语料库上为 doc2vec 获得更好的结果?

您不会从来自 Doc2Vec 和类似算法的小型玩具数据集中获得有趣的结果,这些算法依赖于大型、细微变化的训练数据集来创建 'dense' 和有意义的结果向量。

特别是,您无法从只有 4 个对比示例的训练集中获得有意义的 20 维向量!您需要比维度更多的对比示例,以便模型逐渐学习文本的 'compressed' 表示——其中相似的文本被迫 'near' 在向量 space。 (如果你有比例子更多的维度,根本没有 'pressure' 来强制相似的文本共享邻域——它们都可以得到截然不同的向量,但是模型仍然有很多内部状态可以用来 'memorize' 每个文本的模式,具有 none 有意义的 generalization/learning,这在尝试将大量文本建模为较小的维度时发生。)

关于您的使用的其他注意事项:

  • 不要在自己的循环中多次调用 train(),或者尝试自己减少有效的 alpha:你可能会做错(因为你有这里)。只需保留默认的 alpha/min_alpha,在初始化模型时指定一个 epochs 值,并且只调用一次 train():它将执行正确数量的 epochs &妥善管理alpha

  • min_count=1 通常是个坏主意:很少有用法示例的稀有词通常比有用的含义指示更容易产生干扰,因此默认 min_count=5(或者甚至更高更大的语料库)通常效果更好。

  • 如果您在 class 初始化中指定 epochs,如上建议,那么您指定的值也将用于 infer_vector()。如果不这样做,则只会使用默认值 epochs=5,这通常太小(尤其是在推断最初使用更多 epochs 训练的模型时)。(10-20 或更多的值是在已发表的结果中最常见。)