赞
踩
自然语言处理有很多方法,最近很流行的是谷歌开源项目word2vec,详见谷歌官网:官网链接。其主要理论由Tomas Mikolov大神团队的2篇论文组成:Efficient Estimation of Word Representations in Vector Space, Distributed Representations of Words and Phrases and their Compositionality。
传统的方法是将词汇作为离散的单一符号,这些符号编码毫无规则,无法提供词汇之间可能存在的关联关系,而词汇的向量表示将克服上述难题。
向量空间模型(VSM)将词汇表示在一个连续的向量空间中,语义近似的词被映射为相邻的数据点。VSM依赖于分布式假设思想,该思想的核心是:出现于相同的上下文情景中的词汇都有相似的语义。
基于VSM假设有2种研究方法:
1,基于计数的方法:计算某词汇极其临近词在一个大型语料库中共同出现的频率,然后将其映射到一个小而稠密的向量中。
2,预测方法:该方法试图直接从某词汇的临近词对其进行预测,此过程利用学习到的向量。
word2vec是一种可以进行高效率词嵌套学习的预测模型,该模型有2种具体的形式:
1,CBOW模型:根据上下文词汇“the cat sits on the”,来预测目标词“mat”。
2,skip-gram模型:通过目标词来预测源词汇。
本文不关注具体理论,而是详细介绍如何获取并预处理中文维基百科语料库,并训练成word2vec模型。
实验环境:Ubuntu14.04/Python2.7(Anaconda版)
1,下载原始数据
数据下载地址:https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
下载的文件是一个大小为1.3G的压缩包,解压后是个5.8G左右的xml文件,内容是网页标签形式的。我们需要抽取出其中的有效信息。
2,使用Wikipedia Extractor抽取正文
Wikipedia Extractor是意大利人用Python写的一个维基百科抽取器,使用非常方便。下载之后直接使用这条命令即可完成抽取,运行时间很快。执行以下命令。
$ sudo apt-get install unzip python python-dev python-pip
$ git clone https://github.com/attardi/wikiextractor.git wikiextractor
$ cd wikiextractor
$ sudo python setup.py install
$ ./WikiExtractor.py -b 1024M -o extracted zhwiki-latest-pages-articles.xml.bz2
参数-b 1024M表示以1024M为单位切分文件,默认是1M。由于最后生成的正文文本约1060M,把参数设置的大一些可以保证最后的抽取结果全部存在一个文件里。这里我们设为1024M,可以分成一个1G的大文件和一个36M的小文件,后续的步骤可以先在小文件上实验,再应用到大文件上。
这里,我们得到了2个文本文件:wiki_00, wiki_01。大小分别为:1024M, 36.7M。
3,繁体转简体
维基百科的中文数据是繁简混杂的,里面包含大陆简体、台湾繁体、港澳繁体等多种不同的数据。有时候在一篇文章的不同段落间也会使用不同的繁简字。
为了处理方便起见,我们直接使用了开源项目opencc。参照安装说明的方法,安装完成之后,使用下面的命令进行繁简转换,整个过程也很快:
$ sudo apt-get install opencc
$ opencc -i wiki_00 -o zh_wiki_00 -c zht2zhs.ini
$ opencc -i wiki_01 -o zh_wiki_01 -c zht2zhs.ini
命令中的wiki_00/wiki_01这个文件是此前使用Wikipedia Extractor得到的。到了这里,我们已经完成了大部分繁简转换工作。
这里,我们得到了2个简体文件:zh_wiki_00,zh_wiki_01。大小分别为:1024M,36.7M。同上步结果大小不变。
4,符号处理
由于Wikipedia Extractor抽取正文时,会将有特殊标记的外文直接剔除。我们最后再将「」『』这些符号替换成引号,顺便删除空括号,就大功告成了!代码如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import sys
import codecs
def myfun(input_file):
p1 = re.compile(ur'-\{.*?(zh-hans|zh-cn):([^;]*?)(;.*?)?\}-')
p2 = re.compile(ur'[(\(][,;。?!\s]*[)\)]')
p3 = re.compile(ur'[「『]')
p4 = re.compile(ur'[」』]')
outfile = codecs.open('std_' + input_file, 'w', 'utf-8')
with codecs.open(input_file, 'r', 'utf-8') as myfile:
for line in myfile:
line = p1.sub(ur'\2', line)
line = p2.sub(ur'', line)
line = p3.sub(ur'“', line)
line = p4.sub(ur'”', line)
outfile.write(line)
outfile.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: python script.py inputfile"
sys.exit()
reload(sys)
sys.setdefaultencoding('utf-8')
input_file = sys.argv[1]
myfun(input_file)
将上述代码保存到exec.py文件,并将该文件放到与数据文件相同的目录,执行命令:
$ python exec.py zh_wiki_00
$ python exec.py zh_wiki_01
这里,我们又得到2个格式化文件:std_zh_wiki_00,std_zh_wiki_01。大小分别为:1021M,36.6M。大小比之前的文件要小,因为修改删除了文件中的符号。
5,中文分词
中文分词工具有很多种, 这里我们使用python版本的结巴分词:https://github.com/fxsjy/jieba
安装很简单:$ pip install jieba
安装好后执行命令进行分词:
python -m jieba -d " " ./std_zh_wiki_00 > ./cut_std_zh_wiki_00
python -m jieba -d " " ./std_zh_wiki_01 > ./cut_std_zh_wiki_01
命令中的-d ” “选项,双引号中是一个空格,指的是以空格分割词汇。
这里,我们又得到2个分词文件:cut_std_zh_wiki_00,cut_std_zh_wiki_01。大小分别为:1.21G,44.6M。比之前的文件要大,因为文件中加入了很多空格符。
6,训练word2vec模型
训练模型我们使用python的gensim库提供的方法,gensim官网。
安装非常简单:$ pip install gensim
接下来,我们用1.21G的大文件进行训练,训练代码也很简单:
from gensim.models import word2vec
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.LineSentence(u'./cut_std_zh_wiki_00')
model = word2vec.Word2Vec(sentences,size=200,window=5,min_count=5,workers=4)
model.save('./word2vecModel/WikiCHModel')
训练的过程进度会打印在控制台。训练结束后我们就得到了一个word2vec模型。
7,调用并测试word2vec模型
调用模型也很简单,同样使用gensim库。
from gensim.models import word2vec
model = word2vec.Word2Vec.load('./word2vecModel/WikiCHModel')
print(model.wv.similarity('奥运会','金牌')) #两个词的相关性
print(model.wv.most_similar(['伦敦','中国'],['北京'])) # 北京is to中国 as 伦敦is to?
1,https://flystarhe.github.io/2016/08/31/wiki-corpus-zh/
2,中英文维基百科语料上的word2vec实验
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。