天天看点

word2vec源码阅读笔记

word2vec源码阅读笔记,结合代码加深对word2vec的理解

1. sigmoid函数的近似计算

expTable

2. 构建词汇库
  • 词汇表训练过程 -> LearnVocabFromTrainFile()
    • ReadWordIndex()
      • 读取一个单词 -> ReadWord()
      • 计算单词对应hash值 -> GetWordHash()
      • 通过hash值得到单词在词汇表中的索引 -> SearchVocab() (开放地址法)
    • 将单词加入词汇表 -> AddWordToVocab()
    • 对词汇表根据词频进行降序排序 -> SortVocab(),若词汇量大于了一定值,则会先进行裁剪(先才裁掉频率低的词,再裁剪掉频率高的词 -> ReduceVocab())
    • 保存训练好的词汇表 -> SaveVocab()
    • 如果已经存在训练好的词汇表,则直接读取 -> ReadVocab()
3. 初始化网络

网络参数包括:

  • syn0:词向量,一维数组,大小为vocab_size * layer1_size(词汇量*词向量维度)
  • syn1:huffman树中的非叶子节点向量,一维数组,大小同上
  • syn1neg:负采样优化需要的变量,一维数组,大小同上
  1. 初始化网络参数 -> InitNet()
  2. 构建哈夫曼树 -> CreateBinaryTree()
  3. 初始化负采样概率表 -> InitUnigramTable() (高频的词被选中成负样本的概率大)
4. 模型训练

TrainModelThread()

为了对文本加速训练,采用了多线程的训练方式,如下图所示:

word2vec源码阅读笔记

在每一个线程内执行的是对模型和词向量的训练。

关键变量有:

  • last_word: 当前正在训练的词索引
  • sentence_length: 当前训练的句子长度
  • sentence_position: 当前中心词在句子中的位置
  • sen: 数组,句子中每个词在词汇表中的索引
  • neu1: cbow模式下投影层对应的context(w),为上下文中所有词向量的平均值
  • neu1e: skip模式下,投影层向量就是输入层向量的复制,neu1e用来记录上下文词对输入层的梯度

每次读取一条句子,记录好句子中每个词在词汇表中对应的索引(如果启用下采样,则会随机跳过一些词,随机丢弃频繁的单词,同时保持顺序不变)

  1. CBOW模型——Hierarchical Softmax模式
word2vec源码阅读笔记

输入层->映射层:将context(w)中每个词向量求和

代码中变量与公式的对应关系:

  • syn0:

    $v(·)$

  • syn1:

    $\theta_{j-1}^\omega$

  • neu1:

    $X_\omega$

  • neu1e:

    $e$

  1. CBOW模型——Negative模式

负采样过程中,只有一个正样本(中心词),其他都是负样本。将所有概率加起来,使其最大化。

代码中变量与公式的对应关系:

  • syn0:

    $v(·)$

  • syn1neg:

    $\theta^u$

  • neu1:

    $X_\omega$

  • neu1e:

    $e$

  1. Skip-Gram模型——Hierarchical Softmax模式
word2vec源码阅读笔记

skip模型和cbow模型优化类似,主要是输入层->映射层之间不同:

  • CBOW中是上下文词向量平均求和
  • SKIP中是直接复制中心词向量。

    skip模型中,优化过程是逐个计算中心词和上下文词之间的概率,使其最大化,所以和cbow中的优化计算基本类似

  1. Skip-Gram模型——Negative模式
5. 结果处理

TrainModel()

  • 直接保存结果
  • k-means聚类算法分析结果

参考:

https://blog.csdn.net/jeryjeryjery/article/details/80245924 https://blog.csdn.net/google19890102/article/details/51887344 https://github.com/deborausujono/word2vecpy

继续阅读