gensim训练wiki中文词向量

尝试用gensim来做word2vec,之后还会用glove和fasttext进行比较

获得wiki语料

前往维基百科:资料库下载, 点击中文版的下载,下载这份大的文件

pgn

同时安装好需要的gensim包

pip install --upgrade gensim

加载wikiCorpus

下载得到的*.bz2文件可用gensim的WikiCorpus处理 , 能用 get_texts 迭代每一篇文章,return会tokens list ,用空白符将这些tokens连起来,输出到文件中

import jieba
from gensim.corpora import WikiCorpus
import logging
import gensim
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
import os
import opencc
import pandas as pd


wiki_corpus = WikiCorpus('zhwiki-20190301-pages-articles-multistream.xml.bz2',dictionary={})


texts_num = 0

with open("wiki_texts.txt",'w',encoding='utf-8') as output:
    for text in wiki_corpus.get_texts():
        output.write(' '.join(text) + '\n')
        texts_num += 1
        if texts_num % 10000 == 0:
            logging.info("已處理 %d 篇文章" % texts_num)

2019-03-05 16:09:33,270 : INFO : 已處理 10000 篇文章
2019-03-05 16:09:44,983 : INFO : 已處理 20000 篇文章
2019-03-05 16:09:55,364 : INFO : 已處理 30000 篇文章
2019-03-05 16:10:05,647 : INFO : 已處理 40000 篇文章
2019-03-05 16:10:16,333 : INFO : 已處理 50000 篇文章
2019-03-05 16:10:27,058 : INFO : 已處理 60000 篇文章
2019-03-05 16:10:37,406 : INFO : 已處理 70000 篇文章
2019-03-05 16:10:47,663 : INFO : 已處理 80000 篇文章
2019-03-05 16:10:57,842 : INFO : 已處理 90000 篇文章
2019-03-05 16:11:08,534 : INFO : 已處理 100000 篇文章
2019-03-05 16:11:23,814 : INFO : 已處理 110000 篇文章
2019-03-05 16:11:36,572 : INFO : 已處理 120000 篇文章
2019-03-05 16:11:48,758 : INFO : 已處理 130000 篇文章
2019-03-05 16:12:01,798 : INFO : 已處理 140000 篇文章
2019-03-05 16:12:14,960 : INFO : 已處理 150000 篇文章
2019-03-05 16:12:28,018 : INFO : 已處理 160000 篇文章
2019-03-05 16:12:39,979 : INFO : 已處理 170000 篇文章
2019-03-05 16:12:53,159 : INFO : 已處理 180000 篇文章
2019-03-05 16:14:03,707 : INFO : 已處理 190000 篇文章
2019-03-05 16:14:22,805 : INFO : 已處理 200000 篇文章
2019-03-05 16:14:48,809 : INFO : 已處理 210000 篇文章
2019-03-05 16:15:02,737 : INFO : 已處理 220000 篇文章
2019-03-05 16:15:20,026 : INFO : 已處理 230000 篇文章
2019-03-05 16:15:36,802 : INFO : 已處理 240000 篇文章
2019-03-05 16:15:55,332 : INFO : 已處理 250000 篇文章
2019-03-05 16:16:10,842 : INFO : 已處理 260000 篇文章
2019-03-05 16:16:27,951 : INFO : 已處理 270000 篇文章
2019-03-05 16:16:43,592 : INFO : 已處理 280000 篇文章
2019-03-05 16:16:57,202 : INFO : 已處理 290000 篇文章
2019-03-05 16:17:13,944 : INFO : 已處理 300000 篇文章
2019-03-05 16:17:33,537 : INFO : 已處理 310000 篇文章
2019-03-05 16:17:52,000 : INFO : 已處理 320000 篇文章
2019-03-05 16:18:09,145 : INFO : 已處理 330000 篇文章
2019-03-05 16:18:17,044 : INFO : finished iterating over Wikipedia corpus of 334014 documents with 76295909 positions (total 3257644 articles, 90346224 positions before pruning articles shorter than 50 words)






logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

繁体转简体

查看得到的wiki_texts.txt 是由繁体和简体组成的,这样会导致分词的时候会将比如 「数学」與「數學」 被word2vec当成不同的词,因此需要转换,采用opencc

