一、abstract

为把人们所理解的自然语言让计算机也能够认识并且操作,需要将人的语言(即文字)转换成计算机的语言(即数字)

二 、词的两种表示方法

1.1离散表示(one-hot representation)

缺点:编码过程中并不考虑词的顺序,无法衡量词与词之间的关系

包括:

one-hot

bag of words

TF-IDF

N-gram

one-hot:

假设有一个词库,其大小为V,则词库中的每一个词可以用一个[V,1]的向量表示,在词库中,在出现该词的地方标记为1,其它地方标记为0,这样,每一个词就唯一表示为一个向量,但是这种表示方式受限于词库的大小,当词库过于庞大时,每一个one-hot向量的维度也会很大,对于计算机的存储和计算来说是灾难性的。而且这种表示无法度量词语之间的相似性。

举个例子:

缺点:词矩阵太稀疏,并且没有考虑词出现的频率。

Bag Of Words: 词袋模型,会统计词在语料中出现的次数

是one hot词向量的加和。用元素的频率表示文本的特征。

TF-IDF:是一种统计方法  用以评估一个词对于一个文本的重要程度

其中 TF是衡量一个词在文档中出现的多频繁

TF(t)=(t在文档中出现的次数)/(文档中总的词数)

IDF是衡量一个词有多重要

IDF(t)=log(文档总数/(包含有t的文档数+1))

TF-IDF =TF*IDF

词的重要性随着 词在文档中出现的次数正比增加,并且随着词在语料库中出现的频率呈反比下降。

即词在文本中出现的频率越高,而在其他文档中出现的频率越低  ,越能更好做分类。

N-gram,N代表是几元分词,(比如 如果是bi-gram就是二元分词, 用每两个相邻的词作为一个词作  构建向量)

离散表示具有的缺点:

1 词表维度随着语料库增长膨胀

2 n-gram词序列随着语料库膨胀更快

3 数据稀疏的问题

1.2分布式表示(distribution representation)

word embedding指的是将词转化成一种分布式表示,又称词向量。分布式表示将词表示成一个定长的连续的稠密向量。

分布式表示的优点

(1)可以表示词语之间的相似关系,这种相似关系包括自然语言中词语之间的顺序以及是否是同义词等

(2)词向量包含更多信息,并且每一维都有特定的含义。在采用one-hot特征时,可以对特征向量进行删减,词向量则不能。

包括:

共现矩阵

NNLM 神经网络语言模型

CBOW(continue bag of  words)

skip-gram

共现矩阵: 主要用于发现主题,(n个词共同出现的次数),使用一个对称的局域窗,窗口的大小表示词左右的几个词,将共现矩阵的行 或者 列作为词向量,

缺点:

向量维数随词典大小线性增长   解决方法:降维  PCA  SVD

存储整个词典所需空间消耗巨大

矩阵稀疏

NNLM:  神经网络语言模型   用前N个词去推测最后一个词

CBOW :用左右附近的词去推测中间的词,相比NNLM 去掉了隐层,用求和代替拼接。

skip-gram与CBOW完全相反的思路 ,是通过 当前这个词去预测其之前之后的词。

缺点:对多义词无法很好的表示。

三、如何生成词向量

以上离散表示和分布式表示可以说都是词向量的表示形式,常用的有:CBOW、skip-gram

生成词向量的方法有很多,这些方法都依照一个思想:任一词的含义可以用它的周边词来表示。生成词向量的方式可分为:基于统计的方法和基于语言模型(language model)的方法。这里主要讲解基于语言模型的方法。

两个重要模型

原理:拥有差不多上下文的两个单词的意思往往是相近的

1、Continuous Bag-of-Words(CBOW)

功能:通过上下文预测当前词出现的概率BOW的思想:

v(“abc”)=1/3(v(“a”)+v(“b”)+v(“c”))v(“abc”)=1/3(v(“a”)+v(“b”)+v(“c”))

原理分析:假设文本如下:“the florid prose of the nineteenth century.

