一、原理
word2vec原理部分有大神已经写好的,此处给出链接方便查看:
http://www.cnblogs.com/pinard/p/7160330.html
https://blog.csdn.net/lyc_yongcai/article/details/73275229
二、中文维基百科语料上的Word2Vec实验
参考:https://www.jianshu.com/p/ec27062bd453
https://blog.csdn.net/sinat_36972314/article/details/79637788
http://www.52nlp.cn/%E4%B8%AD%E8%8B%B1%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E8%AF%AD%E6%96%99%E4%B8%8A%E7%9A%84word2vec%E5%AE%9E%E9%AA%8C
1、 开发环境准备
1.1 python环境
在python官网下载计算机对应的python版本,本人使用的是windows下Python3.6.0的版本。
1.2 gensim模块
(1)下载模块
Word2vec需要使用第三方gensim模块, gensim模块依赖numpy和scipy两个包,因此需要依次下载对应版本的numpy、scipy、gensim。下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/
(2)安装模块
cmd打开dos命令行,输入 pip install numpy 、pip install scipy、pip install gensim
输入Python,在python环境下输入import numpy 、import scipy 、import gensim不报错则安装成功
2、 python 实现
2.1 Wiki中文数据的下载
到wiki官网下载中文语料,下载完成后会得到命名为zhwiki-latest-pages-articles.xml.bz2的文件,大小约为1.4G,里面是一个XML文件。
下载地址如下:https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
2.2 将XML的Wiki数据转换为text格式
编写python程序将XML文件转换为text格式,使用到了gensim.corpora中的WikiCorpus函数来处理维基百科的数据。python代码实现如下所示,文件命名为process_wiki.py。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#将xml的wiki数据转换为text格式import logging
import os.path
import sysfrom gensim.corpora import WikiCorpusif __name__ == '__main__':program = os.path.basename(sys.argv[0]) #得到文件名logger = logging.getLogger(program)logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')logging.root.setLevel(level=logging.INFO)logger.info("running %s" % ' '.join(sys.argv))# check and process input argumentsif len(sys.argv) < 3:print (globals()['__doc__'] % locals())sys.exit(1)inp, outp = sys.argv[1:3]space = " "i = 0#output = open(outp, 'w')output = open(outp, 'w',encoding='utf-8') #不加编码方式在处理时会出错wiki = WikiCorpus(inp, lemmatize=False, dictionary={})for text in wiki.get_texts(): #通过get_texts将维基里的每篇文章转换为1行的text文本,并且丢掉标点等output.write(space.join(text) + "\n")i = i + 1if (i % 10000 == 0):logger.info("Saved " + str(i) + " articles")output.close()logger.info("Finished Saved " + str(i) + " articles")
在代码所在文件夹下
打开dos窗口(
Shift+鼠标右键->在此处打开命令窗口
),输入如下命令行:
python process_wiki.py zhwiki-latest-pages-articles.xml.bz2 wiki.zh.txt
获得wiki.zh.txt。大约30分钟运行完成30多万篇文章,得到一个1G多的txt文件。
2.3 Wiki数据预处理
2.3.1 中文繁体替换成简体
Wiki中文语料中包含了很多繁体字,需要转成简体字再进行处理,这里使用到了OpenCC工具进行转换。
(1)安装OpenCC
到以下链接地址下载对应版本的OpenCC,本人下载的版本是opencc-1.0.1-win32。
https://bintray.com/package/files/byvoid/opencc/OpenCC
另外,资料显示还有python版本的,使用pip install opencc-python进行安装,未实践不做赘述。
(2)使用OpenCC进行繁简转换
进入解压后的opencc的目录(opencc-1.0.1-win64),双击opencc.exe文件。在当前目录打开dos窗口(Shift+鼠标右键->在此处打开命令窗口),输入如下命令行:
opencc -i wiki.zh.txt -o wiki.zh.simp.txt -c t2s.json
则会得到文件wiki.zh.simp.txt,即转成了简体的中文。
(3)结果查看
解压后的txt有900多M,用notepad++无法打开,所以采用python自带的IO进行读取。Python代码如下:
import codecs,sysf = codecs.open(‘wiki.zh.simp.txt‘,‘r‘,encoding="utf8")line = f.readline()print(line)
2.4 结巴分词
Python实现代码jieba_participle.py如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 逐行读取文件数据进行jieba分词 import jieba
import jieba.analyse
import jieba.posseg as pseg #引入词性标注接口
import codecs, sys if __name__ == '__main__': f = codecs.open('wiki.zh.simp.txt', 'r', encoding='utf-8') target = codecs.open('wiki.zh.simp.seg.txt', 'w', encoding='utf-8') print('open files.') lineNum = 1 line = f.readline() while line: print('---processing ', lineNum, ' article---') seg_list = jieba.cut(line, cut_all=False) line_seg = ' '.join(seg_list) target.writelines(line_seg) lineNum = lineNum + 1 line = f.readline() print('well done.') f.close() target.close()
在代码所在目录的命令行输入python jieba_participle.py进行分词,结果如下图
2.5 word2vec模型训练
接下来中文分完词的文档可进行Word2Vec模型的训练,代码train_word2vec_model.py如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 使用gensim word2vec训练脚本获取词向量 import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim') # 忽略警告
import logging
import os.path
import sys
import multiprocessing
from gensim.corpora import WikiCorpus
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence if __name__ == '__main__': # print(open('/Users/sy/Desktop/pyRoot/wiki_zh_vec/cmd.txt').readlines()) # sys.exit() program = os.path.basename(sys.argv[0]) logger = logging.getLogger(program) logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s', level=logging.INFO) logger.info("running %s" % ' '.join(sys.argv)) # inp为输入语料, outp1 为输出模型, outp2为原始c版本word2vec的vector格式的模型 fdir = 'D:/科研/word2vec_text/' inp = fdir + 'wiki.zh.simp.seg.txt' outp1 = fdir + 'wiki.zh.text.model' outp2 = fdir + 'wiki.zh.text.vector' # 训练skip-gram模型 sg=1 model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count()) # 保存模型 model.save(outp1) model.wv.save_word2vec_format(outp2, binary=False)
在代码所在目录的命令行输入python train_word2vec_model.py进行训练,得到如下四个文件
3、模型测试
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 测试训练好的模型 import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')# 忽略警告
import sys
# reload(sys)
# sys.setdefaultencoding('utf-8')
import gensim if __name__ == '__main__': fdir = 'D:/科研/word2vec_text/' model = gensim.models.Word2Vec.load(fdir + 'wiki.zh.text.model') word = model.most_similar(u"篮球") for t in word: print(t[0], t[1])'''word = model.most_similar(positive=[u"皇上", u"国王"],negative=u"皇后")for t in word: print(t[0], t[1])print model.doesnt_match(u'太后 妃子 贵人 贵妃 才人'.split())print model.similarity(u'书籍',u'书本')print model.similarity(u'逛街',u'书本') '''
在代码所在目录的命令行输入python model_test.py进行测试,结果如下