我尝试在600000行句子上应用doc2vec:代码如下:
from gensim import models
model = models.Doc2Vec(alpha=.025, min_alpha=.025, min_count=1, workers = 5)
model.build_vocab(res)
token_count = sum([len(sentence) for sentence in res])
token_count
%%time
for epoch in range(100):
#print ('iteration:'+str(epoch+1))
#model.train(sentences)
model.train(res, total_examples = token_count,epochs = model.iter)
model.alpha -= 0.0001 # decrease the learning rate`
model.min_alpha = model.alpha # fix the learning rate, no decay
通过上述实现,我的结果非常糟糕。 我所做的改变与教程中建议的不同之处是更改了以下行:
model.train(sentences)
如:
token_count = sum([len(sentence) for sentence in res])
model.train(res, total_examples = token_count,epochs = model.iter)
答案 0 :(得分:13)
不幸的是,您的代码是误导性做法的荒谬混合。所以不遵循您所关注的在线示例!
按顺序从上到下解决问题:
不要使min_alpha
与alpha
相同。在看到许多不同的例子的过程中,随机梯度下降优化过程需要从较大的alpha
学习率逐渐下降,并且通常应该以可忽略的近零值结束。 (代码尝试以这种方式明确递减alpha
还存在其他问题,我们将在下面进行说明。)只有已经有工作设置的专家用户,能够很好地理解算法,并且正在进行实验调整应该更改alpha
/ min_alpha
默认值。
不要设置min_count=1
。对于Word2Vec / Doc2Vec培训,只出现一次或几次的罕见词语通常无用。它们的少数发生意味着它们自己相应的模型权重没有得到太多的训练,并且与相应的单词“真实含义”(可能反映在测试数据或后来的生产数据中)相比,少数事件更可能不具代表性。因此,模型对这些罕见单词的表示不太可能变得非常好。但总的来说,所有那些罕见的词语与做有机会变得有意义的其他词语竞争很多 - 所以“粗略”的罕见词主要是对其他词的随机干扰。或许,这些词语意味着额外的模型词汇参数,这有助于模型在训练数据上表现得更好,因为记忆那里的非泛化特性,但在未来的测试/生产数据上更糟糕。所以,min_count
是另一个默认值(5),只有在你有一个工作基线后才能更改 - 如果你以后严格地对这个参数进行元优化,那么在一个大小合适的数据集上(比如你的600K文档),你很可能会发现更高 min_count
而不是更低可以改善最终结果。
为什么要制作token_count
?以后没有需要总令牌数的地方。 total_examples
参数稍后需要计算文本示例 - 即单个文档/句子的数量 - 不总单词。通过提供(更大)字数,train()
将无法正确管理alpha
或估计记录输出的进度。
不要使用您自己的明确train()
管理层循环多次调用alpha
,除非您肯定知道自己在做什么。大多数人都弄错了。通过在此处提供默认model.iter
(其值为5)作为参数,您实际上对语料库执行了500次总传递,这不太可能是您想要的。通过在100个循环中将初始0.025 alpha
值减少0.0001,您最终alpha
为0.015 - 不到起始值的一半。相反,请使用正确的train()
和精心挑选的total_examples
值(在Doc2Vec发布的作品中使用10到20个值)调用epochs
一次。然后,它将执行完全正确的显式迭代次数,并智能地管理alpha
,并在日志记录中打印准确的进度估计。
最后,接下来的事情不一定是您的代码中的问题,因为您没有显示您的语料库res
是如何构建的,但是要注意一个常见的错误:确保您的语料库可以是迭代多次(就好像它是内存列表,或者是来自IO的东西的可重新启动的可迭代对象)。通常人们提供一次性使用的迭代器,一次通过(如在build_vocab()
中)返回其他任何东西 - 导致即时训练和无用 - 仍然随机 - 未经训练模型。 (如果您已启用日志记录,并注意每个步骤的记录输出和时间,那么这是一个问题就很明显了。)