word2vec词向量模型介绍
word2vec是一种考虑词与词之间相关性的词向量模型,它可以将意思相近的词投影到一个高维空间,生成一个距离相近高维的向量(通常是50-300维),如下图所示(图片来自于)。
从图中可以看出King与Man的余弦距离较为相近,而King与Woman之间的距离较远。word2vec的最大优势就是将意思相近的词编码成距离相近的高维向量,使编码具有语义特征。
word2vec的实现
word2vec有三种模型:
- N-gram模型
- CBOW(continue bag of word)
- Skip—Gram
这里主要讲解的是CBOW模型,CBOW模型是由中心词的上下文(context(w))来得到中心词(w)并训练词向量。总体框架可以由下图展示
这里需要注意的是,输入的词需要在语料库中先找出其索引,然后根据索引生成一个随机高维向量,然后对这些输入向量求其平均进行特征融合,接着通过一个Hierarchical Softmax分类器,最后计算预测结果与真实的结果之间的交叉熵损失进行模型训练。这里Hierarchical Softmax实际上是多层Logistic回归,并且引入了霍夫曼树模型,从而减小了相比于softmax的参数量。详细请移步Hierarchical Softmax
Negative Sampling
Negative Sampling 下采样是一种采样方式,为了追求更加快速的分类结果和更小的参数量,它摒弃了Hierarchical Softmax分类器。通俗来解释一下:
word2vec将一个句子的中心词和他的上下文视为一个正例(positive),对于不采用Negative Sampling的word2vec来说,它将会有数以千计的分类结果(比如1000分类),这不仅增加了庞大的参数量,也增加了计算的复杂度。因此,基于Negative Sampling的word2vec诞生了。
基于Negative Sampling的word2vec会为一个正例生成一些负样本,然后将正例(正例中心词+上下文)或负样本(负例中心词+上下文)输入到模型中,最终只需通过一个Logistic回归做一个二分类判断其是不是中心词与上下文匹配即可。这样就可以将一个1000分类的问题转化为一个2分类问题,大大的节约了参数量和计算开销。由于我也是一个新手小白,这是我的通俗解释,如有错误,请多多指教。详细请移步Negative Sampling
基于Gensim工具包生成word2vec模型
这里需要安装两个工具包:
- Gensim: pip install gensim
- jieba: pip install jieba
你的语料库数据集可以通过维基百科下载(维基百科)也可以使用一些小说等。在使用Gensim工具包中的word2vec之前,需要将我们准备好的.txt文件中的内容进行分词操作,就是第2个工具包的jieba分词器。我下面贴出分词和训练word2vec模型所需代码:
import jieba
import jieba.analyse
import jieba.posseg as pseg
import codecs,sys
text = open('大主宰.txt','r',encoding="utf8")
target = open('xiaoshuo2.txt','w',encoding="utf8")
line = text.readline()
while line:
line_seg = " ".join(jieba.cut(line))
target.writelines(line_seg)
print(line_seg)
line = text.readline()
text.close()
target.close()
exit()
这个是分词用的代码,接下来还需要一个word2vec生成模型的code:
import logging
import os.path
import sys
import multiprocessing
from gensim.corpora import WikiCorpus
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) < 4:
print (globals()['__doc__'] % locals())
sys.exit(1)
inp, outp1, outp2 = sys.argv[1:4]
model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())
model.save(outp1)
model.model.wv.save_word2vec_format(outp2, binary=False)
#python word2vec_model.py zh.jian.wiki.seg.txt wiki.zh.text.model wiki.zh.text.vector
#opencc -i wiki_texts.txt -o test.txt -c t2s.json
#python word2vec_model.py xiaoshuo.txt xiaoshuo.text.model xiaoshuo.text.vector
这样我们的word2vec的词向量模型就被保存在outp1和outp2中了,我们可以做一下小测试~
from gensim.models import Word2Vec
en_wiki_word2vec_model = Word2Vec.load('xiaoshuo.text.model')
testwords = ['恶心','傻子','厉害','光芒','恐怖']
for i in range(5):
res = en_wiki_word2vec_model.most_similar(testwords[i])
print (testwords[i])
print (res)
恶心
[('光明正大', 0.8532341122627258), ('剁', 0.7731980085372925), ('说服', 0.7661505937576294), ('慷慨', 0.7626612186431885), ('问问', 0.7621469497680664), ('拖泥带水', 0.7603974342346191), ('细说', 0.7572978734970093), ('记着', 0.7553634643554688), ('骗', 0.753753662109375), ('筹划', 0.7510721683502197)]
傻子
[('无关紧要', 0.6628221869468689), ('单打独斗', 0.655975341796875), ('他牧尘', 0.6399290561676025), ('人家', 0.6381828784942627), ('蠢货', 0.6338304281234741), ('失手', 0.6220790147781372), ('多半', 0.6178364753723145), ('换', 0.6163299679756165), ('满载而归', 0.6011545658111572), ('基本上', 0.5946712493896484)]
厉害
[('难缠', 0.7568021416664124), ('变态', 0.7241744995117188), ('棘手', 0.7141222953796387), ('优秀', 0.6876083016395569), ('强', 0.6873076558113098), ('出色', 0.6843757033348083), ('看重', 0.6825308799743652), ('能耐', 0.6758701801300049), ('啊', 0.6750842332839966), ('不错', 0.6658269166946411)]
光芒
[('金光', 0.886652410030365), ('光华', 0.8273990154266357), ('雷光', 0.8178660869598389), ('幽光', 0.7995476722717285), ('黑芒', 0.7966512441635132), ('之光', 0.782035768032074), ('灵光', 0.7716976404190063), ('黑光', 0.7608082294464111), ('青光', 0.7554724812507629), ('白光', 0.7331587672233582)]
恐怖
[('可怕', 0.9216969013214111), ('惊人', 0.7986444234848022), ('霸道', 0.7700717449188232), ('强悍', 0.752230167388916), ('强大', 0.7479638457298279), ('狂暴', 0.7225570678710938), ('精纯', 0.6795037984848022), ('凶猛', 0.6739758253097534), ('凶悍', 0.6677579879760742), ('威压', 0.6544308662414551)]
我用的是一篇武侠小说的语料库,因此数据集非常小,这里测试了几个词语,下面展示出了与它相关性较强的词,并给出了它们之间的相似度。
word2vec的简单介绍到此为止!感谢浏览过此页面的每一位观众。第一次发博客,经验不足,希望大家多多指教,谢谢~