Windows系统下使用维基百科中文语料训练word2vec词向量
By 龙前尘

实验环境:win8、python 2.7


转载请注明地址:
http://blog.csdn.net/svenhuayuncheng/article/details/78751311

笔者按

笔者近期用简单问句模板,搭建了一个面向特定领域的KBQA系统。在做问法泛化的时候,考虑使用问句和同义词集合的交集来处理。
在实验时,笔者发现,单纯使用Jaccard交集来刻画问句与模板的相似度,还是有些粗糙,需要大量的人力统计或制造更可能多的模板,尽量覆盖问法。但是显然,这个做法是没有边界的。
为了解决这个问题,并且体现出问句与模板的语义相似度,笔者想使用词向量为基础,来尝试各种相似度的计算,来找到最相近的模板。
因此,经过一段时间的实验(主要是排雷),完成了词向量训练。笔者使用的是维基百科中文语料,以及特定领域的一些语料进行训练。
这里记录一下全过程,与大家分享与交流。

1. 提取语料

1.1 下载wiki百科的数据

从wiki百科下载中文最新语料。
dump下载地址:https://dumps.wikimedia.org/zhwiki/latest/
本文使用的语料为:zhwiki-latest-pages-articles.xml.bz2,大小大约为1.4GB。

1.2 数据抽取

受到这篇博文获取并处理中文维基百科语料的启发,编写python代码实现。
其中的主要工作,是从下载的压缩包中抽取出wiki百科正文,并通过正则表达式进行初步过滤。首先去掉那些帮助页面和重定向的页面,这些页面的信息都是无用的。其次处理页面的一些特殊的、非文本的标记,将其去掉。最后使用opencc对于文本信息进行繁体到简体的转化。关于如何安装opencc,可以查看博主的文章:手动安装opencc(中文简繁体转换插件) ——解决安装opencc时出现HTTP 403错误的问题。
代码如下:

#coding:utf-8
from gensim.corpora.wikicorpus import extract_pages,filter_wiki
import bz2file
import re
import opencc
from tqdm import tqdm
import codecswiki = extract_pages(bz2file.open('zhwiki-latest-pages-articles.xml.bz2'))def wiki_replace(d):s = d[1]s = re.sub(':*{\|[\s\S]*?\|}', '', s)s = re.sub('[\s\S]*?', '', s)s = re.sub('(.){{([^{}\n]*?\|[^{}\n]*?)}}', '\\1[[\\2]]', s)s = filter_wiki(s)s = re.sub('\* *\n|\'{2,}', '', s)s = re.sub('\n+', '\n', s)s = re.sub('\n[:;]|\n +', '\n', s)s = re.sub('\n==', '\n\n==', s)#cc = opencc.OpenCC('mix2s')#return cc.convert(s).strip()return si = 0
f = codecs.open('wiki.txt', 'w', encoding='utf-8')
w = tqdm(wiki, desc=u'已获取0篇文章')
for d in w:#re.findall返回正则表达式匹配的所有字符串,用于去掉帮助页面和重定向页面;if not re.findall('^[a-zA-Z]+:', d[0]) and not re.findall(u'^#', d[1]):s = wiki_replace(d)f.write(s+'\n\n\n')i += 1#print(u'已获取%s篇文章'%i)if i % 100 == 0:w.set_description(u'已获取%s篇文章'%i)f.close()

注意,此处的第21、22行是使用opencc接口进行繁体中文到简体中文的转化代码。但是笔者在跑代码时,发现使用python的opencc接口,程序会一直卡在繁/简转换这里,而不继续运行。这个bug暂时还没有解决。笔者使用了另一种方法来运行opencc进行转换。如果大家可以正常运行代码,那么可以去掉这里的注释,在代码中直接进行繁/简转换。

2. 繁简转化

如前文所述,在python代码中跑opencc会有问题。故笔者使用命令行来进行繁/简转化。
首先在https://bintray.com/package/files/byvoid/opencc/OpenCC下载opencc的windows安装包opencc-1.0.1-win64.7z,并解压放置到自定义的目录下。
然后在该目录下,放入待转换的文件,并在命令行运行该命令来转化,可以得到转化后的文件:

opencc -i wiki.txt -o wiki.zh.jian.txt -c t2s.json

