本文主要内容翻译自 Word2vec Tutorial
Gemsim 安装
快速安装
easy install -U gensim
pip install --upgrade gensim
依赖
Python >= 2.6
NumPy >= 1.3
SciPy >= 0.7
输入
Gensim Word2vec 使用一个句子序列作为其输入,每个句子包含一个单词列表。
sentences = [['first', 'sentence'], ['second', 'sentence']]
# train word2vec on the two sentences
model = gensim.models.Word2Vec(sentences, min_count=1)
用 Python 内置的 list 类型作为输入很方便,但当输入内容较多时,会占用很大的内存空间。Gemsim 的输入只要求序列化的句子,而不需要将所有输入都存储在内存中。简单来说,可以输入一个句子,处理它,删除它,再载入另外一个句子。
举例来说, 假如输入分散在硬盘的多个文件中,每个句子一行,那么不需要将所有输入先行存储在内存中,Word2vec 可以一个文件一个文件,一行一行地进行处理。
class MySentences(object):
def __init__(self, dirname):
self.dirname = dirname
def __iter__(self):
for fname in os.listdir(self.dirname):
for line in open(os.path.join(self.dirname, fname)):
yield line.split()
sentences = MySentences('/some/directory') # a memory-friendly iterator
model = gensim.models.Word2Vec(sentences)
如果希望对文件中的内容进行预处理,举例来说,转换编码,大小写转换,去除数字等操作,均可以在 MySentences
迭代器中完成,完全独立于 Word2vec。Word2vec 只负责接收 yield 的输入。
针对高级用户:调用 Word2Vec(sentences, iter=1)
会调用句子迭代器运行两次(一般来说,会运行 iter+1
次,默认情况下 iter=5
)。第一次运行负责收集单词和它们的出现频率,从而构造一个内部字典树。第二次以及以后的运行负责训练神经模型。这两次运行(iter+1
)也可以被手动初始化,如果输入流是无法重复利用的,也可以用下面的方式对其进行初始化。
model = gensim.models.Word2Vec(iter=1) # an empty model, no training yet
model.build_vocab(some_sentences) # can be a non-repeatable, 1-pass generator
model.train(other_sentences) # can be a non-repeatable, 1-pass generator
如果对 Python 中迭代器,可迭代的,生成器这些概念不是很理解,可以参考下文。
Python关键字yield的解释
训练
Word2vec 有多个影响训练速度和质量的参数。
其中之一是用来修剪内部字典树的。在一个数以亿计的预料中出现一到两次的单词非常有可能是噪音或不需要被关注的。另外,也没有足够的数据对他们进行有意义的训练。因此,最好的办法就是直接将他们忽略掉。
model = Word2Vec(sentences, min_count=10) # default value is 5
对于设定 min_count
的值,合理的范围是0 - 100,可以根据数据集的规模进行调整。
另一个参数是神经网络 NN 层单元数,它也对应了训练算法的自由程度。
model = Word2Vec(sentences, size=200) # default value is 100
更大的 size
值需要更多的训练数据,但也同时可以得到更准确的模型。合理的取值范围是几十到几百。
最后一个主要参数是训练并行粒度,用来加速训练。
model = Word2Vec(sentences, workers=4) # default = 1 worker = no parallelization
该参数只有在机器已安装 Cython 情况下才会起到作用。如没有 Cython,则只能单核运行。
内存
在内部,Word2vec 模型的参数以矩阵形式存储(NumPy 数组),数组的大小为 #vocabulary 乘以 #size 的浮点数 (4 bytes)。
三个如上的矩阵被存储在内存中(将其简化为两个或一个的工作进行中)。如果输入中存在 100,000 个互异的词,神经网络规模 size
设为200,则该模型大致需要内存
100,000 * 200 * 3 * 4 bytes = ~229MB
。
除此之外,还需要一些额外的空间存储字典树,但除非输入内容极端长,内存主要仍被上文所提到的矩阵所占用。
评估
Word2vec 训练是一个非监督任务,很难客观地评估结果。评估要依赖于后续的实际应用场景。Google 公布了一个包含 20,000 语法语义的测试样例,形式为 “A is to B as C is to D”。
需要注意的是,如在此测试样例上展示良好性能并不意味着在其它应用场景依然有效,反之亦然。
存储和载入模型
使用 Gensim 的方法进行存储和载入模型
model.save('/tmp/mymodel')
new_model = gensim.models.Word2Vec.load('/tmp/mymodel')
该方法将模型内部的 NumPy 矩阵从硬盘载入到虚拟内存。另外,可以使用如下的方法载入原生 C 工具生成的模型,文本和二进制形式的均可。
model = Word2Vec.load_word2vec_format('/tmp/vectors.txt', binary=False)
# using gzipped/bz2 input works too, no need to unzip:
model = Word2Vec.load_word2vec_format('/tmp/vectors.bin.gz', binary=True)
在线训练和恢复训练
高级用户可以载入模型后用更多的预料对其进行训练,你可能要对参数 total_words
进行调整,取决于希望达到的学习率。
model = gensim.models.Word2Vec.load('/tmp/mymodel')
model.train(more_sentences)
从原生 C 工具生成的模型载入后无法继续进行训练,仍然可以对该模型进行查询和相关度计算操作,但由于字典树的丢失,无法继续进行训练。
使用模型
Word2vec 支持以下多种词语相似度任务:
model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)
[('queen', 0.50882536)]
model.doesnt_match("breakfast cereal dinner lunch";.split())
'cereal'
model.similarity('woman', 'man')
0.73723527
可以用如下方法查询词向量:
model['computer'] # raw NumPy vector of a word
array([-0.00449447, -0.00310097, 0.02421786, ...], dtype=float32)
如需要全体的词向量,可以调用 model.syn0
返回一个 2D 的 NumPy 矩阵。