【问题标题】:Gensim Word2Vec model getting worse by increasing the number of epochsGensim Word2Vec 模型通过增加 epoch 数变得更糟
【发布时间】:2020-01-30 20:33:45
【问题描述】:

我正在构建一个 Word2Vec 模型,用于在包含约 35.000 个句子的数据集上进行类别推荐,总共约 500.000 个词,但只有约 3.000 个不同的词。 我基本上是这样构建模型的:

def train_w2v_model(df, epochs):
    w2v_model = Word2Vec(min_count=5,
                                 window=100,
                                 size=230,
                                 sample=0,
                                 workers=cores-1,
                                 batch_words=100)
    vocab = df['sentences'].apply(list)
    w2v_model.build_vocab(vocab)
    w2v_model.train(vocab, total_examples=w2v_model.corpus_count, total_words=w2v_model.corpus_total_words, epochs=epochs, compute_loss=True)
    return w2v_model.get_latest_training_loss()

我试图为这样的模型找到合适的时期数:

print(train_w2v_model(1))
=>> 86898.2109375
print(train_w2v_model(100))
=>> 5025273.0

我发现结果非常违反直觉。 我不明白增加 epoch 的数量会如何导致性能下降。 这似乎不是对函数 get_latest_training_loss 的误解,因为我观察到函数 most_similar 的结果更好,只有 1 个 epoch:

100 个时代:

w2v_model.wv.most_similar(['machine_learning'])
=>> [('salesforce', 0.3464601933956146),
 ('marketing_relationnel', 0.3125850558280945),
 ('batiment', 0.30903393030166626),
 ('go', 0.29414454102516174),
 ('simulation', 0.2930642068386078),
 ('data_management', 0.28968319296836853),
 ('scraping', 0.28260597586631775),
 ('virtualisation', 0.27560457587242126),
 ('dataviz', 0.26913416385650635),
 ('pandas', 0.2685554623603821)]

1 个纪元:

w2v_model.wv.most_similar(['machine_learning'])
=>> [('data_science', 0.9953729510307312),
 ('data_mining', 0.9930223822593689),
 ('big_data', 0.9894922375679016),
 ('spark', 0.9881765842437744),
 ('nlp', 0.9879133701324463),
 ('hadoop', 0.9834049344062805),
 ('deep_learning', 0.9831978678703308),
 ('r', 0.9827396273612976),
 ('data_visualisation', 0.9805369973182678),
 ('nltk', 0.9800992012023926)]

对它为什么会这样表现有任何见解吗?我会认为增加 epoch 的数量肯定会对 training loss 产生积极影响。

【问题讨论】:

    标签: python machine-learning nlp gensim word2vec


    【解决方案1】:

    首先,至少通过 gensim-3.8.1(2019 年 9 月),跑步训练损失的报告是一个半生不熟的功能。它只是所有 epoch 中所有损失的运行总和 - 因此总是增加 - 而不是每个 epoch 的损失可能会减少。有一个长期悬而未决的fix that still needs a little work,但在添加之前,报告的数字需要与早期数字进行额外比较,以检测任何时期到时期的减少。

    但还要注意:即使是每个时期的损失也不是用于外部目的的模型质量/性能的直接衡量标准。这只是一个指标,培训是否仍然有助于其内部优化任务。

    其次,如果事实上模型在外部评估中变得更糟——比如most_similar() 结果是否与人类估计相符——通过更多的训练,那么这通常表明过度拟合正在发生。也就是说,(可能过大的)模型正在记忆(可能过小的)训练数据的特征,从而以不再推广到更大的感兴趣世界的方式更好地实现其内部优化目标。

    500K 总单词对于 word2vec 训练集来说是相当小的,但如果您还打算只训练一个小词汇表(因此每个单词仍有许多不同的示例)并且使用小维度向量。

    不清楚您计算出的min_count 是什么,但请注意,通过缩小模型来增加它可以对抗过度拟合。但还要注意,任何出现次数少于该阈值的单词在训练期间都将被完全忽略,从而使您的有效训练数据量更小。

    同样,不清楚您使用的是什么embedding_size,但尝试为小词汇量制作“非常大”的向量非常容易过度拟合,因为向量有足够的“空间”来记忆训练细节。较小的向量会在模型上强制进行某种“压缩”,从而导致学习更容易泛化。 (我的非常粗略的经验法则,根本没有真正严格建立,是永远不要使用大于预期词汇量平方根的密集嵌入大小。因此,对于 10K 标记,不超过 100 维向量。)

    其他观察结果,可能与您的问题无关,但可能对您的目标感兴趣:

    • window=100 是非典型的,并且似乎远远大于您的平均文本大小(约 14 个字)——如果意图是所有标记都应该影响所有其他标记,而不考虑距离(可能是因为源数据是本质上是无序的),这是合适的,你还不如做得更大(比如 100 万)。另一方面,如果一个令牌的直接邻居比同一文本中的其他令牌更相关,那么较小的窗口将是有意义的。

    • 没有充分的理由使用batch_words=100——它只会减慢训练速度,而且如果事实上你有任何超过 100 个单词的文本,它会人为地将它们分解(从而取消从巨型window 值以上)。 (将此保留为默认值。)

    • train() 方法将只使用total_examplestotal_words,但不能同时使用两者——因此您只需指定一个

    • 看起来您可能使用的是类别推荐而不是纯自然语言,您可能还想修改 ns_exponent 参数的非默认值 - 检查文档评论和引用class docs 中有关该参数的论文以获取更多详细信息。

    【讨论】:

    • 你猜对了。我所有的代币本质上都是无序的,但是如果我没有大于 100、100 或 1000000 的代币列表是一样的吗?此外,我正在研究类别推荐。我将在我的原始帖子中添加所有必要的细节(关于词汇表中的单词数量、embedding_size 和我倾向于执行的推荐类型)。谢谢!
    • 关于window,在训练循环的深处,用于任何一个目标词的有效窗口实际上是一个最多的随机数i> 配置的号码。 (这被证明是一种计算有效的方法来增加最近的邻居的权重。)因此,接近实际文本大小的window 值将更经常使用小于全文的有效窗口,而慷慨超大的window 将只是很少这样做。因此,对于“全文窗口”的意图,慷慨的过大值效果最好。
    • 感谢您提供更多详细信息。我怀疑 230 维对于只有 3k 个单词的独特词汇来说太多了。此外,使用无序数据和大窗口,您基本上只有 35K 独特的上下文——每个完整的文本。 (使用更典型的有序自然语言和小窗口的 word2vec 设置,一个 500k 词的语料库将有近 500k 个独特的上下文,每个词出现一个。)您的most_similar() 结果可能会改善(并且表现得更符合预期关于更多时期)具有较小的size,可能在 40 到 64 范围内。
    • 关于窗口大小参数见stackoverflow.com/questions/22272370/…
    猜你喜欢
    • 1970-01-01
    • 2014-04-02
    • 2019-01-03
    • 2019-05-26
    • 1970-01-01
    • 2017-09-21
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多