词向量与word2vec分析

来源:互联网 发布:java游戏地下城与勇士 编辑:程序博客网 时间:2024/05/29 17:11

0x00.前言

(原文发表在博客,欢迎访问

前一阵子参加了科赛的一个数据的比赛,涉及了自然语言处理(nlp)。所以写一个总结,解释一下词向量(word embedding)、word2vec模型以及词向量的构造。

0x01.词向量

就像图片编码处理后进行模型训练一样,我们也要对文本进行处理,把它抽象为一个矩阵或者向量。通常我们处理的不是一段话、一个句子,而是一个单词或词语。对其进行处理的目的是将单词或词语转化为对计算机友好的数据格式,我们把处理后的向量叫做词向量或词嵌入。

对词语的处理有两种方法,一种是将词语映射为一个独一无二的稀疏矩阵,类似于它的编号,这种方法叫做One-hot Representation。但是这种方法存在着“词汇鸿沟”现象与维度灾难。词汇鸿沟是指,单纯的看两个词语的特征向量,我们发现不了它们的任何联系,任何两个词语间都是孤立的。但是我们知道,看到两个词语的时候,我们可以清楚的认识到两个单词间的联系。

另一种方法是叫做distributed Representations,将单词抽象为词向量,每个词语都由一个多维的特征向量表示,我们可以通过计算余弦相似度比较两个词语间的联系。词向量的训练过程是无监督学习过程,我们只需要提供语料,比较流行的算法模型是word2vec。

0x02.word2vec及其模型

word2vec算法有两种重要模型Skip-gram(Continuous Skip-gram Model)与CBOW(Continuous Bag-of-Words Model),两个算法的区别是前者利用一个单词预测其上下文单词,而后者正相反,是从词语已知上下文中预测这一词语。

对于Skip-gram与CBOW模型,word2vec给出了两套实现框架,分别是Hierarchial Softmax和Negative Sampling。两种框架的区别在于,前者使用利用词语出现次数构造的哈夫曼树计算频率,而后者使用随机负采样,目的是提高训练速度与改善词向量质量。

对于CBOW模型,已知词语上下文Context(w)与词语w,目标函数可得如下对数似然函数:

而Skip-gram模型输入输出正相反,其目标函数为:

根据框架选择的不同,利用哈夫曼树或随机负采样可以得到概率,之后带入目标函数。

得到对数似然函数采用梯度下降法使其最大化。进行梯度计算及更新公式(学习率)。

0x03.使用gensim构造词向量

python没有叫做word2vec的库,我们使用得是gensim库。gensim在python中只实现了skip-gram算法,不过这并不影响我们使用。

1.语料收集

这里我的语料来自于题目所给的数据。有如下几个步骤

  1. 取出所有的字符
  2. 对符号、字母等过滤,得到只有汉字的一个txt文件
  3. 使用jieba对其进行分词,以空格相间

1) 字符清理

只保留汉字就可以了。

#coding:utf-8import osimport re# 输入文件 与 输出文件output = open('output2.txt', 'w')inp = open('log2.txt', 'r')# 按行读取文件for line in inp.readlines():    # 正则过滤    #ss = re.findall('[^\d\n\s*\r\u4e00-\u9fa5]', line)    p = re.compile(ur'[\u4e00-\u9fa5]+')    #ss = re.findall('[^a-zA-Z]', line)    ss = p.findall(unicode(line, "utf-8"))    # 写入输出文件    output.write("".join(ss).encode("utf-8"))    output.write('\n')# 关闭文件inp.close()output.close()

2) jieba分词

jieba对汉语分词效果很好,想要进一步了解可以查看官方文档。

#coding:utf-8import jieba# 多线程、本机支持不好就禁用了#jieba.enable_parallel()# 相邻词语间隔space = ' '# 输入文件 与 输出文件output = open('words.txt', 'w')inp = open('output.txt', 'r')for line in inp.readlines():    # jieba分词    seg_list = jieba.cut(line)    # 写入输出文件    output.write(space.join(seg_list) + '\n')# 关闭文件inp.close()output.close()

2.训练模型