安装opencc

尝试了2种方法都不行

sudo apt-get install opencc
# 能安装,但是会报错初始化错误
# 通过官网下载 https://github.com/BYVoid/OpenCC
cd OpenCC
make && make install 
#报错,解决了cmake 和依赖包还是报错
# 更换之前的版本和换服务器都报错

没办法只能采用 python opencc

发现opencc-python-reimplemented 0.1.4 版本更好,直接

pip install opencc-python-reimplemented

openCC = opencc.OpenCC('t2s')
%%time
nums = 0
ouputs = open('wiki_texts_zg.txt','w',encoding='utf-8')
with open('wiki_texts.txt','r') as f:
 for i in f :
 ouputs.write(openCC.convert(i)+ '\n')
 nums+=1
 if texts_num % 10000 == 0:
 logging.info("已處理 %d 篇文章" % texts_num)
CPU times: user 28min 43s, sys: 5.67 s, total: 28min 49s
Wall time: 28min 49s

速度实在是慢

断词

安装jieba

采用jieba 进行分词 pip install jieba jieba 分词确实很简单

停用词

为什么要去除停用词 ,这里使用的是百度停用词表

举例

1.孔乙己 一到 店 所有 喝酒 的人便 看著他笑

  1. 孔乙己 一到 店 所有 喝酒 人 看著 笑

对于找 的关联词来看,显然第2句的喝酒,看着 更加紧密

stopword_set = set()
with open('baidu_stopword.txt','r', encoding='utf-8') as stopwords:
    for stopword in stopwords:
        stopword_set.add(stopword.strip('\n'))


%%time
output = open('wiki_seg.txt', 'w', encoding='utf-8')
with open('wiki_texts_zg.txt', 'r', encoding='utf-8') as content :
    for texts_num, line in enumerate(content):
        line = line.strip('\n')
        words = jieba.cut(line, cut_all=False)
        for word in words:
            if word not in stopword_set:
                output.write(word + ' ')
        output.write('\n')

        if (texts_num + 1) % 10000 == 0:
            logging.info("已完成前 %d 行的斷詞" % (texts_num + 1))
output.close()

2019-03-06 09:39:44,314 : INFO : 已完成前 10000 行的斷詞
2019-03-06 09:40:46,936 : INFO : 已完成前 20000 行的斷詞
2019-03-06 09:41:43,852 : INFO : 已完成前 30000 行的斷詞
.
.#省略
2019-03-06 10:21:05,301 : INFO : 已完成前 660000 行的斷詞


CPU times: user 43min, sys: 8.15 s, total: 43min 9s
Wall time: 43min 7s

最后得到 wiki_seg.txt 分好词的文本

用gensim的 Word2Vec来训练词向量

核心的程序是 word2vec.Word2Vec()

class gensim.models.word2vec.Word2Vec(sentences=None, size=100, alpha=0.025, window=5, min_count=5, max_vocab_size=None, sample=0.001, seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, cbow_mean=1, hashfxn=<built-in function hash>, iter=5, null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000)

参数说明

sentences:当然了,这是要训练的句子集,没有他就不用跑了
size:这表示的是训练出的词向量会有几维
alpha:机器学习中的学习率,这东西会逐渐收敛到 min_alpha
sg:这个不是三言两语能说完的,sg=1表示采用skip-gram,sg=0 表示采用cbow
window:还记得孔乙己的例子吗?能往左往右看几个字的意思
workers:执行绪数目,除非电脑不错,不然建议别超过 4
min_count:若这个词出现的次数小于min_count,那他就不会被视为训练对象

这里使用默认参数

%%time
from gensim.models import word2vec
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.LineSentence("wiki_seg.txt")
model = word2vec.Word2Vec(sentences, size=250)
#保存模型,供日後使用
model.save("word2vec.model")

#模型讀取方式
# model = word2vec.Word2Vec.load("your_model_name")

2019-03-06 10:55:47,604 : WARNING : consider setting layer size to a multiple of 4 for greater performance
2019-03-06 10:55:47,606 : INFO : collecting all words and their counts
2019-03-06 10:55:47,608 : INFO : PROGRESS: at sentence #0, processed 0 words, keeping 0 word types

