转自:https://blog.csdn.net/sinat_29957455/article/details/81432846
本篇文章主要介绍如何通过中文维基百科语料库来训练一个word2vec模型。
相关资料下载:
中文维基百科下载地址:https://dumps.wikimedia.org/zhwiki/20180720/
WikiExtractor项目git地址:https://github.com/attardi/wikiextractor
OpenCC项目git地址:https://github.com/BYVoid/OpenCC
中文分词jieba项目git地址:https://github.com/fxsjy/jieba
gensim官网地址:https://radimrehurek.com/gensim/install.html
一、语料库的下载
我下载是zhwiki-20180720-pages-articles.xml.bz2文件,1.5G左右是一个压缩包,下载的时候需要注意文件的名称。
二、语料库文章的提取
下载完成之后,解压缩得到的是一个xml文件,里面包含了许多的文章,也有许多的日志信息。所以,我们只需要提取xml文件里面的文章就可以了。我们通过WikiExtractor来提取xml文件中的文章,它是一个意大利人写的一个Python脚本专门用来提取维基百科语料库中的文章,将每个文件分割的大小为500M,它是一个通过cmd命令来设置一些参数提取文章,提取步骤如下:
a、WikiExtractor的安装
将整个WikiExtractor项目clone或者下载到本地,打开cmd窗口,切换到WikiExtractor项目中的setup.py文件的路径中,执行以下命令安装WikiExtractor
python setup.py install
b、维基百科语料库文章的提取
使用WikiExtractor来提取语料库中的文章,还需要使用到WikiExtractor.py脚本,与setup.py文件在同级目录下,通过以下命令来提取语料库中的文章
python WikiExtractor.py -b 500M -o zhwiki zhwiki-20180720-pages-articles.xml.bz2
参数介绍:
-b,设置提取文章后的每个文件大小
-o,制定输出文件的保存目录
zhwiki-20180720-pages-articles.xml,下载的维基百科语料库文件
更多参数的使用,可以通过以下命令查看:
python WikiExtractor.py -h
使用WikiExtractor提取文章,会在指定目录下产生一个AA的文件夹,里面会包含很多的文件。使用WikiExtractor提取的文章格式如下:
其中省略号表示的就是文章的内容,所以后面我们还需要通过正则化表达式来去除不相关的内容。
c、中文简体和繁体的转换
因为维基百科语料库中的文章内容里面的简体和繁体是混乱的,所以我们需要将所有的繁体字转换成为简体。这里我们利用OpenCC来进行转换。
OpenCC的使用教程请参考:https://blog.csdn.net/sinat_29957455/article/details/81290356
d、正则表达式提取文章内容并进行分词
使用WikiExtractor提取的文章,会包含许多的<doc></doc>,所以我们需要将这些不相关的内容通过正则表达式来去除。然后再通过jieba对文章进行分词,在分词的时候还需要将一些没有实际意义的词进行去除,所以在分词的之后加了一个停用词的去除。将分割之后的文章保存到文件中,每一行表示一篇文章,每个词之间使用空格进行分隔。
-
import logging,jieba,os,re
-
-
def get_stopwords():
-
logging.basicConfig(format=
'%(asctime)s:%(levelname)s:%(message)s',level=logging.INFO)
-
#加载停用词表
-
stopword_set = set()
-
with open(
"../stop_words/stopwords.txt",
'r',encoding=
"utf-8")
as stopwords:
-
for stopword
in stopwords:
-
stopword_set.add(stopword.strip(
"\n"))
-
return stopword_set
-
-
'''
-
使用正则表达式解析文本
-
'''
-
def parse_zhwiki(read_file_path,save_file_path):
-
#过滤掉<doc>
-
regex_str =
"[^<doc.*>$]|[^</doc>$]"
-
file = open(read_file_path,
"r",encoding=
"utf-8")
-
#写文件
-
output = open(save_file_path,
"w+",encoding=
"utf-8")
-
content_line = file.readline()
-
#获取停用词表
-
stopwords = get_stopwords()
-
#定义一个字符串变量,表示一篇文章的分词结果
-
article_contents =
""
-
while content_line:
-
match_obj = re.match(regex_str,content_line)
-
content_line = content_line.strip(
"\n")
-
if len(content_line) >
0:
-
if match_obj:
-
#使用jieba进行分词
-
words = jieba.cut(content_line,cut_all=
False)
-
for word
in words:
-
if word
not
in stopwords:
-
article_contents += word+
" "
-
else:
-
if len(article_contents) >
0:
-
output.write(article_contents+
"\n")
-
article_contents =
""
-
content_line = file.readline()
-
output.close()
-
-
'''
-
将维基百科语料库进行分类
-
'''
-
def generate_corpus():
-
zhwiki_path =
"D:/dataset/NLP/zhwiki/AA"
-
save_path =
"D:/dataset/NLP/zhwiki/AA"
-
for i
in range(
3):
-
file_path = os.path.join(zhwiki_path,str(
"zh_wiki_0%s_jt"%str(i)))
-
parse_zhwiki(file_path,os.path.join(save_path,
"wiki_corpus0%s"%str(i)))
-
e、将分词后的文件合并为一个
将分词后的多个文件合并为一个文件,便于word2vec模型的训练
-
'''
-
合并分词后的文件
-
'''
-
def merge_corpus():
-
output = open(
"D:/dataset/NLP/zhwiki/AA/wiki_corpus",
"w",encoding=
"utf-8")
-
input =
"D:/dataset/NLP/zhwiki/AA"
-
for i
in range(
3):
-
file_path = os.path.join(input,str(
"wiki_corpus0%s"%str(i)))
-
file = open(file_path,
"r",encoding=
"utf-8")
-
line = file.readline()
-
while line:
-
output.writelines(line)
-
line = file.readline()
-
file.close()
-
output.close()
三、word2vec模型的训练
训练word2vec模型的时候,需要使用到gensim库,安装教程请参考官网,通过pip命令就可以进行安装。训练过程需要30分钟到1个小时,具体训练时间与电脑的配置相关。
-
import logging
-
from gensim.models
import word2vec
-
-
def main():
-
logging.basicConfig(format=
"%(asctime)s:%(levelname)s:%(message)s",level=logging.INFO)
-
sentences = word2vec.LineSentence(
"D:/dataset/NLP/zhwiki/AA/wiki_corpus")
-
model = word2vec.Word2Vec(sentences,size=
250)
-
#保存模型
-
model.save(
"model/wiki_corpus.model")
四、word2vec模型的使用
训练完成之后,我们可以利用训练好的模型来做一些词的预测,主要包括三个方面的应用。
1、找出与指定词相似的词
返回的结果是一个列表,列表中包含了制定个数的元组,每个元组的键是词,值这个词语指定词的相似度。
-
import logging
-
from gensim
import models
-
import numpy
as np
-
import matplotlib.pyplot
as plt
-
from wordcloud
import WordCloud
-
-
'''
-
获取一个圆形的mask
-
'''
-
def get_mask():
-
x,y = np.ogrid[:
300,:
300]
-
mask = (x
-150) **
2 + (y
-150)**
2 >
130 **
2
-
mask =
255 * mask.astype(int)
-
return mask
-
-
'''
-
绘制词云
-
'''
-
def draw_word_cloud(word_cloud):
-
wc = WordCloud(background_color=
"white",mask=get_mask())
-
wc.generate_from_frequencies(word_cloud)
-
#隐藏x轴和y轴
-
plt.axis(
"off")
-
plt.imshow(wc,interpolation=
"bilinear")
-
plt.show()
-
-
def test():
-
logging.basicConfig(format=
"%(asctime)s:%(levelname)s:%(message)s",level=logging.INFO)
-
model = models.Word2Vec.load(
"model/wiki_corpus.model")
-
#输入一个词找出相似的前10个词
-
one_corpus = [
"人工智能"]
-
result = model.most_similar(one_corpus[
0],topn=
100)
-
#将返回的结果转换为字典,便于绘制词云
-
word_cloud = dict()
-
for sim
in result:
-
# print(sim[0],":",sim[1])
-
word_cloud[sim[
0]] = sim[
1]
-
#绘制词云
-
draw_word_cloud(word_cloud)
2、计算两个词的相似度
-
# #输入两个词计算相似度
-
two_corpus = [
"腾讯",
"阿里巴巴"]
-
res = model.similarity(two_corpus[
0],two_corpus[
1])
-
print(
"similarity:%.4f"%res)
最后计算出来的相似度有,similarity:0.7241
3、根据前三个词来类比
-
#输入三个词类比
-
three_corpus = [
"北京",
"上海",
"广州"]
-
res = model.most_similar([three_corpus[
0],three_corpus[
1],three_corpus[
2]],topn=
100)
-
#将返回的结果转换为字典,便于绘制词云
-
word_cloud = dict()
-
for sim
in res:
-
# print(sim[0],":",sim[1])
-
word_cloud[sim[
0]]=sim[
1]
-
#绘制词云
-
draw_word_cloud(word_cloud)
五、资源下载地址
git项目下载地址:https://github.com/steelOneself/NLP_learn/tree/master/zhwiki_chinese
git项目中没有包含模型文件,因为模型文件比较大,我上传到百度云了,下载地址:
链接:https://pan.baidu.com/s/1o-7H-0h9fGCsdCyjmxJPUQ 密码:javh
下载后,将解压的模型文件放到项目中的model文件夹中。
小提示:对于百度云下载速度比较慢的同学,可以在浏览器中装一个Tampermonkey插件,然后获取百度云的下载链接,在通过IDM或者迅雷下载可以提高不少的速度。