【不可思议的Word2Vec】 2.训练好的模型
By 苏剑林 | 2017-04-03 | 427454位读者 |由于后面几篇要讲解Word2Vec怎么用,因此笔者先训练好了一个Word2Vec模型。为了节约读者的时间,并且保证读者可以复现后面的结果,笔者决定把这个训练好的模型分享出来,用Gensim训练的。单纯的词向量并不大,但第一篇已经说了,我们要用到完整的Word2Vec模型,因此我将完整的模型分享出来了,包含四个文件,所以文件相对大一些。
提醒读者的是,如果你想获取完整的Word2Vec模型,又不想改源代码,那么Python的Gensim库应该是你唯一的选择,据我所知,其他版本的Word2Vec最后都是只提供词向量给我们,没有完整的模型。
对于做知识挖掘来说,显然用知识库语料(如百科语料)训练的Word2Vec效果会更好。但百科语料我还在爬取中,爬完了我再训练一个模型,到时再分享。
模型概况 #
这个模型的大概情况如下:
$$\begin{array}{c|c}
\hline
\text{训练语料} & \text{微信公众号的文章,多领域,属于中文平衡语料}\\
\hline
\text{语料数量} & \text{800万篇,总词数达到650亿}\\
\hline
\text{模型词数} & \text{共352196词,基本是中文词,包含常见英文词}\\
\hline
\text{模型结构} & \text{Skip-Gram + Huffman Softmax}\\
\hline
\text{向量维度} & \text{256维}\\
\hline
\text{分词工具} & \text{结巴分词,加入了有50万词条的词典,关闭了新词发现}\\
\hline
\text{训练工具} & \text{Gensim的Word2Vec,服务器训练了7天}\\
\hline
\text{其他情况} & \text{窗口大小为10,最小词频是64,迭代了10次}\\
\hline
\end{array}$$
需要特别说明的是:公众号文章属于比较“现代”的文章,反映了近来的网络热点内容,覆盖面也比较广,因此文章相对来说还是比较典型的。对于分词,我用的是结巴分词,并且关闭了新词发现,这是宁可分少一些,也要分准一些。当然,自带的词典是不够的,笔者自己还整理了50万词条,词条来源有两部分:1、网络收集的词典合并;2、在公众号文章上做新词发现,人工筛选后加入到词典中。因此,分词的结果还算靠谱,而且包含了比较多的流行词,可用性较高。
训练代码 #
大家可以参考着改写,要注意,这里引入hashlib.md5是为了对文章进行去重(本来1000万篇文章,去重后得到800万),而这个步骤不是必要的。
#! -*- coding:utf-8 -*-
import gensim, logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
import pymongo
import hashlib
db = pymongo.MongoClient('172.16.0.101').weixin.text_articles_words
md5 = lambda s: hashlib.md5(s).hexdigest()
class sentences:
def __iter__(self):
texts_set = set()
for a in db.find(no_cursor_timeout=True):
if md5(a['text'].encode('utf-8')) in texts_set:
continue
else:
texts_set.add(md5(a['text'].encode('utf-8')))
yield a['words']
print u'最终计算了%s篇文章'%len(texts_set)
word2vec = gensim.models.word2vec.Word2Vec(sentences(), size=256, window=10, min_count=64, sg=1, hs=1, iter=10, workers=25)
word2vec.save('word2vec_wx')
下载链接 #
链接: https://pan.baidu.com/s/1htC495U 密码: 4ff8
包含文件:word2vec_wx, word2vec_wx.syn1neg.npy, word2vec_wx.syn1.npy, word2vec_wx.wv.syn0.npy,4个文件都是Gensim加载模型所必需的。具体每个文件的含义我也没弄清楚,word2vec_wx大概是模型声明,word2vec_wx.wv.syn0.npy应该就是我们所说的词向量表,word2vec_wx.syn1.npy是隐层到输出层的参数(Huffman树的参数),word2vec_wx.syn1neg.npy就不大清楚了~
如果你只关心词向量,也可以下载C版本的格式(跟C版本Word2Vec兼容,只包含词向量):
链接: https://pan.baidu.com/s/1nv3ANLB 密码: dgfw
一些演示 #
主要随便演示一下该模型找近义词的结果。欢迎大家提出改进建议。
>>> import gensim
>>> model = gensim.models.Word2Vec.load('word2vec_wx')>>> pd.Series(model.most_similar(u'微信'))
0 (QQ, 0.752506196499)
1 (订阅号, 0.714340209961)
2 (QQ号, 0.695577561855)
3 (扫一扫, 0.695488214493)
4 (微信公众号, 0.694692015648)
5 (私聊, 0.681655049324)
6 (微信公众平台, 0.674170553684)
7 (私信, 0.65382117033)
8 (微信平台, 0.65175652504)
9 (官方, 0.643620729446)>>> pd.Series(model.most_similar(u'公众号'))
0 (订阅号, 0.782696723938)
1 (微信公众号, 0.760639667511)
2 (微信公众账号, 0.73489522934)
3 (公众平台, 0.716173946857)
4 (扫一扫, 0.697836577892)
5 (微信公众平台, 0.696847081184)
6 (置顶, 0.666775584221)
7 (公共账号, 0.665741920471)
8 (微信平台, 0.661035299301)
9 (菜单栏, 0.65234708786)>>> pd.Series(model.most_similar(u'牛逼'))
0 (牛掰, 0.701575636864)
1 (厉害, 0.619165301323)
2 (靠谱, 0.588266670704)
3 (苦逼, 0.586573541164)
4 (吹牛逼, 0.569260418415)
5 (了不起, 0.565731525421)
6 (牛叉, 0.563843131065)
7 (绝逼, 0.549570798874)
8 (说真的, 0.549259066582)
9 (两把刷子, 0.545115828514)>>> pd.Series(model.most_similar(u'广州'))
0 (东莞, 0.840889930725)
1 (深圳, 0.799216389656)
2 (佛山, 0.786817133427)
3 (惠州, 0.779960036278)
4 (珠海, 0.73523247242)
5 (厦门, 0.72509008646)
6 (武汉, 0.724122405052)
7 (汕头, 0.719602584839)
8 (增城, 0.713532209396)
9 (上海, 0.710560560226)>>> pd.Series(model.most_similar(u'朱元璋'))
0 (朱棣, 0.857951819897)
1 (燕王, 0.853199958801)
2 (朝廷, 0.847517609596)
3 (明太祖朱元璋, 0.837111353874)
4 (赵匡胤, 0.835654854774)
5 (称帝, 0.835589051247)
6 (起兵, 0.833530187607)
7 (明太祖, 0.829249799252)
8 (太祖, 0.826784193516)
9 (丞相, 0.826457977295)>>> pd.Series(model.most_similar(u'微积分'))
0 (线性代数, 0.808522999287)
1 (数学分析, 0.791161835194)
2 (高等数学, 0.786414265633)
3 (数学, 0.758676528931)
4 (概率论, 0.747221827507)
5 (高等代数, 0.737897276878)
6 (解析几何, 0.730488717556)
7 (复变函数, 0.715447306633)
8 (微分方程, 0.71503329277)
9 (微积分学, 0.704192101955)>>> pd.Series(model.most_similar(u'apple'))
0 (banana, 0.79927945137)
1 (pineapple, 0.789698243141)
2 (pen, 0.779583632946)
3 (orange, 0.769554674625)
4 (sweet, 0.721074819565)
5 (fruit, 0.71402490139)
6 (pie, 0.711439430714)
7 (watermelon, 0.700904607773)
8 (apples, 0.697601020336)
9 (juice, 0.694036960602)>>> pd.Series(model.most_similar(u'企鹅'))
0 (海豹, 0.665253281593)
1 (帝企鹅, 0.645192623138)
2 (北极熊, 0.619929730892)
3 (大象, 0.618502140045)
4 (鲸鱼, 0.606555819511)
5 (猫, 0.591019570827)
6 (蜥蜴, 0.584576964378)
7 (蓝鲸, 0.572826981544)
8 (海豚, 0.566122889519)
9 (猩猩, 0.563284397125)>>> pd.Series(model.most_similar(u'足球'))
0 (篮球, 0.842746257782)
1 (足球运动, 0.819511592388)
2 (青训, 0.793446540833)
3 (排球, 0.774085760117)
4 (乒乓球, 0.760577201843)
5 (足球赛事, 0.758624792099)
6 (棒垒球, 0.750351667404)
7 (篮球运动, 0.746055066586)
8 (足球队, 0.74296438694)
9 (网球, 0.742858171463)>>> pd.Series(model.most_similar(u'爸爸'))
0 (妈妈, 0.779690504074)
1 (儿子, 0.752222895622)
2 (奶奶, 0.70418381691)
3 (妈, 0.693783283234)
4 (爷爷, 0.683066487312)
5 (父亲, 0.673043072224)
6 (女儿, 0.670304119587)
7 (爸妈, 0.669358253479)
8 (爸, 0.663688421249)
9 (外婆, 0.652905225754)>>> pd.Series(model.most_similar(u'淘宝'))
0 (淘, 0.770935535431)
1 (店铺, 0.739198565483)
2 (手机端, 0.728774428368)
3 (天猫店, 0.725838780403)
4 (口令, 0.721312999725)
5 (登录淘宝, 0.717839717865)
6 (淘宝店, 0.71473968029)
7 (淘宝搜, 0.697688698769)
8 (天猫, 0.690212249756)
9 (网店, 0.6820114851)
转载到请包括本文地址:https://kexue.fm/archives/4304
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Apr. 03, 2017). 《【不可思议的Word2Vec】 2.训练好的模型 》[Blog post]. Retrieved from https://kexue.fm/archives/4304
@online{kexuefm-4304,
title={【不可思议的Word2Vec】 2.训练好的模型},
author={苏剑林},
year={2017},
month={Apr},
url={\url{https://kexue.fm/archives/4304}},
}
October 9th, 2017
博主你好,请教下词典收集到后,词频是怎么给的?直接把文章里的词数当做词典里的词频吗?另外词典方便共享下吗~
词频人工想象(因为个别词的词频不是很重要),或者根据语料去统计(有个EM的思路,就是先假设都是1,然后用它来对语料分词,然后统计词频,然后更新所有词的词频,然后继续用新词典分词,再统计,更新~如此迭代)
October 16th, 2017
苏老师,你这个pymongo.MongoClient('172.16.0.101').weixin.text_articles_words执行不出来,请问有其他方式可以得到这个语料吗,谢谢苏老师
没有。你要自己收集语料,自己分词,自己读取。这是个demo,demo,demo!!不是用来直接跑的。
好的,谢谢苏老师
October 25th, 2017
苏老师,那个包含文件:word2vec_wx,的下载链接打不开了,能麻烦您再分享一次吗?谢谢
我现在测试还可以
October 27th, 2017
博主你好,请问word2vec一般多少文章才能得出基本的数据,我用了2万篇,60M的txt,却连一个数据都没有.是不是这个量低于要求的最低标准?或者我的脚本错了?
我不大清楚你的“一个数据都没有”是什么意思。
我试过十几M的文件都可以训练一个像模像样的结果出来,所以估计是你脚本问题。
November 8th, 2017
请问下,按照你的方法训练得到的模型为什么最终只有一个文件,而不是你上面说的四个
November 20th, 2017
苏老师,看了您的文章受益匪浅,我有一个问题想问一下,您是做的中文训练,如果我想改成英文的话,第一篇文章的训练集应该怎么改?抱歉,新手入门,确实问题有点浅显,望您赐教
一样的呀,还是分词,然后写这么一个迭代器,然后训练。
November 22nd, 2017
尊敬的苏老师,我按照您的代码尝试的时候,python没有报错,但是不显示结果。请问该怎么处理?谢谢!
import gensim
import pandas as pd
model = gensim.models.Word2Vec.load('d:\word2vec_wx')
pd.Series(model.most_similar(u'微信'))
我自己解决了,哈哈,不用麻烦苏老师了。
December 5th, 2017
博主你好,非常感谢你的分享。在我的运行过程中出现了一个问题,特来请教。
我利用new_model = gensim.models.Word2Vec.load('word2vec_wx')加载模型的时候,pycharm提示‘Process finished with exit code -1073741819 (0xC0000005)’。利用python自带的IDLE时,会自己restart shell。
请问是什么原因?谢谢。
在原生python窗口试试?(cmd窗口,输入python,回车)
没遇到过你这个问题~
很可能是版本的问题,或者32位和64位的问题。
这位兄台,问题解决了么?
确定了,一开始使用的是python3,出现如上所述的问题,然后换了pathon2.7,结果出现MemoryError,后来换成64位的2.7版本就OK,搞了一下午加一晚上到凌晨1点半。。。
感谢提供解决方案。辛苦了。
December 18th, 2017
how to resolve?thanks
January 14th, 2018
博主您好,非常感谢您的分享。我现在想在您训练模型的基础上在结合自己的文本进行二次训练,步骤如下:
model_1 = word2vec.Word2Vec.load('/home/martin/word2vec2/word2vec_wx')#加载您的模型
model_1.build_vocab(new_sentences, update = True)
trainedWordCount = model_1.train(new_sentences, total_examples = model_1.corpus_count, epochs = model_1.iter)
但是在训练的是会报异常:AttributeError: 'Word2Vec' object has no attribute 'compute_loss'。
当我自己用自己的数据进行训练得到模型,再加入新的训练文本进行增量训练的时候并没有出现这个问题,比较顺利。(利用的也是gensim下的word2vec)
请问您是否了解是什么原因?谢谢!
据我所知,gensim的word2vec支持增量训练,但应该不支持重新build_vocab的?我不知道新版本有没有更新。你要不直接试试
model_1 = word2vec.Word2Vec.load('/home/martin/word2vec2/word2vec_wx')
model_1.train(new_sentences)
谢谢您的回复!
build_vocab加不加对于的效果是一样的,因为并不支持新词的加入,但是原本词语的向量表示会进行更新(通过利用我自己训练的模型,进而进行增量训练,验证所得)
model_1.train(new_sentences)会报错,total_examples、epochs是必须要赋值。
你好,请教下哈,我用build_vocab增加了一些新数据的词,但是有一些词没有更新到word2vec的词典里,不知道是什么原因。关于相似词,除了word2vec,你有更好的方法可以增量训练吗