You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

word2vec的ReduceVocab()函数是否存在bug或逻辑遗漏?

word2vec ReduceVocab函数词频裁剪逻辑问题解答

以下是从谷歌官方word2vec.c截取的相关源码片段:

// Reduces the vocabulary by removing infrequent tokens
void ReduceVocab() {
    int a, b = 0;
    unsigned int hash;
    for (a = 0; a < vocab_size; a++) if (vocab[a].cn > min_reduce) {
            vocab[b].cn = vocab[a].cn;
            vocab[b].word = vocab[a].word;
            b++;
        } else free(vocab[a].word);
    vocab_size = b;
    
    for (a = 0; a < vocab_hash_size; a++) vocab_hash[a] = -1;
    for (a = 0; a < vocab_size; a++) {
        // Hash will be re-computed, as it is not actual
        hash = GetWordHash(vocab[a].word);
        while (vocab_hash[hash] != -1) hash = (hash + 1) % vocab_hash_size;
        vocab_hash[hash] = a;
    }
    fflush(stdout);
    min_reduce++;
}

ReduceVocab()函数会在LearnVocabFromTrainFile函数中被调用,针对你提出的场景疑问,解答如下:

结论:你的分析完全正确

你观察到的词频计数丢失问题真实存在,没有遗漏代码中的相关逻辑:

  • ReduceVocab执行裁剪时,词频低于当前min_reduce阈值的词会被直接free释放内存,历史出现次数会被彻底丢弃,没有任何留存计数的逻辑
  • 函数每次执行末尾都会执行min_reduce++,下一次触发裁剪时的判定阈值会比当前高1
  • 被删除的词如果在后续语料读取过程中再次出现,会被识别为未登录词,重新加入词表时词频从0开始重新累计,不会和之前被删除时的历史计数合并
  • 你举的"hello"例子完全符合代码实际运行逻辑:第一次裁剪时累计出现4次,达不到初始阈值5被删除;后续新增出现5次时,重新入表的计数仅为5,而第二次裁剪的阈值已经涨到6,因此会再次被删除,哪怕真实累计出现次数已经达到9次,确实会被误删。

该缺陷几乎不会造成实际影响

这个逻辑是原作者做的工程权衡,并非代码疏漏:

  • ReduceVocab的触发时机是词表大小超过预设上限时,核心目的是控制训练过程中的内存占用,本身就不是为了实现100%精确的词频统计
  • 这类被反复删除又反复加入的词,本身在语料中的分布非常稀疏,绝大多数最终总词频也达不到训练时设置的min_count(默认值为5),本来就是要被过滤的无效词
  • 就算真的存在少量总词频达标的词被误删,占整体语料的比例极低,对最终词向量训练效果的影响可以忽略不计,因此官方原版代码一直没有修复这个逻辑。

内容的提问来源于stack exchange,提问作者prof_FL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.21 16:16:02