网上看了很多其他博客,发现有些部分都太老旧了,以至于现在套用都错误百出。。。这里总结了一下使用中文维基百科训练word2vec模型的最新方法。
参考链接:
https://blog.csdn.net/vivian_ll/article/details/89914219
https://blog.csdn.net/chichichich/article/details/80783832
https://blog.csdn.net/Pit3369/article/details/95454354
https://blog.csdn.net/luhuibo318/article/details/98487866
https://blog.csdn.net/sinat_29957455/article/details/81290356
数据下载地址:https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
(下载完成后不用解压)
WikiExtractor:是意大利人用Python写的一个维基百科抽取器,使用非常方便。用于从原始的xml文件中提取出标题和正文。
地址:https://github.com/attardi/wikiextractor/blob/master/WikiExtractor.py
在本地新建一个脚本,将github上的代码全部复制过来就好了,再将这个WikiExtractor.py文件和原始数据文件放到一个路径下。
在此路径下打开cmd,输入
python WikiExtractor.py -b 500M -o zhwiki zhwiki-latest-pages-articles.xml.bz2
参数-b 500M表示以500M为单位切分文件,默认是1M。
这里,我们得到了3个文本文件:wiki_00, wiki_01,wiki_02。
维基百科的中文数据是繁简混杂的,里面包含大陆简体、台湾繁体、港澳繁体等多种不同的数据。有时候在一篇文章的不同段落间也会使用不同的繁简字。为了处理方便起见,我们直接使用了开源项目繁体简体转换工具opencc。
下载地址:https://bintray.com/package/files/byvoid/opencc/OpenCC
百度云下载地址:链接:https://pan.baidu.com/s/10yI1lPRKNOYJ2aSbl4YegA 密码:2kv9
下完直接解压就可以了。
这里建议下载 opencc-1.0.4-win32.7z 这个版本(虽然我电脑是win64)
别问为什么,我也不知道,反正我下了很多其他的版本都运行不成功。。
然后将需要转换的三个文件加入到刚下载的OpenCC的bin目录中,在目录下打开cmd,运行
由于Wikipedia Extractor抽取正文时,会将有特殊标记的外文直接剔除。我们需要将「」『』这些符号替换成引号,顺便删除空括号。代码如下:
import re
import sys
import codecs
from imp import reload
def myfun(input_file):
p1 = re.compile(r'-\{.*?(zh-hans|zh-cn):([^;]*?)(;.*?)?\}-')
p2 = re.compile(r'[(\(][,;。?!\s]*[)\)]')
p3 = re.compile(r'[「『]')
p4 = re.compile(r'[」』]')
outfile = codecs.open('std_zh_wiki', 'a+', 'utf-8')
with codecs.open(input_file, 'r', 'utf-8') as myfile:
for line in myfile:
line = p1.sub(r'\2', line)
line = p2.sub(r'', line)
line = p3.sub(r'“', line)
line = p4.sub(r'”', line)
outfile.write(line)
outfile.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
print ("Usage: python script.py inputfile")
sys.exit()
reload(sys)
input_file = sys.argv[1]
myfun(input_file)
这个代码我是参考第一个借鉴链接的,但他所用的是python2,我是3,所以有几个注意地方
1)在python2里面,u表示unicode string,类型是unicode, 没有u表示byte string,类型是 str。在python3里面,所有字符串都是unicode string, u前缀没有特殊含义了。所以链接1的这部分代码里所有ur要改为r。
2)Python 3.0 把 reload 内置函数移到了 imp 标准库模块中。它仍然像以前一样重载文件,但是,必须导入它才能使用。所以要加一行 from imp import reload
将这个py文件保存,命名为 exec_sum.py,为了避免出错,所以还是把它放到和之前处理好的数据文件的同一路径下。
在cmd中运行
python .\exec_sum.py zh_wiki_00
python .\exec_sum.py zh_wiki_01
python .\exec_sum.py zh_wiki_02
得到格式化文件:std_zh_wiki
import jieba
import jieba.analyse
# 待分词的文本路径
sourceTxt = 'E:\\downloads\\opencc-1.0.4\\bin\\std_zh_wiki'
# 分好词后的文本路径
targetTxt = 'E:\\downloads\\opencc-1.0.4\\bin\\cut_std_zh_wiki'
# 对文本进行操作
with open(sourceTxt, 'r', encoding = 'utf-8') as sourceFile, open(targetTxt, 'a+', encoding = 'utf-8') as targetFile:
for line in sourceFile:
seg = jieba.cut(line.strip(), cut_all = False)
# 分好词之后之间用空格隔断
output = ' '.join(seg)
targetFile.write(output)
targetFile.write('\n')
print('写入成功!')
等待了半个多小时后,终于分好了
比原来的文件大一点,因为多了空格
效果是这个样子…分的不是很好,以后再试着改进吧!
import logging
from gensim.models import word2vec
def main():
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s",level=logging.INFO)
sentences = word2vec.LineSentence("cut_std_zh_wiki")
model = word2vec.Word2Vec(sentences,size=300)
model.save("wiki_corpus.model")
if __name__ == '__main__':
main()
又是 longlonglong time later,终于训练完了,得到
import gensim
model = gensim.models.Word2Vec.load('wiki_corpus.model')
print(model.wv.most_similar('睡觉'))
[('睡', 0.7924377918243408), ('洗澡', 0.7919644713401794), ('吃饭', 0.7749820351600647), ('喝水', 0.7549980878829956), ('就寝', 0.720653772354126), ('喝酒', 0.7139127254486084), ('出门', 0.7127513885498047), ('坐下', 0.7068793773651123), ('躺', 0.6949901580810547), ('入睡', 0.6922317743301392)]
print(model.wv.most_similar(['伦敦','中国'],['北京']))
[('英国', 0.6151248216629028), ('欧洲', 0.5450127720832825), ('英格兰', 0.5430649518966675), ('美国', 0.528755784034729), ('苏格兰', 0.5008379220962524), ('澳洲', 0.5004901885986328), ('爱尔兰', 0.490997314453125), ('澳大利亚', 0.486044704914093), ('德国', 0.4796403646469116), ('大英帝国', 0.4759770333766937)]