word2vec就是一个将词向量化的工具,这里我们使用的是gensim的word2vec。
1、one-hot编码
在介绍Word2vec之前,我们先来看一下one-hot,它是指词向量维度大小为整个词汇表的大小,对于每个具体的词汇表中的词,将对应的位置置为1。例如:“the cat looks so cute”,该文本包含5个单词,词汇表为{'the','cat','looks','so','cute'},用one-hot来向量化例子文本可表示为:[[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]]。
这种词向量化方式虽然非常简单,但是却存在很多问题:
2、CBOW和Skip-gram
因为word2vec有两种训练方法,CBOW 和 Skip-gram,这里我们分开介绍。
(1)CBOW 模型
CBOW模型的训练是输入某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。这是一个简单的神经网络模型,有输入层、隐藏层和输出层,下面详细描述每一层的输入以及操作:
1)输入层的输入为上下文单词的one-hot,假设词典中有V个词,那么单词向量的维度就是V,C是窗口大小,表示当前词的上下文词个数;
2)输入层到隐藏层之间,我们要定义一个权重矩阵W,维度是V*N,N是自己定义的,这里的W需要初始化,之后将输入的每个单词的one-hot向量乘以权重矩阵,再将所得的向量相加求平均作为隐藏层向量(隐藏层向量是当前词的词向量);
3)隐藏层的数据乘以输出权重矩阵W' (初始化),维度是N*V;
4)得到维度为V*1的概率分布;
然后,求使概率分布的最大似然,可用随机梯度下降算法,至此,得到当前词的词向量和最大概率分布。
(2)Skip-gram模型
Skip-gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量,即后验概率。
其训练过程类似CBOW模型。
3、python实战
这里用到的语料是体育新闻语料,先对语料进行分词、去停用词,再调用gensim的word2vec训练模型。
from gensim.models import word2vec
import jieba
import time
import gensim
#读取数据,句子处理为空格连接的词,一个句子即一行,单词需要预先使用空格分隔
def text_deal():
text=[]
with open('./data/p1.txt', 'r', encoding='utf-8') as f:
stop_words=stop_words_deal()
for line in f.readlines():
line=line.strip()
words=jieba.cut(line)
filter_words=[' '.join(word for word in words if word not in stop_words)]
print(filter_words)
text.append(filter_words)
#text.append(' '.join(word for word in words if word not in stop_words))
with open('./data/p1_cut.txt','w',encoding='utf-8') as fw:
for doc in text:
for word in doc:
fw.write(str(word))
fw.write('\n')
def stop_words_deal():
stop_words=[]
for line in open('./data/stop_words.txt',encoding='utf-8').readlines():
stop_words.append(line.strip())
#print(stop_words)
return stop_words
#训练模型
def word2vec_model():
start = time.clock()
sentence=word2vec.LineSentence('./data/p1_cut.txt') #word2vec提供的LineSentence类来读文件
model = word2vec.Word2Vec(sentence,sg=0,size=100,window=3,min_count=1,workers=4,hs=1) #sg表示用CBOW模型训练
end = time.clock()
model.save('model_news.word2vec') #保存模型
time_spend=end-start
print('训练模型时间花费:',time_spend,'秒')
#print(model.wv.vocab)
model=gensim.models.Word2Vec.load('model_news.word2vec') #加载模型
print(model.similarity('体育','篮球')) #利用模型计算词的相似度
for i in model.most_similar("体育"):
print(i[0], i[1])
if __name__ =='__main__':
text_deal()
word2vec_model()
4、word2vec计算网页相似度
这里我们的操作是基于已经训练好的词向量模型,基本步骤是:
(1)抽取网页新闻中的关键词。这里我们可以用jieba的analyse抽取关键词,例如:
tfidf=analyse.extract_tags keywords = tfidf(text)
(2)将抽取到的关键词利用训练好的模型向量化。这里我们要注意判断关键词是否在模型词典中,否则会报错;
model.wv.vectors[model.wv.vocab[word].index]
(3)将得到的各个词向量相加,得到一个词向量总和代表网页新闻的向量化表示,利用总的向量计算相似度,相似度计算可以用余弦距离计算。