NLP(二)词袋模型及余弦相似度、编辑距离相似度

更新时间:2023-07-11 03:34:07 阅读: 评论:0

NLP(⼆)词袋模型及余弦相似度、编辑距离相似度
本⽂将介绍⼀下内容:
NLP中常见的词袋模型(Bag of Words)
如何构造句向量(Sentence Embedding)
利⽤词袋模型来计算句⼦间的余弦相似度(余弦相似度cosine similarity)
使⽤编辑距离算法计算句⼦的相似度(编辑距离相似度)
⼀,什么是词袋模型
1,分句和分词
通常,NLP⽆法⼀下⼦处理完整的段落或句⼦,因此,第⼀步往往是分句和分词。这⾥只有句⼦,因此我们只需要分词即可。
对于英语句⼦,可以使⽤NLTK中的word_tokenize函数,对于中⽂句⼦,则可使⽤jieba、 模块。
故第⼀步为分词,代码如下(如果执⾏遇到“rai LookupError”报错,请转⾄解决):
from nltk import word_tokenize
nt1 ="I love sky, I love a."
nt2 ="I like running, I love reading."
nts =[nt1, nt2]
texts =[[word for word in word_tokenize(nt)]for nt in nts]
# ------ output------
[['I','love','sky',',','I','love','a','.'],['I','like','running',',','I','love','reading','.']]
2,构建语料库(词袋)
all_list =[]
for text in texts:
all_list += text
corpus =t(all_list)
print(corpus)
# ------ output------
{'sky',',','love','.','reading','running','like','I','a'}
⼆,构造句向量
1,建⽴语料库数字映射
可以看到,语料库中⼀共是8个单词及标点。接下来,对语料库中的单词及标点建⽴数字映射,便于后续的句⼦的向量表⽰。代码如下:
corpus_dict =dict(zip(corpus,range(len(corpus))))
print(corpus_dict)
# ------ output------
{'sky':0,',':1,'love':2,'.':3,'reading':4,'running':5,'like':6,'I':7,'a':8}
虽然单词及标点并没有按照它们出现的顺序来建⽴数字映射,不过这并不会影响句⼦的向量表⽰及后续的句⼦间的相似度。
2,建⽴句⼦的向量表⽰
词袋模型的关键⼀步,就是建⽴句⼦的向量表⽰。这个表⽰向量并不是简单地以单词或标点出现与否来选择0,1数字,⽽是把单词或标点的出现频数作为其对应的数字表⽰,结合刚才的语料库字典,句⼦的向量表⽰的代码如下:
# 建⽴句⼦的向量表⽰
def vector_rep(text, corpus_dict):
vec =[]
for key in corpus_dict.keys():
if key in text:
vec.append((corpus_dict[key], unt(key)))
el:
vec.append((corpus_dict[key],0))
vec =sorted(vec, key=lambda x: x[0])
return vec
vec1 = vector_rep(texts[0], corpus_dict)
vec2 = vector_rep(texts[1], corpus_dict)
print(vec1)
print(vec2)
# ------ output------
[(0,1),(1,1),(2,2),(3,1),(4,0),(5,0),(6,0),(7,2),(8,1)]
[(0,0),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,2),(8,0)]
让我们稍微逗留⼀会⼉,来看看这个向量。在第⼀句中I出现了两次,在预料库字典中,I对应的数字为7,因此在第⼀句中7出现2次,在列表中的元组即为(7,2),代表单词I在第⼀句中出现了2次。以上的输出可能并不那么直观,真实的两个句⼦的代表向量应为:
vec1 =[ i[1]for i in vec1]
vec2 =[ i[1]for i in vec2]
# ------ output------
[1,1,2,1,0,0,0,2,1]
冰糖雪梨怎么做法[0,1,1,1,1,1,1,2,0]
词袋模型到此结束。接下来,我们会利⽤刚才得到的词袋模型,即两个句⼦的向量表⽰,来计算相似度。
三,使⽤词袋模型来计算句⼦间的余弦相似度
在NLP中,如果得到了两个句⼦的向量表⽰,那么,⼀般会选择⽤余弦相似度作为它们的相似度,⽽向量的余弦相似度即为两个向量的夹⾓的余弦值。
1,余弦相似度的计算公式
1)余弦相似性简介
余弦相似性通过测量两个向量的夹⾓的余弦值来度量它们之间的相似性。0度⾓的余弦值是1,⽽其他任何⾓度的余弦值都不⼤于1;
并且其最⼩值是-1。从⽽两个向量之间的⾓度的余弦值确定两个向量是否⼤致指向相同的⽅向。两个向量有相同的指向时,余弦相似度的值为1;两个向量夹⾓为90°时,余弦相似度的值为0;两个向量指向完全相反的⽅向时,余弦相似度的值为-1。这结果是与向量的长度⽆关的,仅仅与向量的指向⽅向相关。余弦相似度通常⽤于正空间,因此给出的值为-1到1之间。
注意这上下界对任何维度的向量空间中都适⽤,⽽且余弦相似性最常⽤于⾼维正空间。例如在信息检索中,每个词项被赋予不同的维度,⽽⼀个维度由⼀个向量表⽰,其各个维度上的值对应于该词项在⽂档中出现的频率。余弦相似度因此可以给出两篇⽂档在其主题⽅⾯的相似度。
2)公式解析
a.范数公式
b.欧⼏⾥得点积公式
两个向量间的余弦值可以通过使⽤欧⼏⾥得点积公式求出:
c.余弦相似性θ
给定两个属性向量,A和B,其余弦相似性θ由点积和向量长度给出,如下所⽰:
这⾥的分别代表向量A和B的各分量。
给出的相似性范围从-1到1:-1意味着两个向量指向的⽅向正好截然相反,1表⽰它们的指向是完全相同的,0通常表⽰它们之间是独⽴的,⽽在这之间的值则表⽰中间的相似性或相异性。
对于⽂本匹配,属性向量A和B通常是⽂档中的词频向量。余弦相似性,可以被看作是在⽐较过程中把⽂件长度正规化的⽅法。
在信息检索的情况下,由于⼀个词的频率(TF-IDF权)不能为负数,所以这两个⽂档的余弦相似性范
围从0到1。并且,两个词的频率向量之间的⾓度不能⼤于90°。
2,代码实现
抱字开头的成语from math import sqrt
def similarity_with_2_nts(vec1, vec2):苦练基本功
inner_product =0
square_length_vec1 =0
square_length_vec2 =0
for tup1, tup2 in zip(vec1, vec2):
inner_product += tup1*tup2
square_length_vec1 += tup1**2
square_length_vec2 += tup2**2
return(inner_product/sqrt(square_length_vec1*square_length_vec2))
cosine_sim = similarity_with_2_nts(vec1, vec2)
print('两个句⼦的余弦相似度为: %.4f。'%cosine_sim)
# ------ output------
两个句⼦的余弦相似度为:0.7303。
3,整理代码如下
from nltk import word_tokenize
from math import sqrt
def similarity_with_2_nts(vec1, vec2):
inner_product =0
square_length_vec1 =0
square_length_vec2 =0
for tup1, tup2 in zip(vec1, vec2):
inner_product += tup1*tup2
square_length_vec1 += tup1**2
square_length_vec2 += tup2**2
return(inner_product/sqrt(square_length_vec1*square_length_vec2))
# 建⽴句⼦的向量表⽰
def vector_rep(text, corpus_dict):
vec =[]
for key in corpus_dict.keys():
复印机怎么使用if key in text:
vec.append((corpus_dict[key], unt(key)))
跌倒的反义词el:
vec.append((corpus_dict[key],0))
vec =sorted(vec, key=lambda x: x[0])
return vec
nt1 ="I love sky, I love a."
nt2 ="I like running, I love reading."
nts =[nt1, nt2]
texts =[[word for word in word_tokenize(nt)]for nt in nts]
all_list =[]
for text in texts:
all_list += text
corpus =t(all_list)
print(corpus)
corpus_dict =dict(zip(corpus,range(len(corpus))))
print(corpus_dict)
vec1 = vector_rep(texts[0], corpus_dict)
vec2 = vector_rep(texts[1], corpus_dict)
print(vec1)
print(vec2)
vec1 =[ i[1]for i in vec1]
vec2 =[ i[1]for i in vec2]
cosine_sim = similarity_with_2_nts(vec1, vec2)
print('两个句⼦的余弦相似度为: %.4f。'%cosine_sim)
#------output-----------
{',','reading','sky','a','running','love','.','like','I'}
{',':0,'reading':1,'sky':2,'a':3,'running':4,'love':5,'.':6,'like':7,'I':8}
[(0,1),(1,0),(2,1),(3,1),(4,0),(5,2),(6,1),(7,0),(8,2)]
[(0,1),(1,1),(2,0),(3,0),(4,1),(5,1),(6,1),(7,1),(8,2)]
两个句⼦的余弦相似度为:0.7303。
坐摩天轮4,利⽤gensim实现相似度计算
当然,在实际的NLP项⽬中,如果需要计算两个句⼦的相似度,我们只需调⽤gensim模块即可,它是NLP的利器,能够帮助我们处理很多NLP任务。下⾯为⽤gensim计算两个句⼦的相似度的代码:
nt1 ="I love sky, I love a."
nt2 ="I like running, I love reading."
团体心理辅导游戏from nltk import word_tokenize
nts =[nt1, nt2]
texts =[[word for word in word_tokenize(nt)]for nt in nts]
print(texts)
用仍然造句
from gensim import corpora
from gensim.similarities import Similarity
#  语料库
dictionary = corpora.Dictionary(texts)
# 利⽤doc2bow作为词袋模型
corpus =[dictionary.doc2bow(text)for text in texts]
similarity = Similarity('-Similarity-index', corpus, num_features=len(dictionary))
print(similarity)
# 获取句⼦的相似度
new_nnce = nt1
test_corpus_1 = dictionary.doc2bow(word_tokenize(new_nnce))
cosine_sim = similarity[test_corpus_1][1]
print("利⽤gensim计算得到两个句⼦的相似度: %.4f。"%cosine_sim)
注意,如果在运⾏代码时出现以下warning:
gensim\utils.py:1209: UrWarning: detected Windows; aliasing chunkize to chunkize_rial
warnings.warn("detected Windows; aliasing chunkize to chunkize_rial")
gensim\matutils.py:737: FutureWarning: Conversion of the cond argument of issubdtype from `int` to `np.signedinteger` is deprecated. In future, it will be  treated as `np.int32 == np.dtype(int).type`.
if np.issubdtype(vec.dtype, np.int):
如果想要去掉这些warning,则在导⼊gensim模块的代码前添加以下代码即可:
import warnings
warnings.filterwarnings(action='ignore',category=UrWarning,module='gensim')
warnings.filterwarnings(action='ignore',category=FutureWarning,module='gensim')
四,使⽤辑距离算法计算句⼦的相似度
1,编辑距离概念描述
编辑距离,⼜称Levenshtein Distance算法,是指两个字串之间,由⼀个转成另⼀个所需的最少编辑操作次数。许可的编辑操作包括将⼀个字符替换成另⼀个字符,插⼊⼀个字符,删除⼀个字符。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
2,实现原理
找出字符串的编辑距离,即把⼀个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添
加⼀个字符,删除⼀个字符,修改⼀个字符。
3,实现代码

本文发布于:2023-07-11 03:34:07,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1090118.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:向量   相似   编辑
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图