#coding:utf-8import loggingimport os.pathimport sysimport multiprocessingfrom gensim.corpora import WikiCorpusfrom gensim.models import Word2Vecfrom gensim.models.word2vec import LineSentence# 输入文件inp = 'words3.txt'outp1 = 'web_words.model'outp2 = 'web_words.vector'# Word2Vec函数的参数:# size 表示特征向量维度,默认100# window 表示当前词与预测词在一个句子中的最大距离# min_count 词频少于min_count次数的单词会被丢弃掉, 默认值为5model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5,\                     workers=multiprocessing.cpu_count())# 默认格式modelmodel.save(outp1)# 原始c版本modelmodel.wv.save_word2vec_format(outp2, binary=False)

3.基本使用

训练好模型进行的小测试,感觉很不错。

#coding:utf-8import gensim# 编码格式import sysreload(sys)sys.setdefaultencoding('utf-8')# 加载模型model = gensim.models.Word2Vec.load('web_words.model')# 特征向量维度size = model.vector_size# 单词的向量v = model[u'少女']print sizeprint v

输出:

400[  8.43580186e-01  -9.96889651e-01  -7.99913585e-01  -4.39080328e-01   1.77503848e+00   1.29446602e+00  -1.52770126e+00   1.51806796e+00  -7.54987478e-01   2.55844021e+00   7.50788331e-01   3.79817247e-01  -3.28724474e-01   2.10721001e-01   1.66165423e+00  -1.33865356e-01  -5.39526880e-01  -4.30585086e-01   1.06060803e+00  -3.13318431e-01   3.54138672e-01   5.72560787e-01   9.99186516e-01   1.33570850e+00  -2.47879148e-01   1.30511200e+00   8.60800505e-01  -7.64900982e-01   1.26472020e+00   8.23687077e-01   3.07441205e-01  -7.32565522e-01   4.31946605e-01  -8.97184789e-01  -2.72827983e-01   1.64680278e+00  -9.39997792e-01  -1.68242455e+00   3.67325902e-01  -1.03376389e-01   1.15108991e+00   1.31034935e+00  -2.02769589e+00  -6.89099431e-01  -1.51745272e+00  -8.21902156e-01  -1.76097643e+00  -4.95533198e-01   1.21536779e+00  -1.40373683e+00  -1.36783874e+00   1.69045836e-01   5.21723509e-01  -6.93929017e-01   8.98100674e-01  -3.01276743e-01   4.29140925e-01  -8.04761231e-01   3.44539672e-01  -2.78323054e-01   7.61275738e-02  -7.97224462e-01  -4.74477857e-01  -1.58943701e+00   1.73392504e-01   1.54953849e+00  -1.43597603e+00  -5.84415853e-01   1.11646068e+00   7.99975395e-02   1.73107982e-01   1.03152871e+00  -1.42563516e-02  -2.74376720e-01   9.66395199e-01  -1.08919930e+00   1.20555353e+00  -7.49185562e-01  -5.16100824e-01   6.94500446e-01  -2.00204790e-01   3.70599806e-01   9.45616603e-01   1.78066242e+00  -2.31012732e-01   2.18667269e+00  -7.55105376e-01   1.20586944e+00  -1.84096193e+00   1.47042429e+00  -1.54893851e+00   2.14809775e-01  -9.05168414e-01  -8.84964705e-01   1.00996995e+00   6.90825358e-02  -1.17379665e+00  -8.71409893e-01  -2.98106521e-01  -4.36888635e-01   5.83857417e-01   2.00399256e+00  -3.39457452e-01   5.74710071e-01  -5.80044925e-01   1.25820243e+00  -6.68906450e-01  -2.27513528e+00  -1.95195866e+00  -1.39131975e+00   7.28424013e-01  -6.16876185e-01   9.51394796e-01   6.15295470e-01  -1.00253403e+00   9.03217912e-01   6.12991191e-02   2.91212648e-02  -7.35920072e-01   8.58711898e-01   1.68337727e+00   3.14759016e-01  -3.84985417e-01   1.23079610e+00   7.63045177e-02  -1.86154455e-01   9.24728036e-01  -1.63472295e+00  -1.45414364e+00  -1.97648728e+00   1.16380000e+00   1.79543650e+00  -3.13000560e+00   1.63300264e+00   1.32793307e+00   1.16838443e+00   1.72551259e-01  -5.13504028e-01   8.05045187e-01  -5.61231613e-01  -2.12595153e+00  -8.84528279e-01   1.26554120e+00   1.08733094e+00  -9.27044630e-01  -4.26214278e-01   8.35291803e-01  -6.07960582e-01  -8.45824718e-01   9.59472060e-01   6.95870042e-01  -3.91528457e-01   1.57924187e+00   9.34813440e-01   8.38734150e-01  -1.40014827e+00  -2.92787887e-02   8.75473201e-01  -5.84763288e-01  -1.99537560e-01   9.13132668e-01   6.40124321e-01  -5.09210706e-01   3.32897812e-01   3.09894621e-01  -5.85409343e-01   1.63564682e+00  -1.58412129e-01  -5.84037542e-01  -1.53046978e+00  -1.80295396e+00   1.18067396e+00  -8.94384742e-01  -1.00935853e+00  -1.06740487e+00   9.87019315e-02   1.33844817e+00  -4.84928191e-01  -1.01971292e+00  -1.40371168e+00  -2.42987067e-01   2.21512347e-01  -1.20145929e+00  -5.20043969e-01  -1.44045278e-01  -1.60914969e+00   1.63498008e+00  -6.49034619e-01  -2.05779767e+00   1.92865205e+00  -5.35783648e-01  -5.73674500e-01   2.10478687e+00  -2.56345212e-01   7.60093093e-01   8.38537812e-01  -7.95001328e-01  -9.30995643e-01  -7.99197197e-01  -1.54063523e+00  -6.08063042e-01   2.07473993e-01   4.34703082e-01  -3.71754885e-01   1.02676904e+00   2.78252929e-01   1.52795482e+00   1.37919769e-01  -9.99383926e-01   5.88999748e-01  -7.33785272e-01  -1.66489530e+00  -6.96008623e-01   8.26062500e-01   2.76657869e-03   4.62220579e-01  -1.11987019e+00  -7.05150962e-01   8.52191806e-01   1.05809963e+00   1.25231361e+00  -1.37434757e+00  -5.61459124e-01   1.31524777e+00   7.08946109e-01   6.96632192e-02  -3.72218597e-03   3.93214859e-02   1.26100421e+00  -1.70912647e+00   1.29855648e-01  -1.22835410e+00  -1.85985083e-03  -3.01825792e-01  -2.44489932e+00   9.17255342e-01  -1.04218018e+00   9.62443769e-01   2.05759668e+00  -6.04564250e-01   2.74809033e-01   9.81030405e-01   7.17494130e-01  -3.39406252e-01   1.61588025e+00   7.88029492e-01   3.04335326e-01  -1.42919585e-01  -2.54244238e-01   2.89612436e+00   1.22055089e+00  -2.00335488e-01   1.39601871e-01  -7.40230918e-01  -8.03827226e-01   8.28680277e-01  -8.35719764e-01   3.28945518e-01  -4.77222830e-01  -1.17715454e+00  -1.77932358e+00  -7.43216813e-01   7.03337491e-02  -2.20332235e-01  -7.12516904e-02  -1.91951990e+00   4.60949093e-01  -1.58758390e+00  -1.29770130e-01  -2.06872511e+00   3.72601241e-01  -1.72245955e+00  -8.92038196e-02   1.08535755e+00   4.55891132e-01   3.53040874e-01   6.61257088e-01  -2.06458852e-01  -8.01300645e-01  -2.75559616e+00  -4.32139009e-01  -7.10852563e-01   7.30033457e-01  -1.57075572e+00   1.29583406e+00   1.20143223e+00  -1.06521583e+00   1.70795631e+00   1.33439767e+00   1.92839491e+00   3.64060625e-02   6.86546504e-01  -2.44799590e+00  -8.10643673e-01  -5.33080161e-01   1.11595452e+00   6.28994942e-01  -8.93258214e-01  -8.42106864e-02   1.45618945e-01  -8.96800518e-01   1.59965074e+00   1.86706913e+00  -9.35686052e-01   1.47664523e+00  -1.73507184e-02   8.07405770e-01   1.42838001e+00  -5.87339342e-01   3.76376659e-01   8.61623049e-01   1.58352578e+00   1.47718000e+00  -1.30609155e+00  -1.51038086e+00   2.35511327e+00   1.12220068e-02   6.77131116e-01  -1.57578528e+00   7.28903830e-01   1.53305069e-01   1.41794538e+00   8.46278593e-02   5.67265809e-01   8.36715698e-01   7.25901902e-01  -1.59344685e+00  -1.41044843e+00  -6.70181274e-01  -9.31744993e-01  -1.00910282e+00   1.94031477e-01   1.75198734e+00   4.23809551e-02  -1.33153701e+00   1.27069902e+00   5.32282472e-01   2.04189897e+00  -3.67238641e-01   1.58694279e+00  -2.48838592e+00   1.36547315e+00   1.36934888e+00   1.13085139e+00   2.84735656e+00   6.54410779e-01   8.09507370e-01  -9.17495012e-01   9.85128164e-01   1.52835238e+00  -2.95696944e-01  -6.94908798e-01   1.08731262e-01  -2.22732455e-01   9.58909690e-01  -3.17186117e+00   2.00879526e+00  -2.82169670e-01   9.70469773e-01   1.03761053e+00  -4.70901728e-01   3.67405891e-01   1.97300166e-01   1.42461681e+00  -5.67683399e-01  -5.72197512e-02   2.10058641e+00   6.16604149e-01   2.13886499e+00   1.14346838e+00   1.63408399e+00  -1.39311099e+00   1.39931142e+00  -1.42244124e+00   3.26153308e-01  -1.01225746e+00   1.27143419e+00  -1.47422886e+00   4.32568610e-01  -2.56865764e+00   1.09911728e+00   7.29744792e-01  -3.29833895e-01   2.10092306e+00  -9.02076438e-02   6.40789032e-01  -1.27699077e+00  -9.98630524e-01  -1.85138988e+00  -1.47061205e+00  -1.72385561e+00  -5.83995581e-01   1.87240863e+00  -1.34105369e-01  -1.11345994e+00   2.09584445e-01   1.68201923e+00  -3.93061433e-03   4.20599252e-01   1.14158893e+00]