想象有个滑动窗口,中间的词是关键词,两边为相等长度(m,是超参数)的文本来帮助分析。文本的长度为7,就得到了7个one-hot向量,作为神经网络的输入向量,训练目标是:最大化在给定前后文本7情况下输出正确关键词的概率,比如给定("prose","of","nineteenth","century")的情况下,要最大化输出"the"的概率,

用公式表示就是P("the"|("prose","of","nineteenth","century"))

P("the"|("prose","of","nineteenth","century"))特性hidden layer只是将权重求和,传递到下一层,是线性的

Input layer

x1k,x2k,...,xCk表示上下文中的词语,每一个词用1个维数为1xV的one-hot向量表示,则input layer用向量INPUT_LAYER表示,其维数为CxV,在input layer和hidden layer中间有一个权重矩阵W,

INPUT_LAYER(CxV)xW(VxN)=HIDDEN_LAYER(CxN)

则HIDDEN_LAYER矩阵表示C个词语的分布式表示(词向量)

定义输出矩阵OUTPUT_LAYER(CxV),权重矩阵W'(NxV)

HIDDEN_LAYER(CxN)xW'(NxV)=OUTPUT_LAYER(CxV)

OUTPUT_LAYER(CxV)表示将某一个词作为中心词的概率

2、Skip-gram

功能:根据当前词预测上下文

原理分析

和CBOW相反,则我们要求的概率就变为P(Context(w)|w)P(Context(w)|w)

以上面的句子为例,数据集的构成,(input,output),(input,output)就是(the,prose),(the,of),(the,nineteenth),(the,century)(the,prose),(the,of),(the,nineteenth),(the,century)

损失函数

如果假设当前词为ww,那么可以写成P(wt+j|wt)(−m<=j<=m,j≠0)P(wt+j|wt)(−m<=j<=m,j≠0),每个词都会有一个概率,训练的目标就是最大化这些概率的乘积

也就是:L(θ)=∏(−m≤j≤m,j≠0)P(wt+j|wt;θ)L(θ)=∏(−m≤j≤m,j≠0)P(wt+j|wt;θ),表示准确度,要最大化

在概率中也经常有:J(θ)=−1TlogL(θ)=−1T∑Tt=1∑log(P(wt+j|wt;θ))J(θ)=−1TlogL(θ)=−1T∑t=1T∑log(P(wt+j|wt;θ)),加个负号就改成最小

概率示意P(o|c)=exp(uTovc)∑vw=1exp(uTwvc)P(o|c)=exp(uoTvc)∑w=1vexp(uwTvc)

vcvc:当cc为中心词时用vv

ucuc:当cc在ContextContext里时用uu

优点

在数据集比较大的时候结果更准确

四、word2vec的训练

以下这两个方法是训练技巧,目的是为了加速模型训练

hierarchical softmax,本质是把 N 分类问题变成 log(N)次二分类

negative sampling(负采样),本质是预测总体类别的一个子集

faq问答代码:

import gensim
import jieba
import numpy as np
from gensim.models import Word2Vec, word2vecimport json
import multiprocessingdef stopwordslist():stopwords = [line.strip() for line in open('stopword.txt', 'r', encoding='utf-8').readlines()]return stopwordsdef main():cnt = 0question = {}sentences_list = []with open('train.json', 'r', encoding='utf-8') as f:for line in f:json_obj = json.loads(line)#获得train.json中的每一行,改行包含id,question,candidates,answerquestion[cnt] = json_obj#question中存储train.json中一行所包含的所有信息,包含id,question,candidates,answersentences_list.append(question[cnt]['question'])#sentences_list中存储train.json中每行所对应的question的信息cnt=cnt+1#cnt+1,下一个问题#加载停用词stopwords = stopwordslist()#print(f"stopwords:{stopwords}")# 结巴分词sentences_cut = []for ele in sentences_list:#对train.json中每个问题分词cuts = jieba.cut(ele, cut_all=False)#cuts中存储问题分词后的列表,类似于['','','','',...]new_cuts = []for cut in cuts:#cut用于遍历cuts中的元素,类似于:''if cut not in stopwords:#如果cut不在停用词中new_cuts.append(cut)#new_cuts是cuts过滤掉停用词之后的结果sentences_cut.append(new_cuts)#过滤掉停用词时候,将列表new_cuts加入到记录分词结果的sentences_cut列表中,其中每个元素都是一个列表#print(f"sentences_cut:{sentences_cut}")# 分词后的文本保存在data.txt中with open('data.txt', 'w', encoding='utf-8') as f:for ele in sentences_cut:#sentences_cut中每个元素都是一个列表ele = ele + list('\n')line = ' '.join(ele)#给ele中给个元素之间加一个' 'f.write(line)# 可以用BrownCorpus,Text8Corpus或lineSentence来构建sentences,一般大语料使用这个sentences = list(word2vec.LineSentence('data.txt'))#将data.txt中的数据转换成一个规范的列表# sentences = list('data.txt')# sentences = list(word2vec.Text8Corpus('data.txt'))# 小语料可以不使用# sentences = sentences_cutprint(f"sentences:{sentences}")# 训练方式1model = Word2Vec(sentences, min_count=1, window=5, sg=1, workers=multiprocessing.cpu_count())print(f"model:{model}")# 训练方式2# 加载一个空模型# model2 = Word2Vec(min_count=1)# 加载词表# model2.build_vocab(sentences)# 训练# model2.train(sentences, total_examples=model2.corpus_count, epochs=10)# print(model2)# 保存# 方式一# model.save('word2vec.model')# 方式二model.wv.save_word2vec_format('word2vec.vector')model.wv.save_word2vec_format('word2vec.bin')# 计算相似度# sent1 = ['奇瑞', '新能源', '运营', '航天', '新能源汽车', '平台', '城市', '打造', '技术', '携手']# sent2 = ['新能源', '奇瑞', '新能源汽车', '致力于', '支柱产业', '整车', '汽车', '打造', '产业化', '产业基地']# sent3 = ['辉瑞', '阿里', '互联网', '医师', '培训', '公益', '制药', '项目', '落地', '健康']# sent4 = ['互联网', '医院', '落地', '阿里', '健康', '就医', '流程', '在线', '支付宝', '加速']## sim1 = model.wv.n_similarity(sent1, sent2)# sim2 = model.wv.n_similarity(sent1, sent3)# sim3 = model.wv.n_similarity(sent1, sent4)## print('sim1', sim1)# print('sim2', sim2)# print('sim3', sim3)# 词移距离# distance1 = model.wv.wmdistance(sent1, sent2)# distance2 = model.wv.wmdistance(sent1, sent3)# distance3 = model.wv.wmdistance(sent1, sent4)## print(distance1)# print(distance2)# print(distance3)sent1 = '被车撞,对方负全责,我该找车主还是保险公司来买单?'# 对用户提出的问题分词new_cuts_first = []cuts = jieba.cut(sent1, cut_all=False)for cut in cuts:if cut not in stopwords:new_cuts_first.append(cut)print(new_cuts_first)#遍历train.json中的每一个问题length = len(sentences_list)#sentences_list中存储train.json中每行所对应的question的信息similar_max = 0sign = -1for i in range(length):sent = sentences_list[i]cuts = jieba.cut(sent, cut_all=False)new_cuts_second = []for cut in cuts:if cut not in stopwords:new_cuts_second.append(cut)if len(new_cuts_first) != 0 and len(new_cuts_second) != 0:similar = model.wv.n_similarity(new_cuts_first, new_cuts_second)if similar >= similar_max:similar_max = similarsign = iprint(question[sign]["answer"])print(sign)if __name__ == '__main__':main()

上述faq问答的精确度不高,上述代码文本相似度计算调用的函数为:

similar = model.wv.n_similarity(new_cuts_first, new_cuts_second)

其计算的是两列单词之间的余弦相似度

将计算文本相似度调用的函数改为:

