本文主要包含word2vec 源码分析,word2vec源码,word2vec源码解析,word2vec python 源码,word2vec源码下载等服务器相关知识,网友希望可以进行参考
word2vec.c源码分析,word2vec.c源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#define MAX_STRING 100
#define EXP_TABLE_SIZE 1000
#define MAX_EXP 6
#define MAX_SENTENCE_LENGTH 1000
#define MAX_CODE_LENGTH 40
const int vocab_hash_size = 30000000; // Maximum 30 * 0.7 = 21M words in the vocabulary
typedef float real;
struct vocab_word {
long long cn; // 词频,来自于vocab file或者从训练模型中来计算
int *point; // 霍夫曼树中从根节点到该词的路径,存放路径上每个非叶结点的索引
char *word, *code, codelen; //word:string 字面值 code:Huffman编码 codelen:huffman编码的长度
};
char train_file[MAX_STRING], output_file[MAX_STRING];
char save_vocab_file[MAX_STRING], read_vocab_file[MAX_STRING];
//输入文件中每个基本词的结构体数组
struct vocab_word *vocab;
int binary = 0, cbow = 1, debug_mode = 2;
int window = 5, min_count = 5;//在由语料库构建词典(vocab数组)时,剔除词频小于min_count的词。
//构建词典后仍需要判断是否需要对低频次进行清理,
//如果词典的大小N>0.7*vocab_hash_size,则从词典中删除所有词频小于min_reduce的词。
int num_threads = 12, min_reduce = 1;
//该数组存文件中基本词的字面的hash码,和基本词在vocab_word数组中的位置
//其中基本词的字面的hash码作为该数组的下标
int *vocab_hash;
//vocab_size 不同单词的个数,也就是词典的大小
//layer1_size 词向量的长度
//file_size训练文件的大小
long long vocab_max_size = 1000, vocab_size = 0, layer1_size = 100;
long long train_words = 0, word_count_actual = 0, iter = 5, file_size = 0, classes = 0;
real alpha = 0.025, starting_alpha, sample = 1e-3;
//syn0 - 存储词典中每个词的词向量
//syn1 - 存储Huffman树各个内节点对应的向量
//syn1neg -负采样时,存储每个词对应的辅助向量
//expTable: sigmoid函数表,提前计算好,提高效率
real *syn0, *syn1, *syn1neg, *expTable;
clock_t start;
int hs = 0, negative = 5;
const int table_size = 1e8;
int *table;
//每个单词的能量分布表,table在负采样中用到
void InitUnigramTable() {
int a, i;
double train_words_pow = 0;
double d1, power = 0.75;
table = (int *)malloc(table_size * sizeof(int));//分配空间
//遍历词汇表,统计词的能量总值train_words_pow
for (a = 0; a < vocab_size; a++)
train_words_pow += pow(vocab[a].cn, power);
i = 0;
//表示已遍历词的能量值占总能量的比
d1 = pow(vocab[i].cn, power) / train_words_pow;
//a - table表的索引
//i - 词汇表的索引
for (a = 0; a < table_size; a++) {
table[a] = i;//单词i占用table的a位置
//table反映的是一个单词能量的分布,一个单词能量越大,所占用的table的位置越多
if (a / (double)table_size > d1) {
i++; //移到下个词
d1 += pow(vocab[i].cn, power) / train_words_pow;
}
// put everthing else in the end of the unigram table???
if (i >= vocab_size) i = vocab_size - 1;
}
}
// Reads a single word from a file, assuming space(' ') + tab(\t) + EOL(\n) to be word boundaries
//从fin中读一个词到字符串word
void ReadWord(char *word, FILE *fin) {
int a = 0, ch;//a - 用于向word中插入字符的索引;ch - 从fin中读取的每个字符
while (!feof(fin)) {
ch = fgetc(fin);
if (ch == 13) continue;//回车,开始新的一行,重新开始while循环读取下一个字符
//当遇到space(' ') + tab(\t) + EOL(\n)时,认为word结束
if ((ch == ' ') || (ch == '\t') || (ch == '\n')) {
if (a > 0) {//跳出while循环,这里的特例是‘\n’,我们需要将回退给fin,词汇表中'\n'用</s>来表示。
if (ch == '\n') ungetc(ch, fin);
break;
}
if (ch == '\n') {//