类似的使用还有:

#coding:utf-8import gensimimport sysreload(sys)sys.setdefaultencoding('utf-8')model = gensim.models.Word2Vec.load('web_words.model')# 计算两个词语相似度y = model.similarity(u"男人", u"女人")  # 计算单词相关列表list = model.most_similar(u"赌场", topn=20)print yfor i in list:    print "word:%s | %g" % (i[0].decode('utf-8'), i[1])

输出:

0.765876215668word:贵宾厅 | 0.582149word:赌博 | 0.576606word:赌客 | 0.576345word:娱乐场 | 0.560711word:赌球 | 0.555879word:澳门 | 0.549308word:赌钱 | 0.543402word:威尼斯人 | 0.53562word:葡京 | 0.535545word:拉斯维加斯 | 0.535134word:赌厅 | 0.530768word:轮盘 | 0.528454word:荷官 | 0.52547word:赌桌 | 0.525209word:超濠 | 0.51781word:博彩 | 0.514765word:投注网 | 0.510482word:大西洋城 | 0.509464word:真钱 | 0.508942word:赌局 | 0.506562

了解更多函数,可以查看gensim的word2vec model文档。

4.在线训练

当语料增加时,我们可以在现有模型基础上进行训练,而不需要重新开始训练。

#coding:utf-8import sysreload(sys)sys.setdefaultencoding( "utf-8" )from gensim.models import Word2Vecimport logging,gensim,osfrom gensim.models.word2vec import LineSentence# 加载模型model = Word2Vec.load('word2vector2.model')# 导入新增语料new_corpus = LineSentence('corpus/iphone6sreview-seg.txt')# 在线训练模型model.train(new_corpus)# 保存新模型model.save('word2vector3.model')

0x04.参考资料

自己动手写word2vec (一):主要概念和流程

Google word2vec算法 数学原理 - 下载频道 - CSDN.NET

Deep Learning实战之word2vec

使用 word2vec 训练wiki中英文语料库