similarity=model.wv.cosine_similarities(vec1, vec2)

其中计算余弦相似度的函数可以自己定义,其定义如下:

def cos_sim(vector_a, vector_b):"""计算两个向量之间的余弦相似度:param vector_a: 向量 a :param vector_b: 向量 b:return: sim"""vector_a = np.mat(vector_a)vector_b = np.mat(vector_b)num = float(vector_a * vector_b.T)denom = np.linalg.norm(vector_a) * np.linalg.norm(vector_b)sim = num / denomreturn sim

余弦相似度

用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫"余弦相似性"。

计算公式如下:

该公式中有一个错误的点,应该是最大化,而不是最小化

利用余弦相似度,可以得到以下基于余弦相似度计算文本相似度的代码:

import gensim
import jieba
import numpy as np
from gensim.models import Word2Vec, word2vecimport json
import multiprocessingdef stopwordslist():stopwords = [line.strip() for line in open('stopword.txt', 'r', encoding='utf-8').readlines()]return stopwordsdef cos_sim(vector_a, vector_b):"""计算两个向量之间的余弦相似度:param vector_a: 向量 a:param vector_b: 向量 b:return: sim"""vector_a = np.mat(vector_a)vector_b = np.mat(vector_b)num = float(vector_a * vector_b.T)denom = np.linalg.norm(vector_a) * np.linalg.norm(vector_b)sim = num / denomreturn simdef main():cnt = 0question = {}sentences_list = []with open('train.json', 'r', encoding='utf-8') as f:for line in f:json_obj = json.loads(line)#获得train.json中的每一行,改行包含id,question,candidates,answerquestion[cnt] = json_obj#question中存储train.json中一行所包含的所有信息,包含id,question,candidates,answersentences_list.append(question[cnt]['question'])#sentences_list中存储train.json中每行所对应的question的信息cnt=cnt+1#cnt+1,下一个问题#加载停用词stopwords = stopwordslist()#print(f"stopwords:{stopwords}")# 结巴分词sentences_cut = []for ele in sentences_list:#对train.json中每个问题分词cuts = jieba.cut(ele, cut_all=False)#cuts中存储问题分词后的列表,类似于['','','','',...]new_cuts = []for cut in cuts:#cut用于遍历cuts中的元素,类似于:''if cut not in stopwords:#如果cut不在停用词中new_cuts.append(cut)#new_cuts是cuts过滤掉停用词之后的结果sentences_cut.append(new_cuts)#过滤掉停用词时候,将列表new_cuts加入到记录分词结果的sentences_cut列表中,其中每个元素都是一个列表#print(f"sentences_cut:{sentences_cut}")# 分词后的文本保存在data.txt中with open('data.txt', 'w', encoding='utf-8') as f:for ele in sentences_cut:#sentences_cut中每个元素都是一个列表ele = ele + list('\n')line = ' '.join(ele)#给ele中给个元素之间加一个' 'f.write(line)# 可以用BrownCorpus,Text8Corpus或lineSentence来构建sentences,一般大语料使用这个sentences = list(word2vec.LineSentence('data.txt'))#将data.txt中的数据转换成一个规范的列表# sentences = list('data.txt')# sentences = list(word2vec.Text8Corpus('data.txt'))# 小语料可以不使用# sentences = sentences_cut#print(f"sentences:{sentences}")# 训练方式1model = Word2Vec(sentences, vector_size=256,min_count=1, window=5, sg=1, workers=multiprocessing.cpu_count())#print(f"model:{model}")# 训练方式2# 加载一个空模型# model2 = Word2Vec(min_count=1)# 加载词表# model2.build_vocab(sentences)# 训练# model2.train(sentences, total_examples=model2.corpus_count, epochs=10)# print(model2)# 保存# 方式一model.save('word2vec.model')# 方式二model.wv.save_word2vec_format('word2vec.vector')model.wv.save_word2vec_format('word2vec.bin')# 计算相似度# sent1 = ['奇瑞', '新能源', '运营', '航天', '新能源汽车', '平台', '城市', '打造', '技术', '携手']# sent2 = ['新能源', '奇瑞', '新能源汽车', '致力于', '支柱产业', '整车', '汽车', '打造', '产业化', '产业基地']# sent3 = ['辉瑞', '阿里', '互联网', '医师', '培训', '公益', '制药', '项目', '落地', '健康']# sent4 = ['互联网', '医院', '落地', '阿里', '健康', '就医', '流程', '在线', '支付宝', '加速']## sim1 = model.wv.n_similarity(sent1, sent2)# sim2 = model.wv.n_similarity(sent1, sent3)# sim3 = model.wv.n_similarity(sent1, sent4)## print('sim1', sim1)# print('sim2', sim2)# print('sim3', sim3)# 词移距离# distance1 = model.wv.wmdistance(sent1, sent2)# distance2 = model.wv.wmdistance(sent1, sent3)# distance3 = model.wv.wmdistance(sent1, sent4)## print(distance1)# print(distance2)# print(distance3)sent1 = '被车撞,对方负全责,我该找车主还是保险公司来买单?'sent2='我出车祸,对方全责,对方应该样理赔我'sent3='您好,我产假将结束时被公司劝退,公司答应给赔偿金,但是签订的赔偿协议金额不对,有进行了第二次谈话,公司人事经理承认有差额答应给我,可是现在又不承认有差额了,这种情况我可以申请仲裁吗?'# 对用户提出的问题分词new_cuts_first = []cuts = jieba.cut(sent3, cut_all=False)for cut in cuts:if cut not in stopwords:new_cuts_first.append(cut)print(new_cuts_first)vec1=np.zeros_like(model.wv[str(new_cuts_first[0])])for i in range(len(new_cuts_first)):word1=new_cuts_first[i]if word1!='\n' and word1!='\r\n':vec1=vec1+np.array(model.wv[word1])vec1=1.0/len(new_cuts_first)*vec1length=len(sentences_list)similarity_max=0sign=-1for i in range(length):sent = sentences_list[i]cuts = jieba.cut(sent, cut_all=False)new_cuts_second = []for cut in cuts:if cut not in stopwords:new_cuts_second.append(cut)#计算用户提出的问题和train.json中question的词向量cos_similarity#文本词向量用文本分词词向量的均值代替vec2 = np.zeros((256))for j in range(len(new_cuts_second)):word1 = new_cuts_second[j]if word1!='\n' and word1!='\r\n':vec2 = vec2 + np.array(model.wv[word1])if len(new_cuts_second)!=0:vec2 = 1.0/len(new_cuts_second)*vec2similarity=cos_sim(vec1,vec2)if similarity>similarity_max:similarity_max=similaritysign=iprint(f"similarity_max:{similarity_max}")print(question[sign]["answer"])print(sign)if __name__ == '__main__':main()