经过转化的简体中文文件,其编码为是utf16,需要写代码进行文件编码的转换,转换为utf8的编码,转换代码如下:

#encoding:utf8
import codecs
from tqdm import tqdm def transformFile(ipath, opath):encoding = 'utf-16-le'iFile = codecs.open(ipath, 'r', encoding)encoding = 'utf-8'oFile = codecs.open(opath, 'w', encoding)sentences = iFile.readlines()i = 0w = tqdm(sentences, desc=u'转换句子')for sentence in w:oFile.write(sentence)i += 1if i % 100 == 0:w.set_description(u'已转换%s个句子'%i)iFile.close()oFile.close()ipath = 'wiki.zh.jian.txt'
opath = 'wiki.zh.jian.utf8.txt'
transformFile(ipath, opath)

3. 语料清洗

经过简体化的文档,仍然有很多脏信息。如数字、标点符号、非中文语言字符等,并且文档中的句子是不能用来训练的,需要进行分词处理。
故编写代码,进行非中文字符串的清除,以及分词。

这个博客有整理好的停用词,可以直接拿来做分词用。

分词及文本清洗的代码如下,此处使用jieba分词工具。

#encoding:utf8
import jieba
import os
import codecs
from tqdm import tqdmclass MySentences(object):def __init__(self, dirname):self.dirname = dirnamedef __iter__(self):for fname in os.listdir(self.dirname):for line in open(os.path.join(self.dirname, fname)):if len(line) > 0:yield [segment.strip() for segment in jieba.cut(line.strip(), cut_all=False)if segment not in stoplist and len(segment) > 0]def is_ustr(instr):out_str = ''for index in range(len(instr)):if is_uchar(instr[index]):out_str = out_str + instr[index].strip()return out_strdef is_uchar(uchar):# """判断一个unicode是否是汉字"""if u'\u4e00' <= uchar <= u'\u9fff':return Trueif __name__ == '__main__':dirname = 'zh_simplify'# 读取停用词;stop_f = codecs.open(u'停用词.txt', 'r', encoding='utf-8')stoplist = {}.fromkeys([line.strip() for line in stop_f])# 进行jieba分词sentences = MySentences(dirname)# 分词结果写入文件f = codecs.open('wiki_jieba.txt', 'w', encoding='utf-8')i = 0j = 0w = tqdm(sentences, desc=u'分词句子')for sentence in w:if len(sentence) > 0:output = " "for d in sentence:# 去除停用词;if d not in stoplist:output += is_ustr(d).strip() + " "f.write(output.strip())f.write('\r\n')i += 1if i % 10000 == 0:j += 1w.set_description(u'已分词: %s万个句子'%j)f.close()

经过分词之后的文本,大概是这样的:

每一行为一篇文档,每个文档被分为许多词语的组合,且以空格分开。
这里我建立了一个名为‘zh_simplify’的文件夹,里面存放有几个文本文件,代码中迭代地处理这些文件,并将语料都存于最终的一个文档中。
整个清理过程大约40分钟。

4. 词向量训练

经过那么多步骤的预处理,终于得到“干净”的语料,可以开始训练了。
先放训练代码:

# -*- coding: utf-8 -*-
import logging
import multiprocessing
import codecs
from tqdm import tqdmfrom gensim.models import Word2Vec
from gensim.models.word2vec import LineSentenceif __name__ == '__main__':program = "train_word2vec_model.py"logger = logging.getLogger(program)logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')logging.root.setLevel(level=logging.INFO)logger.info("running %s" % ' '.join(program))infile = "wiki_jieba.txt"vec_outfile1 = "wiki.zh.text.model"vec_outfile2 = "wiki.zh.text.vector"sentences = LineSentence(infile)model = Word2Vec(LineSentence(infile), size=300, window=5, min_count=5,workers=multiprocessing.cpu_count(), iter=100)# trim unneeded model memory = use(much) less RAM# model.init_sims(replace=True)model.save(vec_outfile1)model.wv.save_word2vec_format(vec_outfile2, binary=False)

最重要的训练语句只要一行:

model = Word2Vec(LineSentence(infile), size=300, window=5, min_count=5, workers=multiprocessing.cpu_count(), iter=100)

这里用了LineSentence函数,文档中这个函数功效为:

