用维基百科训练word2vec中文词向量

主要参考:

https://blog.csdn.net/weixin_40547993/article/details/97781179

https://www.kaggle.com/jeffd23/visualizing-word-vectors-with-t-sne

其他的可能还有一些,查阅的时候没注意,后来找不到了(⊙﹏⊙)

 

本文使用的语料库是维基百科中文语料库截至2019-07-20的数据,下载链接:https://dumps.wikimedia.org/zhwiki/20190720/

我已经保存在网盘里,有需要的可以直接提取:链接:https://pan.baidu.com/s/1IYZPD2B6BZCE3nlXfSjK2A 提取码:e1wf

 

进入具体步骤之前,先梳理一下大致步骤,以便大脑中先有个大致思路:

  • step1:利用gensim的WikiCorpus处理工具对下载的xml压缩文件进行txt格式转换,转换后的文件每行是一篇维基文档
  • step2:对语料库进行预处理,主要包括:繁体字转简体字,去除汉字以外其他字符,分词
  • step3:利用gensim的LineSentence训练词向量

以上三个步骤后,词向量就训练完成啦,得到词向量以后,为了验证词向量的质量,我们可以测试一些词语的近义词,对词向量可视化

 

1.将.xml文件转为.text格式文件,.text格式文件中,一行是一篇文章

from gensim.corpora import WikiCorpus# 这是gensim专门为处理维基百科数据的工具包
input_file_name = '/Users/admin/A_NLP/data/zhwiki-20190720-pages-articles-multistream.xml.bz2'
output_file_name = 'wiki.cn.txt'
input_file = WikiCorpus(input_file_name, lemmatize=False, dictionary={})
output_file = open(output_file_name, 'w', encoding="utf-8")
count = 0
for text in input_file.get_texts():
    output_file.write(' '.join(text) + '\n')
    count = count + 1
    if count % 10000 == 0:
        print('目前已处理%d条数据' % count)
input_file.close() output_file.close()

2.打印处理成txt文件后的第一行数据查看:

ff = open('')
for line in ff:
    print(line)
    break

 

可以看到,上述文件中的字符许多繁体字,且其中掺杂一些英文或其他字符,因此需要对语料再进行一些预处理

3.将语料库 按行进行,繁转简、清洗、分词:

  • 繁转简使用的是opencc工具;
  • 清洗非中文数据是使用正则表达式直接提取中文字符;
  • 分词则是使用jieba分词工具
import re
import opencc
import jieba
cc = opencc.OpenCC('t2s')
fr = open('wiki.cn.txt','r')
fw = open('wiki.sen.txt','a+')
for line in fr:
    simple_format = cc.convert(line)# 繁转简
    zh_list = re.findall(u"[\u4e00-\u9fa5]+",simple_format)# 清洗掉非中文数据
    sentence = []
    for short_sentence in zh_list:
        sentence += list(jieba.cut(cc.convert(short_sentence)))# 分词
    fw.write(' '.join(sentence)+'\n')
fr.close()
fw.close()

4.打印出处理完的文件的第一行查看

ft = open('wiki.sen.txt','r')
for line in ft:
    print(line)
    break 

5.训练词向量并保存模型:利用LineSentence对行文件进行读取,再放入Word2Vec中进行向量训练