2019-03-06 11:01:48,226 : INFO : EPOCH 2 - PROGRESS: at 9.72% examples, 615014 words/s, in_qsize 6, out_qsize 0
2019-03-06 11:01:49,228 : INFO : EPOCH 2 - PROGRESS: at 10.02% examples, 614295 words/s, in_qsize 5, out_qsize 0
2019-03-06 11:01:50,249 : INFO : EPOCH 2 - PROGRESS: at 10.35% examples, 614064 words/s, in_qsize 5, out_qsize 0
.
.#省略
.
2019-03-06 11:17:32,648 : INFO : EPOCH - 5 : training on 158675895 raw words (153653982 effective words) took 245.7s, 625486 effective words/s
2019-03-06 11:17:32,649 : INFO : training on a 793379475 raw words (768269616 effective words) took 1227.4s, 625940 effective words/s
2019-03-06 11:17:32,651 : INFO : saving Word2Vec object under word2vec.model, separately None
2019-03-06 11:17:32,653 : INFO : storing np array 'vectors' to word2vec.model.wv.vectors.npy
2019-03-06 11:17:33,571 : INFO : not storing attribute vectors_norm
2019-03-06 11:17:33,573 : INFO : storing np array 'syn1neg' to word2vec.model.trainables.syn1neg.npy
2019-03-06 11:17:34,351 : INFO : not storing attribute cum_table
2019-03-06 11:17:36,999 : INFO : saved word2vec.model


CPU times: user 1h 2min 24s, sys: 1min 6s, total: 1h 3min 30s
Wall time: 21min 49s

测试模型

这么看来"硕士"还是相似的结果还是可以的

model.most_similar('硕士',topn=20)

/data1/tangx/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Call to deprecated `most_similar` (Method will be removed in 4.0.0, use self.wv.most_similar() instead).
  """Entry point for launching an IPython kernel.





[('硕士学位', 0.7839304208755493),
 ('工商管理', 0.7311581373214722),
 ('学士学位', 0.7111238837242126),
 ('法学硕士', 0.6728358268737793),
 ('哲学博士', 0.6678472757339478),
 ('企管', 0.6472733020782471),
 ('管理学', 0.6467524766921997),
 ('学位', 0.643904447555542),
 ('双学位', 0.6417083740234375),
 ('mba', 0.6414850354194641),
 ('双硕士', 0.6396973133087158),
 ('博士学位', 0.6280169486999512),
 ('硕士文凭', 0.6261978149414062),
 ('emba', 0.6250591278076172),
 ('法学士', 0.6218668222427368),
 ('博士班', 0.6175341010093689),
 ('攻读', 0.6171110272407532),
 ('经营学', 0.6158137321472168),
 ('专业学位', 0.6130814552307129),
 ('商学', 0.6127603054046631)]

测试2个词的余弦相似度

model.similarity('中国','日本')

/data1/tangx/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Call to deprecated `similarity` (Method will be removed in 4.0.0, use self.wv.similarity() instead).
  """Entry point for launching an IPython kernel.





0.42389622

但是"高压锅"的结果就很差了

model.most_similar('高压锅',topn=20)

/data1/tangx/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Call to deprecated `most_similar` (Method will be removed in 4.0.0, use self.wv.most_similar() instead).
  """Entry point for launching an IPython kernel.





[('型砂', 0.8324052691459656),
 ('虫囊菌', 0.8292349576950073),
 ('鱼滑', 0.8289652466773987),
 ('孙儒泳', 0.8285413384437561),
 ('铜熏炉', 0.8280029296875),
 ('迦叶为', 0.8257135152816772),
 ('同服', 0.8253897428512573),
 ('攻毒', 0.8247901201248169),
 ('味杯面', 0.8247039318084717),
 ('notoraja', 0.8243815898895264),
 ('ouachita', 0.8240832090377808),
 ('yanxia', 0.8236766457557678),
 ('测星', 0.8233869075775146),
 ('提帕萨省', 0.8231750130653381),
 ('蔬菜园艺', 0.8220863342285156),
 ('leende', 0.8215625286102295),
 ('龟冈高夫', 0.8215353488922119),
 ('lecanoromycetes', 0.8213621973991394),
 ('范奎', 0.8205204010009766),
 ('林尊贤', 0.820358395576477)]
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值