本文翻译自
本文关于在gensim中如何使用word2vec
准备输入(Preparing the Input)
从一开始,gensim的word2vec把语句序列作为它的输入(即文本);每一个语句就是一个单词序列;
# import modules & set up logging
import gensim, logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = [['first', 'sentence'], ['second', 'sentence']]
# train word2vec on the two sentences
model = gensim.models.Word2Vec(sentences, min_count=1)
把输入当作一个Python内置列表很方便,但当输入量很大的时候,大会占用大量内存时。
Gensim需要输入提供顺序的语句,当迭代结束,没有必要把一切东西都保存在内存中:我么能够提供一个语句,处理它,忘记它,加载另一个语句;
例如,如果我们的输入分散在磁盘中的几个文件夹下,每一个语句占据一行。我们就不用加载所有的数据到内存;我们就可以一个文件接着一个文件、一行接着一行进行处理;
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)
假如我们想要进一步预处理文件中的单词,例如转换到Unicode,变换成小写,移除数字,提取命名实体… 所有的这些都可以在MySentences 迭代器内进行,不需要让word2vec获知。所要知道的仅仅是输入产生一个语句接着一个语句;
高级用户注意:
调用Word2Vec(sentences,iter = 1)
将使语句迭代器运行两遍(一般情况,是iter+1遍;默认iter= 5 )。第一次迭代收集单词和统计单词的频率来构建一个内部的词典树结构;第二次迭代以及之后的迭代用来训练神经模型。这两次迭代能够被人工的的初始化,以防输入流是不可重复的,你只能使用其他的方式进行初始化词典;
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中的数据流
训练(Training)
Word2Vec接受几个参数,它们影响训练速度和质量;
其中之一就是修剪内部字典。在成千上万的语料库中,有些单词仅仅出现了一次或两次,它们极有可能是不令人感兴起的错别字和垃圾;此外,也没有足够的数据使这些单词得到有意义的训练,所以最好的方式就是忽略它们:
model = Word2Vec(sentences, min_count=10) # default value is 5
min_count合理的取值在0-100,取决于数据库的大小;
另一个参数是神经网络层的大小,对应于训练算法的自由度。
model = Word2Vec(sentences, size=200) # default value is 100
size值越大需要越多的训练数据,但是能获得更好的模型;合理的取值在几十到几百之间;
最后一个重要的参数用于训练并行,用于加速训练;
model = Word2Vec(sentences, workers=4) # default = 1 worker = no parallelization
worker 参数只有在安装了Cython之后才起效果。如果没有Cython你只能用单核,因为GIL
存储(Memory)
word2vec 模型参数以矩阵的形式进行存储(Numpy arrays);
包括单词表(被min_count parameter限制)
size(size parameter)
floats(单精度需要4 bytes)
所以如果你的输入包含100,000不同的单词,,神经网络层大小为size = 200 ,模型需要接近100,000*200*4*3 bytes = ~229MB
还需要少量的内存来存储单词树,但是除非你的单词都是极长的字符串,内存占用主要有上述三个矩阵决定;
评价(Evaluating)
Word2vec 训练是一个非监督过程,没有一个客观的评价这个结果;评价取决于最后的应用;
Google发布了它的测试集,大约20,000个语法和语义测试实例
Gensim支持相同的评价集,以相同的方式:
model.accuracy('/tmp/questions-words.txt')
2014-02-01 22:14:28,387 : INFO : family: 88.9% (304/342)
2014-02-01 22:29:24,006 : INFO : gram1-adjective-to-adverb: 32.4% (263/812)
2014-02-01 22:36:26,528 : INFO : gram2-opposite: 50.3% (191/380)
2014-02-01 23:00:52,406 : INFO : gram3-comparative: 91.7% (1222/1332)
2014-02-01 23:13:48,243 : INFO : gram4-superlative: 87.9% (617/702)
2014-02-01 23:29:52,268 : INFO : gram5-present-participle: 79.4% (691/870)
2014-02-01 23:57:04,965 : INFO : gram7-past-tense: 67.1% (995/1482)
2014-02-02 00:15:18,525 : INFO : gram8-plural: 89.6% (889/992)
2014-02-02 00:28:18,140 : INFO : gram9-plural-verbs: 68.7% (482/702)
2014-02-02 00:28:18,140 : INFO : total: 74.3% (5654/7614)
存储和加载模型(Storing and loading models):
可以使用标准的Gensim方法存储和加载模型:
model.save('/tmp/mymodel')
new_model = gensim.models.Word2Vec.load('/tmp/mymodel')
此外,能够加载由最初的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)
在线训练/恢复训练
高级用户能够加载一个模型,使用更多的语句继续训练它:
model = gensim.models.Word2Vec.load('/tmp/mymodel')
model.train(more_sentences)
模型的使用:
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)