两个字符串的匹配比例是多少?

2024-05-23 22:32:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两列疾病名称,我必须尝试匹配最佳选项。我尝试在python中使用“SequenceMatcher”模块和“fuzzyfuzzy”模块,结果令人惊讶。我把结果和我的疑问贴在下面:

考虑到有一种疾病“肝肿瘤”,我需要将其与“癌症,肝脏”或“癌症,乳腺”的最佳匹配名称相匹配。现在很明显,既然肝是一个匹配的词,它应该很容易找到“癌症,肝”作为答案,但这并没有发生。我想知道原因和一个更好的方式来匹配python。你知道吗

from difflib import SequenceMatcher

s1 = 'liver neoplasms'
s2 = 'cancer, liver'

SequenceMatcher(None, s1, s2).ratio() 
# Answer = 0.3571

s2 = 'cancer, breast'
SequenceMatcher(None, s1, s2).ratio()
# Answer = 0.4137 

# fuzzy.ratio also has the same results.

我的疑问是癌症、乳腺癌怎么比癌症、肝癌更相配。我还可以使用哪种技术来正确地完成这个任务?你知道吗

谢谢:)


Tags: 模块answer名称none选项疾病癌症ratio
3条回答

似乎difflib.SequenceMatcherfuzzywuzzy使用相同的机制来确定相似性。即Levenshtein Distance,可以有效地概括为“将一个字符串转换为另一个字符串所需的修改次数”。你知道吗

这里,根据this calculator'liver neoplasms''cancer, liver'之间的Levenshtein距离是13。同时,'liver neoplasms''cancer, breast'之间的距离为12-稍小。你知道吗

Levenshtein距离似乎不是解决这个问题的理想方法。你知道吗


在您的情况下,我将尝试使用某种形式的关键字匹配。我对这样做的适当技巧不太了解,但我的直觉是将输入拆分为关键字,将可能的输出拆分为关键字:

input_keywords = 'liver neoplasms'.split()
possibility_keywords = {title: title.split(', ') for title in ('cancer, breast', 'cancer, liver')}

然后做一些加权匹配(无论哪一组可能的关键字最接近输入的关键字集-你可能需要创造性地找出有效的方法来计算这个)或关键字检测。例如:

def ratio(input_keywords, possibility_keywords):
    return sum(
        min(
            SequenceMatcher(None, inp_kw, poss_kw).ratio() for poss_kw in possibility_keywords
        ) for inp_kw in input_keywords
     )

粗略地看一眼就发现this paper可能是相关的。或者其他答案中提到的余弦相似算法。你知道吗

下面是两个字符串之间的余弦相似性匹配算法。你知道吗

请参考下面的链接来解释这个理论

https://blog.nishtahir.com/2015/09/19/fuzzy-string-matching-using-cosine-similarity/

import re
import math
from collections import Counter


def get_cosine(vec1, vec2):
    intersection = set(vec1.keys()) & set(vec2.keys())
    numerator = sum([vec1[x] * vec2[x] for x in intersection])

    sum1 = sum([vec1[x]**2 for x in vec1.keys()])
    sum2 = sum([vec2[x]**2 for x in vec2.keys()])
    denominator = math.sqrt(sum1) * math.sqrt(sum2)

    if not denominator:
        return 0.0
    else:
        return float(numerator) / denominator


def text_to_vector(text):
    word = re.compile(r'\w+')
    words = word.findall(text)
    return Counter(words)


def get_result(content_a, content_b):
    text1 = content_a
    text2 = content_b

    vector1 = text_to_vector(text1)
    vector2 = text_to_vector(text2)

    cosine_result = get_cosine(vector1, vector2)
    return cosine_result


print(get_result('liver neoplasms', 'cancer, liver'))
print(get_result('liver neoplasms', 'cancer, breast'))

这些类型的匹配器没有语义理解。他们只是计算匹配的字符数。有些人比其他人更老练。你知道吗

距离可能会有所帮助。见https://github.com/ztane/python-Levenshtein。你知道吗

from difflib import SequenceMatcher from Levenshtein import distance

s1 = 'liver neoplasms' s2 = 'cancer, liver'

print('Sequence-matcher: ', SequenceMatcher(None, s1, s2).ratio()) 
# Answer = 0.35...

print('Levenshtein: ', distance(s1, s2))
# Answer = 13

s2 = 'cancer, breast' 

print('Sequence-matcher: ', SequenceMatcher(None, s1, s2).ratio()) 
# Answer = 0.41...

print('Levenshtein: ', distance(s1, s2))
# Answer = 12

相关问题 更多 >