gensim中word2vec python源码理解(一)初始化构建单词表
gensim中word2vec python源码理解(二)Skip-gram模型训练
本文主要谈一谈对gensim包中封装的word2vec python源码中,使用Hierarchical Softmax构建单词表部分代码的理解。
由于之前阅读的论文是对使用Hierarchical Softmax的Skip-gram模型进行拓展,因此在阅读代码的时候重点阅读了Hierarchical Softmax构建单词表的方法,以及Skip-gram模型的训练方法。对于negative sampling方法和CBOW模型的实现方法,则会继续对代码进行研究。
init
初始化一个model(实际上是Word2Vec类的实例化对象):
model = Word2Vec(sentences, size=100, window=5, min_count=5, workers=4)
进入类的初始化方法__init__
,对里面的属性值进行初始化。
在传入的训练句子不为空的情况下,主要调用两个方法:
self.build_vocab(sentences, trim_rule=trim_rule)
self.train(
sentences, total_examples=self.corpus_count, epochs=self.iter,
start_alpha=self.alpha, end_alpha=self.min_alpha
)
build_vocab
该方法是从句子序列中构建单词表,其中每个句子都是字符串组成的列表。依次调用了三个方法:scan_vocab
,scale_vocab
,finalize_vocab
下面依次介绍三个方法的功能:
scan_vocab
:对句子中的单词进行初始化
代码内容阅读(有省略):
sentence_no = -1 #保存扫描完成的句子数量
total_words = 0 #保存出现的单词总数(不去重)
min_reduce = 1
vocab = defaultdict(int) #将单词表初始化为一个字典
checked_string_types = 0
#扫描每个句子
for sentence_no, sentence in enumerate(sentences): #取出语料中每个句子和其在语料库中的编号no
for word in sentence:
vocab[word] += 1 #记录每个词出现的次数
total_words += len(sentence) #记录扫描过的句子里的单词总数
if self.max_vocab_size and len(vocab) > self.max_vocab_size: #如果对于最大单词数有限制且当前超出限制
#将语料库中小于min_reduce(初始值为1)的单词都删除
utils.prune_vocab(vocab, min_reduce, trim_rule=trim_rule)
min_reduce += 1 #不断增大min_reduce,直到单词表长度不大于max_vocab_size
self.corpus_count = sentence_no + 1 #保存语料数(句子数)
self.raw_vocab = vocab #保存单词表
return total_words #返回单词总数
scale_vocab
:应用min_count
的词汇表设置(丢弃不太频繁的单词)和sample
(控制更频繁单词的采样)。
代码内容阅读(有省略):
加载新的词汇表:
if not update: #加载一个新的词汇表
retain_total, retain_words = 0, [] #保留总数,保留的单词
#获得单词及其出现的数量,raw_vocab是scan_vocab中保存的单词表dict
for word, v in iteritems(self.raw_vocab):
#判断当前单词是否被丢弃,trim_rule为修剪规则,默认为none
if keep_vocab_item(word, v, min_count, trim_rule=trim_rule):
retain_words.append(word) #添加单词
retain_total += v #添加词数
if not dry_run:
#为每个单词构建一个Vocab类,传入词频、下标
self.wv.vocab[word] = Vocab(count=v, index=len(self.wv.index2word))
self.wv.index2word.append(word)
else: #不符合条件则丢弃
drop_unique += 1
drop_total += v
添加新的单词更新模型:
else:
new_total = pre_exist_total =