Doc2Vec infer_vector 未按预期工作
Doc2Vec infer_vector not working as expected
程序应该返回列表中最相似的第二个文本,因为它是同一个词。但这里不是这样。
import gensim
from nltk.tokenize import word_tokenize
from gensim.models import Word2Vec
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
data = ["I love machine learning. Its awesome.",
"I love coding in python",
"I love building chatbots",
"they chat amagingly well"]
tagged_data=[TaggedDocument(word_tokenize(_d.lower()),tags=[str(i)]) for i,_d in enumerate(data)]
max_epochs = 100
vec_size = 20
alpha = 0.025
model = Doc2Vec(size=vec_size,
alpha=alpha,
min_alpha=0.00025,
min_count=1,
negative=0,
dm =1)
model.build_vocab(tagged_data)
for epoch in range(max_epochs):
#print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.iter)
# decrease the learning rate
model.alpha -= 0.0002
# fix the learning rate, no decay
model.min_alpha = model.alpha
model.save("d2v.model")
loaded_model=Doc2Vec.load("d2v.model")
test_data=["I love coding in python".lower()]
v1=loaded_model.infer_vector(test_data)
similar_doc=loaded_model.docvecs.most_similar([v1])
print similar_doc
输出:
[('0', 0.17585766315460205), ('2', 0.055697083473205566), ('3', -0.02361609786748886), ('1', -0.2507985532283783)]
它显示列表中的第一个文本而不是第二个文本最相似。你能帮忙解决这个问题吗?
首先,使用玩具大小的数据集的 Doc2Vec
风格模型不会获得好的结果。仅四个文档和大约 20 个独特单词的词汇表,无法创建充满 20 维向量的有意义对比 "dense embedding" 向量模型。
其次,如果您在模型初始化中设置 negative=0
,您将禁用默认的模型训练校正模式 (negative=5
) – 而您不会启用非默认的, 不太推荐的替代方案 (hs=1
)。根本不会进行任何培训。代码输出中也可能会显示错误——而且,如果您的 运行 至少是 INFO
级别的日志记录,您可能会注意到输出中的其他问题。
第三,infer_vector()
需要一个单词标记列表作为其参数。您提供的是纯字符串。对于代码来说,这看起来像是一个单字符单词列表,所以就像您要求它推断 23 个单词的句子一样:
['i', ' ', 'l', 'o', 'v', 'e', ' ', 'c', ...]
infer_vector()
的参数应该被标记化,就像训练文本被标记化一样。 (如果您在训练期间使用了 word_tokenize()
,那么在推理期间也使用它。)
infer_vector()
还将对等于 Doc2Vec
模型中的 'epochs' 值的文本使用多次重复推理传递,除非您指定另一个值。由于您没有指定 epochs
,该模型仍将具有其默认值(继承自 Word2Vec
)epochs=5
。大多数 Doc2Vec
工作在训练期间使用 10-20 个 epoch,在推理期间至少使用同样多的 epoch 似乎是一个很好的做法。
还有:
不要尝试在循环中多次调用 train()
,或在您自己的代码中管理 alpha
,除非您是专家。
任何在线示例建议的代码块都像您...
for epoch in range(max_epochs):
#print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.iter)
# decrease the learning rate
model.alpha -= 0.0002
# fix the learning rate, no decay
model.min_alpha = model.alpha
...是一个不好的例子。它错误地上下发送有效 alpha
速率,如果您想更改 epochs
的数量,它会非常脆弱,它实际上会结束 运行 500 个纪元(100 * model.iter),它的代码比必要的多得多。
相反,不要更改默认 alpha
选项,并在创建模型时指定所需的迭代次数。因此,该模型将缓存一个有意义的 epochs
值,以供稍后 infer_vector()
.
使用
然后,只调用一次 train()。它将正确处理所有时期和 alpha 管理。例如:
model = Doc2Vec(size=vec_size,
min_count=1, # not good idea w/ real corpuses but OK
dm=1, # not necessary to specify since it's the default but OK
epochs=max_epochs)
model.build_vocab(tagged_data)
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.epochs)
程序应该返回列表中最相似的第二个文本,因为它是同一个词。但这里不是这样。
import gensim
from nltk.tokenize import word_tokenize
from gensim.models import Word2Vec
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
data = ["I love machine learning. Its awesome.",
"I love coding in python",
"I love building chatbots",
"they chat amagingly well"]
tagged_data=[TaggedDocument(word_tokenize(_d.lower()),tags=[str(i)]) for i,_d in enumerate(data)]
max_epochs = 100
vec_size = 20
alpha = 0.025
model = Doc2Vec(size=vec_size,
alpha=alpha,
min_alpha=0.00025,
min_count=1,
negative=0,
dm =1)
model.build_vocab(tagged_data)
for epoch in range(max_epochs):
#print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.iter)
# decrease the learning rate
model.alpha -= 0.0002
# fix the learning rate, no decay
model.min_alpha = model.alpha
model.save("d2v.model")
loaded_model=Doc2Vec.load("d2v.model")
test_data=["I love coding in python".lower()]
v1=loaded_model.infer_vector(test_data)
similar_doc=loaded_model.docvecs.most_similar([v1])
print similar_doc
输出:
[('0', 0.17585766315460205), ('2', 0.055697083473205566), ('3', -0.02361609786748886), ('1', -0.2507985532283783)]
它显示列表中的第一个文本而不是第二个文本最相似。你能帮忙解决这个问题吗?
首先,使用玩具大小的数据集的 Doc2Vec
风格模型不会获得好的结果。仅四个文档和大约 20 个独特单词的词汇表,无法创建充满 20 维向量的有意义对比 "dense embedding" 向量模型。
其次,如果您在模型初始化中设置 negative=0
,您将禁用默认的模型训练校正模式 (negative=5
) – 而您不会启用非默认的, 不太推荐的替代方案 (hs=1
)。根本不会进行任何培训。代码输出中也可能会显示错误——而且,如果您的 运行 至少是 INFO
级别的日志记录,您可能会注意到输出中的其他问题。
第三,infer_vector()
需要一个单词标记列表作为其参数。您提供的是纯字符串。对于代码来说,这看起来像是一个单字符单词列表,所以就像您要求它推断 23 个单词的句子一样:
['i', ' ', 'l', 'o', 'v', 'e', ' ', 'c', ...]
infer_vector()
的参数应该被标记化,就像训练文本被标记化一样。 (如果您在训练期间使用了 word_tokenize()
,那么在推理期间也使用它。)
infer_vector()
还将对等于 Doc2Vec
模型中的 'epochs' 值的文本使用多次重复推理传递,除非您指定另一个值。由于您没有指定 epochs
,该模型仍将具有其默认值(继承自 Word2Vec
)epochs=5
。大多数 Doc2Vec
工作在训练期间使用 10-20 个 epoch,在推理期间至少使用同样多的 epoch 似乎是一个很好的做法。
还有:
不要尝试在循环中多次调用 train()
,或在您自己的代码中管理 alpha
,除非您是专家。
任何在线示例建议的代码块都像您...
for epoch in range(max_epochs):
#print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.iter)
# decrease the learning rate
model.alpha -= 0.0002
# fix the learning rate, no decay
model.min_alpha = model.alpha
...是一个不好的例子。它错误地上下发送有效 alpha
速率,如果您想更改 epochs
的数量,它会非常脆弱,它实际上会结束 运行 500 个纪元(100 * model.iter),它的代码比必要的多得多。
相反,不要更改默认 alpha
选项,并在创建模型时指定所需的迭代次数。因此,该模型将缓存一个有意义的 epochs
值,以供稍后 infer_vector()
.
然后,只调用一次 train()。它将正确处理所有时期和 alpha 管理。例如:
model = Doc2Vec(size=vec_size,
min_count=1, # not good idea w/ real corpuses but OK
dm=1, # not necessary to specify since it's the default but OK
epochs=max_epochs)
model.build_vocab(tagged_data)
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.epochs)