Simple format: one sentence = one line; words already preprocessed and separated by whitespace.

即表示:这里一句话 = 一行(用换行符分割),每一句话都经过预处理,并且用空白符分隔。

另外,训练参数的意义如下:

  • size=300 :词向量的维度大小为300维;size越大,需要更多的训练数据,但是效果会更好. 推荐值为几十到几百
  • window=5 :滑动窗口大小为5,即当前词的上下文为前后各两个词
  • min_count=5 :词频少于5的词被舍弃掉
  • workers=multiprocessing.cpu_count() :多核并行计算,worker参数只有在安装了Cython后才有效. 没有Cython的话, 只能使用单核.
  • iter=100 :训练迭代次数,即将语料训练词向量100次

此外,还有一些参数设置:

  • sg=0 :用于设置训练算法,默认为0,对应CBOW算法;sg=1,则采用skip-gram算法
  • alpha=0.05 :用于设置学习速率
  • seed=1 :用于随机数发生器,初始化词向量
  • max_vocab_size=None :设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
  • sample=0.001 :高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
  • hs=0 :如果设置为0(defaut),使用negative sampling;若为1,使用hierarchica softmax技巧
  • negative=5 :如果>0,则会采用negative samping,用于设置多少个noise words(负例)
  • cbow_mean=1 :如果为1(defaut)则对上下文向量求均值进行训练;如果为0,则采用上下文词向量的和;只有使用CBOW的时候才起作用
  • hashfxn=< built-in function hash> : hash函数来初始化权重,默认使用python的hash函数
  • trim_rule=None :用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除
  • sorted_vocab=1 :如果为1(default),则在分配word index 的时候会先对单词基于频率降序排序
  • batch_words=10000 :表示每一批的传递给线程的单词的数量,默认为10000

所有参数都设置的训练语句如下所示:

model = Word2Vec(LineSentence(infile), size=300, alpha=0.5,window=5, min_count=5, max_vocab_size=None, sample=0.001,seed=1, workers=multiprocessing.cpu_count(),min_alpha=0.0001, sg=0, hs=0, negative=5, cbow_mean=1, hashfxn=<built-in function hash>,iter=100,null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000)

5. 测试词向量

训练开始:

经过将近10个小时,终于完成了词向量的训练。

最终得到两个文件,Gensim中默认格式的词向量文件model,以及原始c版本的词向量文件vector。

写一个代码测试下效果吧:

# encoding:utf8
import gensimif __name__ == '__main__':model = gensim.models.Word2Vec.load('wiki.zh.text.model')word1 = u'农业'word2 = u'计算机'if word1 in model:print (u"'%s'的词向量为: " % word1)print (model[word1])else:print (u'单词不在字典中!')result = model.most_similar(word2)print (u"\n与'%s'最相似的词为: " % word2)for e in result:print ('%s: %f' % (e[0], e[1]))print (u"\n'%s'与'%s'的相似度为: " % (word1, word2))print (model.similarity(word1, word2))print (u"\n'早餐 晚餐 午餐 中心'中的离群词为: ")print (model.doesnt_match(u"早餐 晚餐 午餐 中心".split()))print (u"\n与'%s'最相似,而与'%s'最不相似的词为: " % (word1, word2))temp = (model.most_similar(positive=[u'篮球'], negative=[u'计算机'], topn=1))print ('%s: %s' % (temp[0][0], temp[0][1]))

最终结果如下所示:

上图为‘农业’的词向量。


上图为一些近义词、离群词等的测试效果。

以上,完成了维基百科中文语料训练词向量的全过程。本文旨在做一个实验记录,也是抛砖引玉,欢迎大家共同探讨!

