word2vec 基于 gensim 包的实现以及 预训练模型的再训练

先占个坑,基于 Python gensim模块进行word2vec的训练相对容易,在此基础上根据选择相应的预训练的word2vec 向量,基于自有数据的再训练更符合实际应用。

官方文档

关于模型的训练就不说了,主要说下预训练模型的使用。

预训练的模型可能包括两种格式,一种是在训练过程中使用:

model.wv.save(file_path)

另一种是保存和 original C word2vec-tool 相同的格式:

model.wv.save_word2vec_format(file_path)

在进行再训练时,上述两种保存的格式会影响我们的继续训练。

如果是以第一种方式进行保存的,则可以通过以下的方式进行再训练:

model = gensim.models.Word2Vec.load(temporary_filepath)
more_sentences = [
['Advanced', 'users', 'can', 'load', 'a', 'model',
'and', 'continue', 'training', 'it', 'with', 'more', 'sentences']
]
model.build_vocab(more_sentences, update=True)
model.train(more_sentences, total_examples=model.corpus_count, epochs=model.iter)

如果是以第二种方式进行保存的(网上的预训练模型大部分都是这种模式),首先介绍一些已有的模型:

https://github.com/Embedding/Chinese-Word-Vectors

这里提供了一些训练好的词向量,向量维度为300。

https://ai.tencent.com/ailab/nlp/en/embedding.html

腾讯提供了一个基于800万中文语料的词向量模型,向量维度为200。

基于这种方式保存的模型,可以通过如下的方式进行再训练:

# 首先初始化一个word2vec 模型:
w2v_model = Word2Vec(size=300, sg=1, min_count=1)
w2v_model.build_vocab(more_sentences)

# 再加载第三方预训练模型:
third_model = KeyedVectors.load_word2vec_format(third_model_path, binary=False)
# 通过 intersect_word2vec_format()方法merge词向量:
w2v_model.build_vocab([list(third_model.vocab.keys())], update=True) w2v_model.intersect_word2vec_format(third_model_path, binary=False, lockf=1.0) w2v_model.train(more_sentences, total_examples=w2v_model.corpus_count, epochs=w2v_model.epochs)

其中的维度需要与你要结合的预训练模型的维度一致。以上即可结合已有的词向量与你的部分语料结合。
参考资料: https://stackoverflow.com/questions/46013294/gensim-doc2vec-intersect-word2vec-format-command
https://datascience.stackexchange.com/questions/10695/how-to-initialize-a-new-word2vec-model-with-pre-trained-model-weights

且实际测试中显示,新的语料也能改变原有模型中的词向量。

可以使用word2vec获取两个句子的相似度:

list1 = ['附近', '有', '卫生间', '吗']
list2 = ['附近', '最近', '地铁', '在', '哪里']
list3 = ['附近', '有', '地铁', '吗']
sim1_3 = model.wv.n_similarity(list1, list3)
sim2_3= model.wv.n_similarity(list2, list3)

单纯的使用词向量判断语句的相似度缺少了一些词语的权重信息,如上述例子中,n_similarity的实现是将所有的词的词向量相加再平均,这样一些常见词如: “附近”、“吗” 等会对句子的相似度与 “地铁”、“卫生间”等关键词起到相同的作用。因此,可以结合TF-IDF词权重,进行更好的判断。

如果有需要的话会继续更新结合了TF-IDF词权重的相似度度量方法。

其中遇到的问题先补上:

1. 将模型部署到环境上时出现如下异常:

Traceback (most recent call last):
File "/home/ubuntu/python/word2vec/eval_model.py", line 150, in
model = Word2Vec.load(model_path)
File "/usr/local/lib/python3.6/dist-packages/gensim/models/word2vec.py", line 1141, in load
model = super(Word2Vec, cls).load(*args, *
kwargs) File "/usr/local/lib/python3.6/dist-packages/gensim/models/base_any2vec.py", line 1230, in load model = super(BaseWordEmbeddingsModel, cls).load(args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/gensim/models/base_any2vec.py", line 602, in load
return super(BaseAny2VecModel, cls).load(fname_or_handle, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/gensim/utils.py", line 435, in load
obj = unpickle(fname)
File "/usr/local/lib/python3.6/dist-packages/gensim/utils.py", line 1398, in unpickle
return _pickle.load(f, encoding='latin1')
ModuleNotFoundError: No module named 'numpy.random._pickle'

原因numpy 版本不一致, https://github.com/RaRe-Technologies/gensim/issues/2602

解决办法: 查看模型保存时使用的numpy版本:

import numpy
numpy.__version
__

升级至指定版本:pip3 install --upgrade numpy==1.17.0

2. 缺少bz2:

File “/usr/local/python3/lib/python3.7/bz2.py”, line 19, in
from _bz2 import BZ2Compressor, BZ2Decompressor
ModuleNotFoundError: No module named ‘_bz2’

解决办法https://stackoverflow.com/questions/12806122/missing-python-bz2-module

sudo yum install bzip2-devel
sudo ln -s `find /usr/lib64/ -type f -name "libbz2.so.1*"` /usr/lib64/libbz2.so.1.0

发表评论

电子邮件地址不会被公开。 必填项已用*标注