词向量 文本相似度计算相关推荐

  1. 基于预训练词向量的文本相似度计算-word2vec, paddle

    文章目录 0. 前言 1. 余弦相似度算子 2. 示例代码并验证 3. 基于词向量的文本相似度 3.1 读取word2vec文件 3.2 定义模型 3.3 运行模型 3.4 根据分数降序排列 3.5 ...

  2. 文本相似度计算(切词、生成词向量,使用余弦相似度计算)

    项目需求 有多个文本,分别是正负样本,使用余弦相似度计算负样本与正样本的样本相似度,若准确率高,后期可判断新加样本与正样本的相似度. 输入如下所示: content label 今天下午,在龙口市诸由 ...

  3. Google开源word2vec,文本相似度计算工具

    Google开源word2vec,文本相似度计算工具 谷歌已经使用Deep Learning技术开发了许多新方法来解析语言,目前,谷歌开源了一款基于Deep Learning的学习工具--word2v ...

  4. 【NLP实战】基于ALBERT的文本相似度计算

    实战是学习一门技术最好的方式,也是深入了解一门技术唯一的方式.因此,NLP专栏推出了实战专栏,让有兴趣的同学在看文章之余也可以自己动手试一试. ALBERT是一个比BERT要轻量,效果更好的模型,本篇 ...

  5. 文本相似度计算python lda_如何识别“答非所问”?使用gensim进行文本相似度计算...

    在文本处理中,比如商品评论挖掘,有时需要了解每个评论分别和商品的描述之间的相似度,以此衡量评论的客观性. 评论和商品描述的相似度越高,说明评论的用语比较官方,不带太多感情色彩,比较注重描述商品的属性和 ...

  6. 如何识别“答非所问”?使用gensim进行文本相似度计算

    在文本处理中,比如商品评论挖掘,有时需要了解每个评论分别和商品的描述之间的相似度,以此衡量评论的客观性. 评论和商品描述的相似度越高,说明评论的用语比较官方,不带太多感情色彩,比较注重描述商品的属性和 ...

  7. sklearn tfidf求余弦相似度_【基础算法 】文本相似度计算

    在自然语言处理中,文本相似度是一种老生常谈而又应用广泛的基础算法模块,可用于地址标准化中计算与标准地址库中最相似的地址,也可用于问答系统中计算与用户输入问题最相近的问题及其答案,还可用于搜索中计算与输 ...

  8. 中文文本相似度计算工具集

    欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 一.基本工具集 1.分词工具 a.jieba 结巴中文分词 htt ...

  9. 最准的中文文本相似度计算工具

    向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程   公众号:datayx text2vec, chinese text to vetor.(文本向量化表示工具,包括词向 ...

最新文章

  1. ubuntu14.04 升级gcc的方法
  2. Go语言中字符串的查找方法小结
  3. python jupyter 选择按钮,使用按钮选择数据
  4. 使用SAP Cloud Platform fullstack WebIDE创建SAP UI5应用并部署
  5. LoadRunner 12.02 安装教程及中文语言包安装
  6. pca百分比取多少比较好_母亲节给妈妈发多少红包比较好合适 母亲节红包吉利数字含义...
  7. ccf小明放学20分_关于完全平方数的好题(20年3月1日)
  8. matlab写的串口通信图像上位机,MATLAB的串口通信
  9. Java中split函数的用法及使用示例
  10. CubeMX配置SPI-Flash(W25Q256)
  11. JS学习3-Js运算符优先级
  12. 同志,云原生了解一下?
  13. 【Raspberry Pi】搭建NAS流媒体播放器 + ARIA2 + YAAW + 迅雷下载系统
  14. 利用metadata-extractor定向获取图片拍摄时间以及宽高
  15. pytorch下可训练分段函数的写法
  16. 读取Java源文件中字段的注释当做Swagger的字段描述
  17. MySQL中关于字符编码的配置
  18. Oracle导出报错: unknown command beginning “exp SCOTT/...“ - rest of line ignored.
  19. 中职计算机基础应用知识,总发中职《计算机应用基础:基础模块》第一单元 计算机基础知识.pptx...
  20. YOLO系列网络训练数据准备工具—Yolo_mark

热门文章

  1. 输入一个正整数n,去掉其中任意s个数字后,剩下的数字按原左右次序将组成一个新的正整数。寻找一种方案,使得剩下的数字组成的新数最小
  2. 基于聚类的方法提取关键帧
  3. 【视频】支持向量机SVM、支持向量回归SVR和R语言网格搜索超参数优化实例
  4. 汽车无钥匙启动系统, 汽车无钥匙进入一键启动系统工作原理,无钥匙启动系统优缺点
  5. 薛之谦变身“首席体验官”与金立S10“机情四摄”
  6. 玩游戏什么手机好用?rog3 平价手机也有高端配置
  7. 前端--jsp、js--返回上一个页面的方法(非脚本返回)
  8. 网易的“草长莺飞二月天”:增长稳健,加码研发,逐浪AI
  9. JS原型和原型链、继承
  10. rust 枪法_RUST枪法详解 RUST枪法受哪些因素影响