赞
踩
参考:https://blog.csdn.net/svenhuayuncheng/article/details/78751311
1.获取维基百科语料库资源
https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2下载1.5G左右xml版本
2.抽取文件内容:从原始的xml文件中提取出标题和正文
https://github.com/attardi/wikiextractor
提取文本:命令行进入当前文件夹输入
python WikiExtractor.py -b 500M -o extracted zhwiki-latest-pages-articles.xml.bz2
500M代表提取出来的单个文件最大为500M。这是会产生目录extracted/AA,其中有三个文件分别是wiki_00,wiki_01,wiki_02。
首先在https://bintray.com/package/files/byvoid/opencc/OpenCC下载opencc的windows安装包opencc-1.0.1-win64.7z,并解压放置到自定义的目录下。
opencc -i wiki_00 -o wiki.zh.txt -c t2s.json
-i表示输入文件,-o表示输出文件,
t2s.json
Traditional Chinese to Simplified Chinese 繁體到簡體经过简体化的文档,仍然有很多脏信息。如数字、标点符号、非中文语言字符等,并且文档中的句子是不能用来训练的,需要进行分词处理。 故编写代码,进行非中文字符串的清除,以及分词。
这个博客有整理好的停用词,可以直接拿来做分词用。编码方式为utf-8。
分词及文本清洗的代码如下,此处使用jieba分词工具。
- #encoding:utf8
- import jieba
- import os
- import codecs
- from tqdm import tqdm
-
-
- class MySentences(object):
- def __init__(self, dirname):
- self.dirname = dirname
-
- def __iter__(self):
- for fname in os.listdir(self.dirname):
- for line in open(os.path.join(self.dirname, fname),encoding='utf-8'):
- 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_str
-
-
- def is_uchar(uchar):
- # """判断一个unicode是否是汉字"""
- if u'\u4e00' <= uchar <= u'\u9fff':
- return True
-
- if __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 = 0
- j = 0
- w = 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 += 1
- if i % 10000 == 0:
- j += 1
- w.set_description(u'已分词: %s万个句子'%j)
- f.close()
经过分词之后的文本,大概是这样的:
每一行为一篇文档,每个文档被分为许多词语的组合,且以空格分开。
这里我建立了一个名为‘zh_simplify’的文件夹,里面存放有几个文本文件,代码中迭代地处理这些文件,并将语料都存于最终的一个文档中。 整个清理过程大约40分钟。
经过那么多步骤的预处理,终于得到“干净”的语料,可以开始训练了。
先放训练代码:
- # -*- coding: utf-8 -*-
- import logging
- import multiprocessing
- import codecs
- from tqdm import tqdm
-
- from gensim.models import Word2Vec
- from gensim.models.word2vec import LineSentence
-
- if __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.
即表示:这里一句话 = 一行(用换行符分割),每一句话都经过预处理,并且用空白符分隔。
另外,训练参数的意义如下:
:词向量的维度大小为300维;size越大,需要更多的训练数据,但是效果会更好. 推荐值为几十到几百
:滑动窗口大小为5,即当前词的上下文为前后各两个词
:词频少于5的词被舍弃掉
:多核并行计算,worker参数只有在安装了Cython后才有效. 没有Cython的话, 只能使用单核.
:训练迭代次数,即将语料训练词向量100次
此外,还有一些参数设置:
:用于设置训练算法,默认为0,对应CBOW算法;sg=1,则采用skip-gram算法
:用于设置学习速率
:用于随机数发生器,初始化词向量
:设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
:高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
:如果设置为0(defaut),使用negative sampling;若为1,使用hierarchica softmax技巧
:如果>0,则会采用negative samping,用于设置多少个noise words(负例)
:如果为1(defaut)则对上下文向量求均值进行训练;如果为0,则采用上下文词向量的和;只有使用CBOW的时候才起作用
: hash函数来初始化权重,默认使用python的hash函数
:用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除
:如果为1(default),则在分配word index 的时候会先对单词基于频率降序排序
:表示每一批的传递给线程的单词的数量,默认为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)
训练开始:
经过将近10个小时,终于完成了词向量的训练。
最终得到两个文件,Gensim中默认格式的词向量文件model,以及原始c版本的词向量文件vector。
写一个代码测试下效果吧:
- # encoding:utf8
- import gensim
-
- if __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]))
最终结果如下所示:
上图为‘农业’的词向量。
上图为一些近义词、离群词等的测试效果。
以上,完成了维基百科中文语料训练词向量的全过程。本文旨在做一个实验记录,也是抛砖引玉,欢迎大家共同探讨!
参考:https://blog.csdn.net/svenhuayuncheng/article/details/78751311
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。