Word2vec原理与应用

时间:2021-12-07 01:42:24

用一个普通的向量表示一个词,将所有这些向量放在一起形成一个词向量空间,而每一向量则为该空间中的一个点,在这个空间上的词向量之间的距离度量也可以表示对应的两个词之间的“距离”。所谓两个词之间的“距离”,就是这两个词之间的语法,语义之间的相似性。
只介绍基于Hierarchical Softmax的CBOW模型,其他模型参考文章的参考链接。

原理

语言模型的目标函数

一般为对数似然函数 C为所有语料 针对所有语料进行极大似然
Word2vec原理与应用

预测函数

训练过程中所有词全部生成,输入词(语料库已有)查询出结果即可。
p(w|Context(w))

模型学习

基于Hierarchical Softmax的CBOW模型
Word2vec原理与应用
输入层:上下文词向量
隐藏层:词向量的累加和
输出层:Huffman树(根据所有语料频数构建),叶子节点代表语料库中的词,每次分支看做二分类,往左负类,往右正类。
label=1-huffman编码(d)
梯度计算:
一个节点被分为正类的概率:
Word2vec原理与应用
sigmoid函数
负类的概率:
Word2vec原理与应用
对于词典中D中的任意词w,Huffman树必存在一条从根节点到词的路径,每次分支为一次二分类,每一次分类就产生一个概率,
这些概率连乘 就是p(w|Context(w))
Word2vec原理与应用
目标函数变为:
Word2vec原理与应用
为了推导方便上面花括号里内容记为L(w,j)
Word2vec原理与应用
训练过程:
每一个样本(w,Context(w)) 更新一次参数
Word2vec原理与应用
Word2vec原理与应用
w词向量更新
Word2vec原理与应用
伪代码:
Word2vec原理与应用

python代码实践

安装

pip install –upgrade gensim
或者
easy_install -U gensim

初始化语料库

(每行格式是词以空格分割)
使用*中文语料库:中英文*语料上的word2vec实验
读入多文件每行内容:
例如,如果我们的输入散布在磁盘上的多个文件中,每行一个句子,那么不是将所有内容都加载到内存列表中,我们可以逐行处理输入文件。(读入多文件每行内容)

class MySentences(object):
def __init__(self, dirname):
self.dirname = dirname
def __iter__(self):
for fname in os.listdir(self.dirname):
for line in open(os.path.join(self.dirname, fname)):
yield line.split()
sentences = MySentences('/some/directory') # a memory-friendly iterator

训练语料库

常见参数默认size=100, window=5, min_count=5
min_count是在0-100之间,这取决于你的数据集的大小,忽略出现次数少于多少的无意义的词。
window:是词向量训练时的上下文扫描窗口大小,窗口为5就是考虑前5个词和后5个词;
size是每个词的向量维度;较大的size值需要更多的训练数据,但可以导致更好(更准确)的模型。
workers 进程数用于训练并行化 默认1无并行化

import logging
##设置log日志格式: 时间:级别:消息 级别是INFO以上输出
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
run='test'
##拼接字符串 %s代替变量 后面%跟上变量
logging.info("running %s began %s "%(run,'!'))
##模型训练
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
##设置训练实例格式 每行一个list数组
sentences = [['first', 'sentence'], ['second', 'sentence']]
#model = Word2Vec(sentences, size=100, window=5, min_count=5, workers=4)
model = Word2Vec(sentences, size=10, window=5, min_count=0, workers=4)

从文件中读取

from gensim import Word2Vec
from gensim.Word2Vec import LineSentence
# inp为输入语料
inp = 'demo.txt'
model = Word2Vec(LineSentence(inp), size=100, window=5, min_count=1, workers=4)

存储和加载模型

model.save('./mymodel')
model = Word2Vec.load('./mymodel')

查看单个词向量

model.wv['second']
#or 中文model[u'汽车']
model['second']

增量训练模型

model.train(more_sentences)
##model.train(LineSentence(more_inp))

计算两词之间的余弦相似度

##输出相似的topn 
model.most_similar(positive=['first', 'second'], negative=['sentence'], topn=1)
##查找语料库有的词汇 ?
model.doesnt_match("breakfast first dinner lunch".split())
##计算两个词的余弦相似度
model.similarity('first', 'second')

计算一个词的最近似的词,倒排序

#word.decode('utf-8')most_similar(word.decode('utf-8'), topn=topN) 
result = model.most_similar(u'足球')
for each in result:
print each[0] , each[1]

计算两个集合之间的余弦似度

当出现某个词语不在这个训练集合中的时候,会报错!

list1 = [u'今天', u'我', u'很', u'开心']
list2 = [u'空气',u'清新', u'善良', u'开心']
list_sim1 = model.n_similarity(list1, list2)

整合

# coding: utf-8
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
import logging
##设置log日志格式: 时间:级别:消息 级别是INFO以上输出
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
run='test'
##拼接字符串 %s代替变量 后面%跟上变量
logging.info("running %s began %s "%(run,'!'))

inp = 'demo.txt'
model = Word2Vec(LineSentence(inp), size=100, window=5, min_count=1, workers=4)

# model.save('./mymodel')
# model = Word2Vec.load('./mymodel')

print model[u'弓箭']

print model.similarity(u'弓箭', u'樱花树')

print model.doesnt_match(u"亚特兰 樱花树 小布".split())

result = model.most_similar(u'樱花树')
for each in result:
print each[0] , each[1]
result = model.most_similar(positive=[u'樱花树', u'铁环'], negative=[u'亚特兰'], topn=5)
for each in result:
print each[0] , each[1]

list1 = [u'铁环', u'樱花树', u'热门货', u'转学']
list2 = [u'铁环',u'樱花树', u'弓箭', u'英雄主义']
list_sim1 = model.n_similarity(list1, list2)
print list_sim1

Doc2Vec

基于gensim的Doc2Vec简析
doc2vec使用说明1学习文档向量
doc2vec使用说明2带多个标签的文档向量训练方法

import gensim, logging
import os
logging.basicConfig(format = '%(asctime)s : %(levelname)s : %(message)s', level = logging.INFO)
sentences = gensim.models.doc2vec.TaggedLineDocument('review_pure_text.txt')
model = gensim.models.Doc2Vec(sentences, size = 100, window = 5)
model.save('review_pure_text_model.txt')
print len(model.docvecs)
out = file('review_pure_text_vector.txt', 'w')
for idx, docvec in enumerate(model.docvecs):
for value in docvec:
out.write(str(value) + ' ')
out.write('\n')
print idx
print docvec
out.close()

输入文件Tweets_id_text.txt的格式就是每个doc 对应内容的分词,空格隔开,每个doc是一行
用TaggedLineDocument 实现,每个doc默认编号

参考

Word2vec知乎
中英文*语料上的word2vec实验
深度学习word2vec笔记之基础篇
gensim官方文档
wiki2vec——github
Google的word2vec官网
Deep Learning实战之word2vec
Word2vec教程
自己动手写word2vec (一):主要概念和流程
word2vec伪代码