以下参考其他大佬的文章给出word2vec参数说明(原文链接:https://blog.csdn.net/weixin_40547993/article/details/97781179): 

在gensim中,word2vec相关的API都在包gensim.models.word2vec中。和算法有关的参数都在类gensim.models.word2vec.Word2Vec中。

  • sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。
  • size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。
  • window:即词向量上下文最大距离,这个参数在我们的算法原理篇中标记为,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。如果是小语料则这个值可以设的更小。对于一般的语料这个值推荐在[5,10]之间。
  • sg: 即我们的word2vec两个模型的选择了。如果是0,则是CBOW模型,是1则是Skip-Gram模型,默认是0即CBOW模型。
  • hs: 即我们的word2vec两个解法的选择了,如果是0, 则是Negative Sampling,是1的话并且负采样个数negative大于0, 则是Hierarchical Softmax。默认是0即Negative Sampling。
  • negative:即使用Negative Sampling时负采样的个数,默认是5。推荐在[3,10]之间。这个参数在我们的算法原理篇中标记为neg。
  • cbow_mean: 仅用于CBOW在做投影的时候,为0,则算法中的为上下文的词向量之和,为1则为上下文的词向量的平均值。
  • min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。
  • iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
  • alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为,默认是0.025。
  • min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。
  • worker:训练词向量使用时使用的线程数,默认为3。
import multiprocessing
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

input_file_name = 'wiki.sen1k.txt'
model_file_name = 'wiki_min_count500.model'

model = Word2Vec(LineSentence(input_file_name),# LineSentence函数可以将保存为行-文档格式的语料转换成WordVec需要的格式
                 size=100,  # 词向量长度
                 window=5,
                 min_count=500,
                 workers=multiprocessing.cpu_count())

model.save(model_file_name)

6.测试几个词语,找出与其最相似的10个词语

from gensim.models import Word2Vec
 
wiki_model = Word2Vec.load('wiki_min_count500.model')
 
test = ['文学', '雨水', '汽车', '怪物', '几何','故宫']
for word in test:
    res = wiki_model.most_similar(word)
    print(word)    
    print(res)

7.查看词向量

wiki_model.wv['文学']

8.向量可视化,利用TSNE工具,将词向量降维,降维的原理是使得原本距离相近的向量降维后距离尽可能近,原本距离较远的向量降维后距离尽可能远。

这个步骤参考了kaggle上的词向量可视化文档:

from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
%matplotlib inline
def tsne_plot(model):
    "Creates and TSNE model and plots it"
    labels = []
    tokens = []

    for word in model.wv.vocab:
        tokens.append(model[word])
        labels.append(word)
    
    tsne_model = TSNE(perplexity=40, n_components=2, init='pca', n_iter=2500, random_state=23)
    new_values = tsne_model.fit_transform(tokens)

    x = []
    y = []
    for value in new_values:
        x.append(value[0])
        y.append(value[1])
        
    plt.figure(figsize=(16, 16)) 
    for i in range(len(x)):
        plt.scatter(x[i],y[i])
        plt.annotate(labels[i],
                     xy=(x[i], y[i]),
                     xytext=(5, 2),
                     textcoords='offset points',
                     ha='right',
                     va='bottom')
    plt.show()
wiki_model = Word2Vec.load('wiki_min_count500.model')
tsne_plot(wiki_model)

 

 第一张图是用所有语料训练处的模型,包含的词语较多,因此成了一个大墨团;由于matplotlib模块的SimHei.ttf文件没有替换,因此中文文字没有显示出来

 

 

 

第二张图使用了预处理后的前1w行数据作为语料库训练,在以下位置替换掉了SimHei.ttf文件,

(以下是matplotlib不能显示中文的解决办法)

  • 下载Github仓库中的字体SimHei.ttf;
  •  在命令行中执行:

    python

    import matplotlib

    print(matplotlib.__path__)

    这样就找到了matplotlib 的路径,然后 cd 到这个路径。 cd 到这个路径之后,继续 cd,cd 到 mpl-data/fonts/ttf 这个路径。 然后把 `DejaVuSans.ttf` 这个文件换成SimHei.ttf:

    mv SimHei.ttf DejaVuSans.ttf

这样就可以在matplotlib中显示中文了。

 

以下是向量可视化效果图:

 

 为了看的更清晰一点,第三章图使用的是预处理后的前1000行数据作训练,效果如下:

完。

 

posted @ 2019-08-04 22:52  Byu  阅读(1744)  评论(0编辑  收藏  举报