Windows系统下使用维基百科中文语料训练Word2Vec词向量相关推荐

  1. 【NLP】维基百科中文数据训练word2vec词向量模型——基于gensim库

    前言   本篇主要是基于gensim 库中的 Word2Vec 模型,使用维基百科中文数据训练word2vec 词向量模型,大体步骤如下: 数据预处理 模型的训练 模型的测试 准备条件: Window ...

  2. 维基百科简体中文语料训练word2vec词向量

    步骤: 1.下载维基百科中文语料 2.使用工具从压缩包中抽取正文文本 3.将繁体字转简体字 4.分词 5.训练模型 6.测试模型 1.下载维基百科中文语料 语料下载地址:https://dumps.w ...

  3. wiki中文文本语料下载,在维基百科中文语料训练Word2vec and doc2vec 文本向量化代码示例

    首先下载wiki中文语料(大约1.7G) https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2 ...

  4. 【用户行为分析】 用wiki百科中文语料训练word2vec模型

    本文地址: http://blog.csdn.net/hereiskxm/article/details/49664845  前言 最近在调研基于内容的用户行为分析,在过程中发现了word2vec这个 ...

  5. 用Python3.6来做维基百科中文语料

    首先介绍一下word2vec 参考http://www.cnblogs.com/iloveai/p/word2vec.html 2013年,Google开源了一款用于词向量计算的工具--word2ve ...

  6. Python Djang 搭建自动词性标注网站(基于Keras框架和维基百科中文预训练词向量Word2vec模型,分别实现由GRU、LSTM、RNN神经网络组成的词性标注模型)

    引言 本文基于Keras框架和维基百科中文预训练词向量Word2vec模型,分别实现由GRU.LSTM.RNN神经网络组成的词性标注模型,并且将模型封装,使用python Django web框架搭建 ...

  7. windows下使用word2vec训练维基百科中文语料全攻略!(三

    全文共1552个字,7张图,预计阅读时间8分钟. 训练一个聊天机器人的很重要的一步是词向量训练,无论是生成式聊天机器人还是检索式聊天机器人,都需要将文字转化为词向量,时下最火的词向量训练模型是word ...

  8. windows下使用word2vec训练维基百科中文语料全攻略!(二)

    全文共454个字,3张图,预计阅读时间5分钟. 训练一个聊天机器人的很重要的一步是词向量训练,无论是生成式聊天机器人还是检索式聊天机器人,都需要将文字转化为词向量,时下最火的词向量训练模型是word2 ...

  9. gensim 中文语料训练 word2vec

    gensim 的word2vec api参见: https://radimrehurek.com/gensim/models/word2vec.html 本文说一下中文语料的使用,很简单. 1 wor ...

  10. NLP之word2vec:利用 Wikipedia Text(中文维基百科)语料+Word2vec工具来训练简体中文词向量

    NLP之word2vec:利用 Wikipedia Text(中文维基百科)语料+Word2vec工具来训练简体中文词向量 目录 输出结果 设计思路 1.Wikipedia Text语料来源 2.维基 ...

最新文章

  1. Java实现内嵌浏览器
  2. Science审稿人谈中国首次实现量子优越性:「九章」到底打了谁的脸?
  3. Linux网络篇基础知识
  4. linux服务器带宽设置,linux 系统查看服务器带宽使用
  5. dz论坛发html乱码,发帖时出现乱码 - Discuz!-安装使用 - Discuz! 官方站 - Powered by Discuz!...
  6. swift函数的用法,及其嵌套实例
  7. ubuntu怎么将Dash切换位bash
  8. 简单图片隐写术练习题
  9. 启动Xshell报错:由于找不到MSVCR110.dll,无法继续执行代码。重新安装程序可能会解决此问题
  10. 人参果水果宣传文案模版,水果店文案人参果
  11. 英语学了十年,还是学不会!建议你:那就别学了!
  12. Android Studio教程从入门到精通
  13. zuul 里面的 prefix 和 strip-prefix 怎么使用
  14. R与Excel之数据分析
  15. GPS的相关指标的意思
  16. Lua-cjson使用笔记
  17. mysql外键约束失败
  18. Opencv之图像滤波:2.均值滤波(cv2.blur)
  19. 日本鲭川CRAFSIS进军中国市场 无界眼镜独家代理
  20. 海格里斯穿梭车操作指南五步曲

热门文章

  1. c语言一些简单的程序
  2. smart3D的初探索
  3. 什么是爬虫-Java网络爬虫系统性学习与实战(2)
  4. 微信小程序底部导航栏小效果
  5. 高端物理学名词_物理名词大全
  6. ad中电容用什么封装_【AD封装】XH2.54mm座子插件贴片(带3D)
  7. 牛顿插值法,泰勒公式
  8. 揭秘360手机助手未经用户同意,自动开启辅助的“黑科技”
  9. LTE学习笔记:LTE总体架构
  10. Axure 基础控件(1-49)