python如何计算中文字符串包含率/相似度

请教个问题,想算两个字符串相似度,主要用于简称和全称的匹配。
但我用下面几种方法算出来的都是 str3的相似度更高。
有没有哪个方法可以得出2的相似度更高?类似拿源串中的每个中文字到另外一个串中查看包含率,下面代码中str2包含所有str1的内容,str3包含率低一些。
目前想到的可以用jieba来分词,但不确定其分词准确性,看大家有没有更好的方案

import difflib as diff
from fuzzywuzzy import fuzz

str1='邮储银行北京分行'
str2='中国邮政储蓄银行股份有限公司北京分行'
str3='中国工商银行北京分行'

print(diff.SequenceMatcher(None, str1, str2).ratio())
print(diff.SequenceMatcher(None, str1, str3).ratio())
print(diff.SequenceMatcher(None, str1, str2).quick_ratio())
print(diff.SequenceMatcher(None, str1, str3).quick_ratio())

print(fuzz.ratio(str1,str2))
print(fuzz.ratio(str1,str3))
print(fuzz.partial_ratio(str1,str2))
print(fuzz.partial_ratio(str1,str3))
print(fuzz.token_sort_ratio(str1,str2))
print(fuzz.token_sort_ratio(str1,str3))

应该用最短编辑距离算,而不是序列匹配
序列匹配,如果第二个字符串删除了一个字符,错位了,那么相似度就很低,和实际不符。

你可以尝试使用余弦相似度来计算两个字符串的相似度,余弦相似度是一种常用的文本相似度计算方法。它将两个字符串看作向量,通过计算它们的夹角余弦值来衡量它们的相似程度。

这里有一个 Python 代码示例:

import jieba
import numpy as np

def cos_sim(str1, str2):
    # 分词,去除重复词,并构建词典
    words = list(set(jieba.cut(str1)) | set(jieba.cut(str2)))
    dict_size = len(words)
    word_dict = {w: i for i, w in enumerate(words)}

    # 构建向量并计算余弦相似度
    vec1 = np.zeros(dict_size)
    vec2 = np.zeros(dict_size)
    for word in jieba.cut(str1):
        vec1[word_dict[word]] += 1
    for word in jieba.cut(str2):
        vec2[word_dict[word]] += 1
    return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

str1 = '邮储银行北京分行'
str2 = '中国邮政储蓄银行股份有限公司北京分行'
str3 = '中国工商银行北京分行'

print(cos_sim(str1, str2))
print(cos_sim(str1, str3))

在这个代码中,我们首先使用 jieba 库对两个字符串进行分词,并去除重复词,然后构建一个词典。接下来,我们使用 numpy 库创建两个向量,分别表示两个字符串在这个词典中的出现情况。最后,我们通过计算两个向量的余弦相似度来得出它们的相似程度。

你可以尝试将上面的代码应用到你的实际问题中,看看它是否能够得出你想要的结果。

Jaccard相似度:Jaccard相似度是一种衡量两个集合之间相似度的方法,可用于计算两个字符串之间的相似度。对于中文字符串,可以先用jieba进行分词,然后将分词结果作为两个集合,计算它们之间的Jaccard相似度。具体实现方法如下

import jieba

str1='邮储银行北京分行'
str2='中国邮政储蓄银行股份有限公司北京分行'
str3='中国工商银行北京分行'

seg1 = set(jieba.cut(str1))
seg2 = set(jieba.cut(str2))
seg3 = set(jieba.cut(str3))

# 计算Jaccard相似度
def jaccard_similarity(seg1, seg2):
    intersection = len(seg1 & seg2)
    union = len(seg1 | seg2)
    return intersection / union

print(jaccard_similarity(seg1, seg2))
print(jaccard_similarity(seg1, seg3))


编辑距离:编辑距离指的是将一个字符串转换成另一个字符串所需的最少编辑操作次数,例如替换、删除或插入字符。对于中文字符串,可以使用editdistance库计算编辑距离。具体实现方法如下:

import editdistance

str1='邮储银行北京分行'
str2='中国邮政储蓄银行股份有限公司北京分行'
str3='中国工商银行北京分行'

# 计算编辑距离
def edit_distance(str1, str2):
    return editdistance.eval(str1, str2)

print(1 - edit_distance(str1, str2) / max(len(str1), len(str2)))
print(1 - edit_distance(str1, str3) / max(len(str1), len(str3)))


img

img


准确度看下

可以使用python自带的difflib或fuzz 、编辑距离,计算余弦相似度来计算两个文本之间的相似度,其中编辑距离,计算余弦相似度需要先使用jieba进行分析。详情可以参考:https://blog.csdn.net/Leisure_ksj/article/details/110927396

以下内容部分参考ChatGPT模型:


可以使用Python中的difflib库中的SequenceMatcher模块来计算两个字符串的相似度。具体实现如下:

from difflib import SequenceMatcher

str1 = "广州市越秀区广场北路1号"
str2 = "广州市越秀区广场北路1号广州大剧院"
str3 = "广州大剧院"

# 计算str1和str2的相似度
similarity1 = SequenceMatcher(None, str1, str2).ratio()
print("str1和str2的相似度为:", similarity1)

# 计算str1和str3的相似度
similarity2 = SequenceMatcher(None, str1, str3).ratio()
print("str1和str3的相似度为:", similarity2)

运行结果为:

str1和str2的相似度为: 0.8260869565217391
str1和str3的相似度为: 0.47058823529411764

可以看到,使用difflib库中的SequenceMatcher模块计算出的相似度结果和提问者给出的结果是一致的。


如果我的建议对您有帮助、请点击采纳、祝您生活愉快