向量化算法word2vec
词袋模型
最早的以词语为基本处理单元的文本向量化方法
方法:
- 基于出现的词语构建词典(唯一索引)
- 统计每个单词出现的词频构成向量
存在的问题
- 维度灾难
- 无法保留语序信息
- 存在语义鸿沟的问题
神经网络语言模型(NNLM)
特点
与传统方法估算P不同,NNLM直接通过一个神经网络结构对nn元条件概率进行估计。
基本结构
大致操作
从语料库中搜集一系列长度为nn的文本序列,假设这些长度为nn的文本序列组成的集合为DD,那么NNLM的目标函数为:
网络模型
- 输入层:低维度、紧密的词向量,将词序列中每个词向量按顺序拼接:
- 将得到的xx输入到隐含层,得到hh:
h=tanh(b+Hx)
其中HH为输入层到隐含层的权重矩阵,维度为∣h∣×(n−1)∣e∣。 - 隐含层的hh接入输出层得到yy:
y=b+Uh
其中UU为隐藏层到输出层的权重矩阵,维度为∣V∣×∣h∣∣V∣×∣h∣,∣V∣∣V∣表示词表的大小。 - 对输出层进行归一化
在输出层前加softmaxsoftmax函数,将yy转化为对应的概率值: - 训练方法
使用随机梯度下降法法训练,在训练每个batch时,随机从语料库DD中抽取若干样本进行训练,迭代公式: - 其中αα为学习率,θθ为模型中涉及的所有参数。
C&W模型
特点
NNLM的目标是构建一个语言概率模型,C&W则是生成词向量
核心机制
如果nn元短语在语料库中出现过,则给该短语打高分,如未出现过则打较低的评分
模型结构
目标函数
其中(w,c)(w,c)为正样本,从语料中抽取的nn元短语,nn为单数,ww为目标词,cc为目标词的上下文语境,w′w ′是从词典中随机抽取的一个词语,(w′,c)为负样本。
CBOW模型和Skip-gram模型
CBOW模型
简介
以一段文本的中间词作为目标词
去掉了隐含层,提高了运行速度
模型结构
CBOW对目标词的条件概率计算公式
CBOW的目标函数
Skip-gram模型
简介
与CBOW类似,没有隐含层
CBOW输入上下文词的中间词向量,Skip-gram从目标词ww的上下文中选择一个词
模型结构
Skip-gram目标函数
实战:网页文本向量化
语料:下载地址是https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2,或者在这里找https://dumps.wikimedia.org/zhwiki/。这个文件只包含了标题和正文,不包含词条之间的链接信息,大小约为1.3G
1、词向量的训练
1.1 中文语料预处理
将xml->txt 繁->简 利用结巴进行分词
# -*- coding: utf-8 -*-
from gensim.corpora import WikiCorpus
import jieba
from langconv import *
def my_function():
space = ' '
i = 0
l = []
zhwiki_name = './data/zhwiki-latest-pages-articles.xml.bz2'
f = open('./data/reduce_zhiwiki.txt', 'w')
wiki = WikiCorpus(zhwiki_name, lemmatize=False, dictionary={})
for text in wiki.get_texts():
for temp_sentence in text:
temp_sentence = Converter('zh-hans').convert(temp_sentence)
seg_list = list(jieba.cut(temp_sentence))
for temp_term in seg_list:
l.append(temp_term)
f.write(space.join(l) + '\n')
l = []
i = i + 1
if (i %200 == 0):
print('Saved ' + str(i) + ' articles')
f.close()
if __name__ == '__main__':
my_function()
1.2 利用gensim模块训练词向量
# -*- coding: utf-8 -*-
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
def my_function():
wiki_news = open('./data/reduce_zhiwiki.txt', 'r')
model = Word2Vec(LineSentence(wiki_news), sg=0,size=192, window=5, min_count=5, workers=9)
model.save('zhiwiki_news.word2vec')
if __name__ == '__main__':
my_function()
2.计算网页相似度
2.1 word2vec计算网页相似度
基本方法:抽取文本中的关键词(结巴工具包里面的tfidf关键字提取),将关键词向量化,然后将得到的各个词向量相加,最后得到一个词向量总和代表文本的向量化表示,利用总的向量计算文本相似度。
# -*- coding: utf-8 -*-
import jieba.posseg as pseg
from jieba import analyse
def keyword_extract(data, file_name):
tfidf = analyse.extract_tags
keywords = tfidf(data)
return keywords
def getKeywords(docpath, savepath):
with open(docpath, 'r') as docf, open(savepath, 'w') as outf:
for data in docf:
data = data[:len(data)-1]
keywords = keyword_extract(data, savepath)
for word in keywords:
outf.write(word + ' ')
outf.write('\n')
def word2vec(file_name,model):
with codecs.open(file_name, 'r') as f:
word_vec_all = numpy.zeros(wordvec_size)
for data in f:
space_pos = get_char_pos(data, ' ')
first_word=data[0:space_pos[0]]
if model.__contains__(first_word):
word_vec_all= word_vec_all+model[first_word]
for i in range(len(space_pos) - 1):
word = data[space_pos[i]:space_pos[i + 1]]
if model.__contains__(word):
word_vec_all = word_vec_all+model[word]
return word_vec_all
def simlarityCalu(vector1,vector2):
vector1Mod=np.sqrt(vector1.dot(vector1))
vector2Mod=np.sqrt(vector2.dot(vector2))
if vector2Mod!=0 and vector1Mod!=0:
simlarity=(vector1.dot(vector2))/(vector1Mod*vector2Mod)
else:
simlarity=0
return simlarity
if __name__ == '__main__':
model = gensim.models.Word2Vec.load('data/zhiwiki_news.word2vec')
p1 = './data/P1.txt'
p2 = './data/P2.txt'
p1_keywords = './data/P1_keywords.txt'
p2_keywords = './data/P2_keywords.txt'
getKeywords(p1, p1_keywords)
getKeywords(p2, p2_keywords)
p1_vec=word2vec(p1_keywords,model)
p2_vec=word2vec(p2_keywords,model)
print(simlarityCalu(p1_vec,p2_vec))