词向量源码解析:(2.3)word2vec源码解析之word2vec

这篇文章分析word2vec.c的源代码。word2vec.c和word2pharse一样都要过两遍语料,第一遍建立字典,这部分的代码两个文件完全是一样的。word2vec.c第二遍过语料就在训练词向量了。

word2vec实际上是包含了四种模型,根据对上下文的不同的定义方式,可以分为cbow和sg,根据对上下文和中心单词不同的建模方式,分为负采样和哈夫曼树。所以一组合就有四种模型。负采样英文缩写是ns(negative sampling)。目前最普遍的模型是sg和ns的组合。即sgns。这篇文中我就以sgns模型为例过一遍word2vec.c的代码。

word2vec.c中的单词用结构体vocab_word表示

struct vocab_word {
  long long cn;
  int *point;
  char *word, *code, codelen;
};

由于word2vec中用到了哈夫曼树的数据结果,所以多存了一个point,一个code和一个codelen。由于我们这里只讲sgns,所以也不会涉及这些变量。

先分析几个函数的源码。

首先是InitUnigramTable函数,这个函数是做negative sampling用的。语料给出了单词的概率分布,下面的代码就是模拟这样一个分布。比如the的频数高,被抽到概率就大。当然这里对分布进行了一个改动,power=0.75。所有单词的频数的0.75次方构成分布,这样能抑制高频词被采样的几率。

void InitUnigramTable() {
  int a, i;
  double train_words_pow = 0;
  double d1, power = 0.75;
  table = (int *)malloc(table_size * sizeof(int));//从table中采样,table_size是一个很大的数
  for (a = 0; a < vocab_size; a++) train_words_pow += pow(vocab[a].cn, power);//所有单词的频数(的power次方)之和,分母
  i = 0;
  d1 = pow(vocab[i].cn, power) / train_words_pow;//按照单词分布往table中填单词id
  for (a = 0; a < table_size; a++) {
    table[a] = i;
    if (a / (double)table_size > d1) {
      i++;
      d1 += pow(vocab[i].cn, power) / train_words_pow;
    }
    if (i >= vocab_size) i = vocab_size - 1;
  }
}

InitNet函数用来初始化word2vec中所有的参数,word2vec中的参数有两部分,分别是词向量和上下文向量。他们的参数个数都是|V|*d。其中|V|是字典中单词的个数,d是词向量的维度,比如是300。由于有两种建模方式:哈夫曼(hs)还是负采样(ns),所以有可以有两份上下文向量。我们这里就考虑ns,所以只有一份儿上下文向量

void InitNet() {
  long long a, b;
  unsigned long long next_random = 1;
  a = posix_memalign((void **)&syn0, 128, (long long)vocab_size * layer1_size * sizeof(real));//初始化词向量
  if (syn0 == NULL) {printf("Memory allocation failed\n"); exit(1);}
  if (hs) {
    a = posix_memalign((void **)&syn1, 128, (long long)vocab_size * layer1_size * sizeof(real));
    if (syn1 == NULL) {printf("Memory allocation failed\n"); exit(1);}
    for (a = 0; a < vocab_size; a++) for (b = 0; b < layer1_size; b++)
     syn1[a * layer1_size + b] = 0;
  }
  if (negative>0) { //初始化上下文向量,用0初始化
    a = posix_memalign((void **

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值