前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nlp自然语言处理中句子相似度计算

nlp自然语言处理中句子相似度计算

作者头像
Python疯子
发布2019-12-02 21:53:53
1.3K0
发布2019-12-02 21:53:53
举报
文章被收录于专栏:Python疯子Python疯子

在做自然语言处理的过程中,现在智能对话比较火,例如智能客服,智能家电,智能音箱等,我们需要获取用户说话的意图,方便做出正确的回答,这里面就涉及到句子相似度计算的问题,那么本节就来了解一下怎么样来用 Python 实现句子相似度的计算。

句子相似度常用的几种方法: 1、编辑距离 2、杰卡德系数计算 3、Word2Vec 计算

编辑距离,英文叫做 Edit Distance,又称 Levenshtein 距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数, 如果它们的距离越大,说明它们越是不同。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如我们有两个字符串:string 和 setting,如果我们想要把 string 转化为 setting,需要这么两步:

第一步,在 s 和 t 之间加入字符 e。 第二步,把 r 替换成 t。 所以它们的编辑距离差就是 2,这就对应着二者要进行转化所要改变(添加、替换、删除)的最小步数。

安装:pip3 install distance

代码语言:javascript
复制
import distance

str1 = "公司地址是哪里"
str2 = "公司在什么位置"

def edit_distance(s1, s2):
    return distance.levenshtein(s1, s2)

print(edit_distance(str1, str2))

想要获取相似的文本的话可以直接设定一个编辑距离的阈值来实现,如设置编辑距离为 2

代码语言:javascript
复制
def edit_distance(s1, s2):
    return distance.levenshtein(s1, s2)

strings = [
    '你在干什么',
    '你在干啥子',
    '你在做什么',
    '你好啊',
    '我喜欢吃香蕉'
]

target = '你在干啥'
results = list(filter(lambda x: edit_distance(x, target) <= 2, strings))
print(results)
# ['你在干什么', '你在干啥子']

杰卡德系数计算

杰卡德系数,英文叫做 Jaccard index, 又称为 Jaccard 相似系数,用于比较有限样本集之间的相似性与差异性。Jaccard 系数值越大,样本相似度越高。

实际上它的计算方式非常简单,就是两个样本的交集除以并集得到的数值,当两个样本完全一致时,结果为 1,当两个样本完全不同时,结果为 0。

算法非常简单,就是交集除以并集,下面我们用 Python 代码来实现一下:

代码语言:javascript
复制
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np

def jaccard_similarity(s1, s2):
    def add_space(s):
        return ' '.join(list(s))

    # 将字中间加入空格
    s1, s2 = add_space(s1), add_space(s2)
    # 转化为TF矩阵
    cv = CountVectorizer(tokenizer=lambda s: s.split())
    corpus = [s1, s2]
    vectors = cv.fit_transform(corpus).toarray()
    # 获取词表内容
    ret = cv.get_feature_names()
    print(ret)
    # 求交集
    numerator = np.sum(np.min(vectors, axis=0))
    # 求并集
    denominator = np.sum(np.max(vectors, axis=0))
    # 计算杰卡德系数
    return 1.0 * numerator / denominator


s1 = '你在干嘛呢'
s2 = '你在干什么呢'
print(jaccard_similarity(s1, s2))

Word2Vec,顾名思义,其实就是将每一个词转换为向量的过程。如果不了解的话可以参考:https://blog.csdn.net/itplus/article/details/37969519

Word2Vec的词向量模型是训练的维基百科的中文语库,这里模型有250维和50维,向量维度越大模型越大,计算越复杂,正常使用时,需要小的模型,发现50维的也差不多,训练模型方式和模型下载请参考:之前文章。 流程: 01、对句子进行拆词 02、去除无用的分词 03、计算句子平均词向量 04、余弦相似度

对句子进行拆词:Python提供了很对可用库,自行选择 去除无用的分词:删除没用的语气词等,为的是减少对计算句子平均词向量的影响。 计算句子平均词向量用的是AVG-W2V,计算句子平均词向量,所以02步尤为重要 余弦相似度:

代码语言:javascript
复制
余弦相似度 np.linalg.norm(求范数)(向量的第二范数为传统意义上的向量长度
dist1=float(np.dot(vec1,vec2)/(np.linalg.norm(vec1)*np.linalg.norm(vec2)))
代码语言:javascript
复制
def key_words_ask_method(sentence1, sentence2):
    '''
    因为无论是#1:AVG-W2V 2:AVG-W2V-TFIDF 都需要求得平均值,
    除数:决定整个数据的大小  被除数:影响平均值
    所以 分词的标准很重要,可通过自定义词典、停用词 和 语义分析进行适当处理
    '''
    vec1 = sentence_to_vec(sentence1)
    vec2 = sentence_to_vec(sentence2)

    # 零向量直接返回
    if (vec1 == np.zeros(WORD_VECTOR_DIM)).all() == True or (vec2 == np.zeros(WORD_VECTOR_DIM)).all() == True:
        return "不符合相似"

    # score = cos(vec1, vec2)
    # print(score)
    # if score < COSINE_CRITICAL_VALUE:
    #     return "1"
    # else:
    #     return "0"

    # 余弦相似度 np.linalg.norm(求范数)(向量的第二范数为传统意义上的向量长度
    dist1=float(np.dot(vec1,vec2)/(np.linalg.norm(vec1)*np.linalg.norm(vec2)))
    print("score:", dist1)
    if dist1 > 0.92:
        return "两个句子相似"
    else:
        return "两个句子不相似"
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档