【问题标题】:Get similarity percentage on multiple strings获取多个字符串的相似度百分比
【发布时间】:2018-12-16 17:27:08
【问题描述】:

在 Python 中是否有任何函数可以接受多行字符串并返回它们具有多少相似度的百分比? SequenceMatcher 之类的东西,但适用于多个字符串。

例如我们有以下句子

Hello how are you?
Hi how are you?
hi how are you doing?
Hey how is your day?

我希望能够根据句子彼此的相似程度得到一个百分比

假设我们有这三个句子

Hello how are you?
Hello how are you?
Hello how are you?

那么我们应该得到 100% 的相似度

但是如果我们有

Hello how are you?
Hello how are you?
hola como estats?

那么我们应该得到一个相似度约为 67% 的数字。

【问题讨论】:

  • 也许您可以提供更多信息?到目前为止,您尝试了哪些代码,预期的输出是什么?
  • 您可以使用mapitertools.product 来构建相似度矩阵。不过,您必须定义自己的指标:map(metric, product(strings, strings))
  • 只是想建议difflib,但显然你已经知道了。除了比较所有对的成对相似性之外,多个字符串的相似性应该如何工作?你能展示一些示例输入/输出吗?
  • 它应该根据我们拥有的总句子返回一个数字(这是它们相似程度的百分比)。我将更新问题以改进我的示例
  • 你的第二个例子“大约 67%”怎么样?那是一对具有完全相似性的对和两对具有非常低相似性的对。对我来说,这更像是 35-40% 的相似性。还是你也想考虑句子意思的相似度,而不是单纯的单词和字母的相似度?

标签: python string similarity sentence-similarity


【解决方案1】:

您可以使用pandas 对数据框进行操作,itertools.combinations 用于计算列表中 2 个字符串的组合,difflib.SequenceMatcher 用于相似度计算:

import pandas as pd
import itertools
from difflib import SequenceMatcher

def similarity(a,b):
    seq = SequenceMatcher(a=a, b=b)
    return seq.ratio()    

strings = ['Hello how are you?', 'Hi how are you?', 'hi how are you doing?', 'Hey how is your day?']
combinations = itertools.combinations(strings,2)

df = pd.DataFrame(list(combinations))
df['similarity'] = df.apply(lambda x: similarity(x[0],x[1]), axis=1)

df.similarity.mean()
0.68

【讨论】:

  • 这正是我想要的,谢谢。如果我能把它转换成Java就更好了,看起来有一个名为JPanda for Java的库
  • 哦,有趣的是从未听说过那个库。我没有 Java 经验。
  • 这里不需要使用pandasnumpy 就可以了,而且开销更少。
【解决方案2】:

天真地,您可以按照以下方式做一些事情:

from collections import Counter 
from itertools import zip_longest

cases=[('Hello how are you?','Hello how are you?','Hello how are you?'),
       ('Hello how are you?','Hello how are you?','hola como estats?')]

for t in cases:    
    sums=[]
    for st in zip_longest(*t,fillvalue='|'):
        sums.append((st,(len(Counter(st))-1)/len(st)))
    print(t)
    print('\n'.join(map(str, sums)))   

打印:

('Hello how are you?', 'Hello how are you?', 'Hello how are you?')
(('H', 'H', 'H'), 0.0)
(('e', 'e', 'e'), 0.0)
(('l', 'l', 'l'), 0.0)
(('l', 'l', 'l'), 0.0)
(('o', 'o', 'o'), 0.0)
((' ', ' ', ' '), 0.0)
(('h', 'h', 'h'), 0.0)
(('o', 'o', 'o'), 0.0)
(('w', 'w', 'w'), 0.0)
((' ', ' ', ' '), 0.0)
(('a', 'a', 'a'), 0.0)
(('r', 'r', 'r'), 0.0)
(('e', 'e', 'e'), 0.0)
((' ', ' ', ' '), 0.0)
(('y', 'y', 'y'), 0.0)
(('o', 'o', 'o'), 0.0)
(('u', 'u', 'u'), 0.0)
(('?', '?', '?'), 0.0)
('Hello how are you?', 'Hello how are you?', 'hola como estats?')
(('H', 'H', 'h'), 0.3333333333333333)
(('e', 'e', 'o'), 0.3333333333333333)
(('l', 'l', 'l'), 0.0)
(('l', 'l', 'a'), 0.3333333333333333)
(('o', 'o', ' '), 0.3333333333333333)
((' ', ' ', 'c'), 0.3333333333333333)
(('h', 'h', 'o'), 0.3333333333333333)
(('o', 'o', 'm'), 0.3333333333333333)
(('w', 'w', 'o'), 0.3333333333333333)
((' ', ' ', ' '), 0.0)
(('a', 'a', 'e'), 0.3333333333333333)
(('r', 'r', 's'), 0.3333333333333333)
(('e', 'e', 't'), 0.3333333333333333)
((' ', ' ', 'a'), 0.3333333333333333)
(('y', 'y', 't'), 0.3333333333333333)
(('o', 'o', 's'), 0.3333333333333333)
(('u', 'u', '?'), 0.3333333333333333)
(('?', '?', '|'), 0.3333333333333333)

所以你在第二种情况下的差异会略小于 1/3,因为在最后的西班牙语句子中有两个字符是相同的。

然后将该序列简化为总差。

【讨论】:

    【解决方案3】:

    您可以使用numpyitertools.product 创建成对相似度矩阵。然后,您可以从该矩阵中提取所需的相似性度量。在任何情况下,您都需要提出适合您问题的指标(即成对量词)。

    import itertools as it
    import numpy as np
    
    
    def similarity_check(sentences, metric):
        pairwise = np.fromiter(map(
            metric,
            it.product(sentences, sentences)),
        dtype=float).reshape(len(sentences), -1)
        # return pairwise[np.triu_indices(len(sentences), 1)].mean()  # Option 1.
        return pairwise.mean(axis=0).max()  # Option 2.
    
    
    print(similarity_check([
        'Hello how are you?',
        'Hello how are you?',
        'Hello how are you?'
    ], lambda x: float(x[0] == x[1])))  # Plug in your own metric here.
    
    print(similarity_check([
        'Hello how are you?',
        'Hello how are you?',
        'hola como estats?'
    ], lambda x: float(x[0] == x[1])))  # Plug in your own metric here.
    

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      • 2019-07-07
      • 2012-06-16
      • 2019-07-11
      相关资源
      最近更新 更多