向量化算法word2vec

词袋模型

最早的以词语为基本处理单元的文本向量化方法
方法:

  1. 基于出现的词语构建词典(唯一索引)
  2. 统计每个单词出现的词频构成向量

存在的问题

  1. 维度灾难
  2. 无法保留语序信息
  3. 存在语义鸿沟的问题

神经网络语言模型(NNLM)

特点

与传统方法估算P不同,NNLM直接通过一个神经网络结构对nn元条件概率进行估计。

基本结构

python词嵌入向量计算文本相似度 文本向量化 python_词向量

大致操作

从语料库中搜集一系列长度为nn的文本序列,假设这些长度为nn的文本序列组成的集合为DD,那么NNLM的目标函数为:

python词嵌入向量计算文本相似度 文本向量化 python_python词嵌入向量计算文本相似度_02

网络模型

  1. 输入层:低维度、紧密的词向量,将词序列中每个词向量按顺序拼接:
  2. python词嵌入向量计算文本相似度 文本向量化 python_xml_03

  3. 将得到的xx输入到隐含层,得到hh:
    h=tanh(b+Hx)
    其中HH为输入层到隐含层的权重矩阵,维度为∣h∣×(n−1)∣e∣。
  4. 隐含层的hh接入输出层得到yy:
    y=b+Uh
    其中UU为隐藏层到输出层的权重矩阵,维度为∣V∣×∣h∣∣V∣×∣h∣,∣V∣∣V∣表示词表的大小。
  5. 对输出层进行归一化
    在输出层前加softmaxsoftmax函数,将yy转化为对应的概率值:
  6. python词嵌入向量计算文本相似度 文本向量化 python_xml_04

  7. 训练方法
    使用随机梯度下降法法训练,在训练每个batch时,随机从语料库DD中抽取若干样本进行训练,迭代公式:
  8. python词嵌入向量计算文本相似度 文本向量化 python_python词嵌入向量计算文本相似度_05

  9. 其中αα为学习率,θθ为模型中涉及的所有参数。

C&W模型

特点

NNLM的目标是构建一个语言概率模型,C&W则是生成词向量

核心机制

如果nn元短语在语料库中出现过,则给该短语打高分,如未出现过则打较低的评分

模型结构

python词嵌入向量计算文本相似度 文本向量化 python_向量化_06


目标函数

python词嵌入向量计算文本相似度 文本向量化 python_向量化_07


其中(w,c)(w,c)为正样本,从语料中抽取的nn元短语,nn为单数,ww为目标词,cc为目标词的上下文语境,w′w ′是从词典中随机抽取的一个词语,(w′,c)为负样本。

CBOW模型和Skip-gram模型

CBOW模型

简介

以一段文本的中间词作为目标词

去掉了隐含层,提高了运行速度

模型结构

python词嵌入向量计算文本相似度 文本向量化 python_词向量_08

CBOW对目标词的条件概率计算公式

python词嵌入向量计算文本相似度 文本向量化 python_向量化_09

CBOW的目标函数

python词嵌入向量计算文本相似度 文本向量化 python_词向量_10

Skip-gram模型

简介

与CBOW类似,没有隐含层

CBOW输入上下文词的中间词向量,Skip-gram从目标词ww的上下文中选择一个词

模型结构

python词嵌入向量计算文本相似度 文本向量化 python_自然语言处理_11


Skip-gram目标函数

python词嵌入向量计算文本相似度 文本向量化 python_自然语言处理_12

实战:网页文本向量化

语料:下载地址是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))