由于课题任务需要一个繁体中文的word3vec, 折腾经过记录在此。希望以后少掉几个坑。
训练好的embedding放在网盘中, 密码:2um0
后来又按照这个方法训练了简体中文维度分别为50、100、200、300的embedding,一并放出来网盘链接 密码:751d
原文发布于个人博客(好望角),并在博客持续更新。
get wiki
最新的wiki datas下载地址,目前有1.6G大小。
里面的内容以XML格式保存。节点信息如下:
初步处理
直接解压真的太蠢了。
为了节省时间,免去自己写代码处理Wiki的烦恼,Wikipedia Extractor先初步处理。(服务器非root用户,安装命令加上--user
)
git clone https://github.com/attardi/wikiextractor.git wikiextractor
cd wikiextractor
python setup.py install --user
python WikiExtractor.py -b 1024M -o extracted zhwiki-latest-pages-articles.xml.bz2
执行过程如下,可以看到一共处理了1012693篇文章,输出如下所示:
INFO: 6205533 手語新聞
INFO: 6205536 班傑明·古根海姆
INFO: 6205549 同意
INFO: 6205556 2018年荷蘭網路監控法公民投票
INFO: 6205594 李儒新
INFO: 6205610 深圳信息职业技术学院
INFO: 6205626 停下來等著你 (2018年電視劇)
INFO: 6205642 簡單矩陣的快速演算法設計
INFO: 6205644 斯義桂
INFO: 6205646 焦耳效应
INFO: 6205648 1925年世界大賽
INFO: 6205653 True (方力申專輯)
INFO: 6205657 华睿2号
INFO: 6205664 河內郡 (大阪府)
INFO: 6205691 京都寺町三条商店街的福爾摩斯
INFO: 6205675 莫莉·比什死亡事件
INFO: 6205703 都筑郡
INFO: 6205701 皇座法庭所屬分庭庭長
INFO: 6205709 冬瓜餅
INFO: 6205710 吸血鬼莫比亞斯
INFO: 6205712 淘綾郡
INFO: 6205714 明石香織
INFO: Finished 71-process extraction of 1012693 articles in 1114.1s (909.0 art/s)
通过以上抽取后得到两个文件wiki_00
和wiki_01
。里面的格式类似下面
文章内容
在上面的基础上,我们在去掉一些不需要的特殊符号。
import re
import sys
import codecs
def filte(input_file):
p5 = re.compile('')
p6 = re.compile(' ')
outfile = codecs.open('std_' + input_file, 'w', 'utf-8')
with codecs.open(input_file, 'r', 'utf-8') as myfile:
for line in myfile:
line = p5.sub('', line)
line = p6.sub('', line)
outfile.write(line)
outfile.close()
if __name__ == '__main__':
filte(input_file)
input_file = sys.argv[1]
繁体转简体
首先安装opencc-python
网上一大堆教程,全是深坑!其实直接按照代码仓库作者的方法安装就好了。
git clone https://github.com/yichen0831/opencc-python.git
cd opencc-python
python setup.py install --user
但是,如果追求效率,可以安装opencc C++ 版本,python代码的效率堪忧。
看文档不难发现,繁体字也分为香港区和台湾省,要用怎么样的转换看具体需求就好
from opencc import OpenCC
opencc = OpenCC('s2hk')
for filename in ['wiki_01','wiki_00']:
with open('std_'+filename,'r',encoding='utf-8') as fin, open('hk_'+filename,'w',encoding='utf-8') as fou:
for index , line in enumerate(fin.readlines()):
hk = opencc.convert(line)
if index % 10000 == 0:
print(index,hk)
fou.write(hk)
得到了两个文件分别大小为 1024M
和154M
jieba Segment
先把两个wiki文件合并cat hk_wiki_00 hk_wiki_01 > hk_wiki
python -m jieba -d " " ./hk_wiki > ./SegHk_wiki
train word2vec
运行下面写好的脚本,
# -*- coding: utf-8 -*-
from gensim.models import word2vec
from gensim.models import KeyedVectors
import logging
import os
if not os.path.exists('./word2vec_tradiCN/'):
os.makedirs('./word2vec_tradiCN/')
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.LineSentence('./SegHk_wiki')
for number in [50,100,200,300]:
model = word2vec.Word2Vec(sentences,size=number,window=5,min_count=5,workers=20)
# min-count 表示设置最低频率,默认为5,如果一个词语在文档中出现的次数小于该阈值,那么该词就会被舍弃; size代表词词向量的维度
# 为了后续建模读取vector方便,我们的保存格式应该和glove vector 保持一致
model.wv.save_word2vec_format('./word2vec_tradiCN/Wiki'+str(number)+'.txt', binary=False)
然而出现了Intel MKL FATAL ERROR: Cannot load libmkl_avx2.so or libmkl_def.so.
这个错误
运行conda install nomkl
安装nomkl,这是anaconda的问题。
test word2vec
如果用python2,运行下面的测试脚本可能会出现如下错误KeyError: "word '\xe7\xb8\xbd\xe7\xb5\xb1' not in vocabulary"
这个是python2对于中文的支持不太友好造成的,用python3即可表现正常。
# -*- coding: utf-8 -*-
from gensim.models.keyedvectors import KeyedVectors
for number in [50,100,200,300]:
wv = KeyedVectors.load_word2vec_format('./word2vec_tradiCN/Wiki'+ str(number)+'.txt', binary=False)
print(number, wv.similarity('總統','民國')) #两个词的相关性
print(number, wv.most_similar(['倫敦','中國'],['北京']),'\n\n') # 北京is to中国 as 伦敦is to?
- 注意,繁体中文,测试的时候也要用繁体的
- 这里直接测试了四组不同大小的embedding,可以对比效果。以这个简单的测试来说,200d embedding效果比较好。
- 当然,在实际中,效果怎么样,还是要实际测试。
50 0.08906988
50 [('美國', 0.8497380614280701), ('英國', 0.8156374096870422), ('荷蘭', 0.7635571956634521), ('加拿大', 0.7618951201438904), ('蘇格蘭', 0.7564111948013306), ('法國', 0.7498287558555603), ('冰島', 0.7447660565376282), ('愛爾蘭', 0.7290477752685547), ('德國', 0.7261558175086975), ('哥倫比亞', 0.715803861618042)]
100 0.0021609096
100 [('英國', 0.7518529891967773), ('美國', 0.716768741607666), ('蘇格蘭', 0.706271767616272), ('德國', 0.6398693323135376), ('法國', 0.6289862394332886), ('愛爾蘭', 0.6286278963088989), ('荷蘭', 0.6277433633804321), ('英格蘭', 0.625410795211792), ('加拿大', 0.6076068878173828), ('威爾斯', 0.6075741052627563)]
200 0.044366393
200 [('英國', 0.6959728598594666), ('蘇格蘭', 0.6404226422309875), ('美國', 0.6401909589767456), ('英格蘭', 0.6158463358879089), ('愛爾蘭', 0.5740842223167419), ('德國', 0.5558757781982422), ('威爾斯', 0.5539498925209045), ('法國', 0.5375431776046753), ('荷蘭', 0.5276069641113281), ('威爾士', 0.5051602721214294)]
300 0.034565542
300 [('英國', 0.6512337923049927), ('蘇格蘭', 0.5884094834327698), ('英格蘭', 0.5666802525520325), ('美國', 0.5420516729354858), ('愛爾蘭', 0.5202239751815796), ('威爾斯', 0.48060378432273865), ('荷蘭', 0.4763559103012085), ('德國', 0.4744102358818054), ('法國', 0.4675533175468445), ('北愛爾蘭', 0.46320733428001404)]
网盘链接
训练好的四个embedding包含892594个词,都放到了网盘中,可以按需下载。 密码:2um0
参考文献
word2vec实战:获取和预处理中文维基百科(Wikipedia)语料库,并训练成word2vec模型