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 或更多的值是在已发表的结果中最常见。)
对于一个非常小的语料库的文档相似性的 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 或更多的值是在已发表的结果中最常见。)