中文维基百科语料库词向量的训练
要通过计算机进行自然语言处理,首先就需要将这些文本数字化。目前用得最广泛的方法是词向量,根据训练使用算法的不同,目前主要有 Word2Vec 和 GloVe 两大方法,本文主要讲述通过这两个方法分别训练中文维基百科语料库的词向量。
获取并处理中文维基百科语料库
下载
中文维基百科语料库的下载链接为:https://dumps.wikimedia.org/zhwiki/, 本试验下载的是最新的zhwiki-latest-pages-articles.xml.bz2。这个压缩包里面存的是标题、正文部分,该目录下还包括了其他类型的语料库,如仅包含标题,摘要等。
抽取内容
Wikipedia Extractor 是一个开源的用于抽取维基百科语料库的工具,由python写成,通过这个工具可以很容易地从语料库中抽取出相关内容。使用方法如下:
1 | $ git clone https://github.com/attardi/wikiextractor.git wikiextractor |
由于这个工具就是一个python脚本,因此无需安装,-b
参数指对提取出来的内容进行切片后每个文件的大小,如果要将所有内容保存在同一个文件,那么就需要把这个参数设得大一下,-o
的参数指提取出来的文件放置的目录,抽取出来的文件的路径为zhwiki_extract/AA/wiki_00
。更多参数可参考其github主页的说明。
抽取后的内容格式为每篇文章被一对<doc> </doc>
包起来,而<doc>
中的包含了属性有文章的id、url和title属性,如<doc id="13" url="https://zh.wikipedia.org/wiki?curid=13" title="数学">
。
繁简转换
由上一步提取出来的中文维基百科中的语料中既有繁体字也有简体字,这里需要将其统一变为简体字,采用的工具也是开源的 OpenCC 转换器。使用方法如下:
1 | $ git clone https://github.com/BYVoid/OpenCC.git |
我使用的是
centos,yum源中找不到这个软件,因此通过编译安装最新的版本,需要注意的是编译OpenCC
要求gcc的版本最低为 4.6 。其中 -i
表示输入文件路径,
-o
表示输出的文件
,-c
表示转换的配置文件,这里使用的繁体转简体的配置文件,OpenCC自带了一系列的转换配置文件,可参考其github主页的说明。
去除标点符号
去除标点符号有两个问题需要解决,一是像下面这种为了解决各地术语名称不同的问题
1
他的主要成就包括Emacs及後來的GNU Emacs,GNU C 編譯器及-{zh-hant:GNU 除錯器;zh-hans:GDB 调试器}-。
另外一个就是将所有标点符号替换成空字符,通过正则表达式均可解决这两个问题,下面是具体实现的python代码。
1 | #!/usr/bin/python |
分词
经过上面的步骤基本得到了都是简体中文的纯净文本,下面需要对其进行分词并且整理成每行一篇文本的格式,从而方便后续的处理。
分词采用 python 的分词工具 jieba,通过
pip install jieba
安装即可。且将一篇文章分词后的结果存储在一行,由前面可知,每篇文章存储在一对<doc></doc>
标签中,由于前面去掉了标点,所以现在变成了doc doc
,所以只要判断当前行为doc
时即可认为文章结束,从而开始在新的一行记录下一篇文章的分词结果。实现的python代码如下:
1 | #!/usr/bin/python |
通过 Word2Vec 训练词向量
Word2vec中包含了两种训练词向量的方法:Continuous Bag of Words(CBOW)和Skip-gram。CBOW的目标是根据上下文来预测当前词语的概率。Skip-gram刚好相反,根据当前词语来预测上下文的概率。这两种方法都利用人工神经网络作为它们的分类算法。起初,每个单词都是一个随机N维向量。训练时,该算法利用CBOW或者Skip-gram的方法获得了每个单词的最优向量。
最初 Google 开源的 Word2Vec 是用C来写的,后面陆续有了Python ,Java 等语言的版本,这里采用的是 Python 版本的 gensim。通过 gensim 提供的 API 可以比较容易地进行词向量的训练。gensim的建议通过conda安装,步骤如下:
1 | $ wget https://repo.continuum.io/archive/Anaconda2-4.1.1-Linux-x86_64.sh |
Linux 系统一般原来会带有 python,直接执行 python
命令可能会调用系统内置的 python 解释器,因此如果要使用conda安装的
python, 执行 python 命令的时候需要输入指定其通过 conda
安装的完整目录,或者将这个路径添加在环境变量$PATH
之前。
下面是对上面处理后的语料库进行训练的一个简单例子。
1 | #!/usr/bin/python |
上面的训练过程首先将输入的文件转为 gensim 内部的 LineSentence 对象,要求输入的文件的格式为每行一篇文章,每篇文章的词语以空格隔开。
然后通过 gensim.models.Word2Vec
初始化一个 Word2Vec
模型,size
参数表示训练的向量的维数;min_count
表示忽略那些出现次数小于这个数值的词语,认为他们是没有意义的词语,一般的取值范围为(0,100);sg
表示采用何种算法进行训练,取0时表示采用CBOW模型,取1表示采用skip-gram模型;workers
表示开多少个进程进行训练,采用多进程训练可以加快训练过程,这里开的进程数与CPU的核数相等。
最后将训练后的得到的词向量存储在文件中,存储的格式可以是 gensim
提供的默认格式(save
方法),也可以与原始c版本word2vec的
vector 相同的格式(save_word2vec_format
方法),加载时分别采用
load
方法和 load_word2vec_format
方法即可。更详细的API可参考
https://rare-technologies.com/word2vec-tutorial/ 和
http://radimrehurek.com/gensim/models/word2vec.html。
假设我们训练好了一个语料库的词向量,当一些新的文章加入这个语料库时,如何训练这些新增的文章从而更新我们的语料库?将全部文章再进行一次训练显然是费时费力的,gensim提供了一种类似于“增量训练”的方法。即可在原来的model基础上仅对新增的文章进行训练。如下所示为一个简单的例子:
1 | model = gensim.models.Word2Vec.load(exist_model) |
上面的代码先加载了一个已经训练好的词向量模型,然后再添加新的文章进行训练,同样新增的文章的格式也要满足每行一篇文章,每篇文章的词语通过空格分开的格式。这里需要注意的是加载的模型只能
是通过model.save()
存储的模型,从model.save_word2vec_format()
恢复过来的模型只能用于查询.
通过 Glove 训练词向量
除了上面的 Word2Vec ,通过 Glove 也可以训练出词向量,只是这种方法并没有 Word2Vec 用得那么广泛。这里简单提及,也算是为训练词向量提供多一个选择。
首先需要下载并编译 Glove,步骤如下: 1
2
3$ wget http://www-nlp.stanford.edu/software/GloVe-1.2.zip
$ unzip Glove-1.2.zip
$ cd Glove-1.2 && make
编译后会在 Glove-1.2
目录下生成一个 build
目录,里面包含了训练需要用到的工具。目录结构如下所示: 1
2
3
4
5build/
|-- cooccur
|-- glove
|-- shuffle
`-- vocab_count
训练过程总共分为四步,对应上面的四个工具,顺序依次为vocab_count --> cooccur --> shuffle --> glove
,下面是具体的训练过程
1 | $ build/vocab_count -min-count 5 -verbose 2 < zhs_wiki_cutwords > zhs_wiki_vocab |
上面四条命令分别对应于训练的四个步骤,每个步骤含义如下
vocab_count
从语料库(zhs_wiki_cutwords
是上面第一步处理好的语料库)中统计词频,输出文件zhs_wiki_vocab
,每行为词语 词频
;-min-count 5
指示词频低于5的词舍弃,-verbose 2
控制屏幕打印信息的,设为0表示不输出cooccur
从语料库中统计词共现,输出文件zhs_wiki_cooccurence.bin
,格式为非文本的二进制;-memory 4.0
指示bigram_table
缓冲器,-vocab-file
指上一步得到的文件,-verbose 2
同上,-window-size 5
指示词窗口大小。shuffle
对zhs_wiki_cooccurence.bin
重新整理,输出文件zhs_wiki_shuff.bin
glove
训练模型,输出词向量文件。-save-file
、-threads
、-input-file
和-vocab-file
直接按照字面应该就可以理解了,-iter
表示迭代次数,-vector-size
表示向量维度大小,-binary
控制输出格式0: save as text files; 1: save as binary; 2: both
训练后得到的二进制词向量模型格式与原始c版本word2vec的 vector 格式也相同,可以通过下面的方法统一加载使用。
使用词向量模型
训练好的词向量可以供后续的多项自然语言处理工作使用,下面是通过 gensim 加载训练好的词向量模型并进行查询的例子
1 | # 加载模型 |
这里并没有对训练出来的词向量质量进行评估,虽然 Google
提供了一种测试集,约20000句法和语义的测试实例(questions-words.txt),检查如A对于B类似C对于D
这种线性平移关系。由于测试集是英文的,因此可以考虑翻译过来然后对中文的采用同样的评估方法,但是实际的效果还是要看具体应用中的效果。
参考: https://flystarhe.github.io/2016/09/04/word2vec-test/ https://flystarhe.github.io/2016/08/31/wiki-corpus-zh/ http://radimrehurek.com/gensim/models/word2vec.html https://rare-technologies.com/word2vec-tutorial/