尝试用gensim来做word2vec,之后还会用glove和fasttext进行比较
获得wiki语料
前往维基百科:资料库下载, 点击中文版的下载,下载这份大的文件
同时安装好需要的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.孔乙己 一到 店 所有 喝酒 的人便 看著他笑
- 孔乙己 一到 店 所有 喝酒 人 看著 笑
对于找人
的关联词来看,显然第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)]