Найдите показатель сходства между двумя строками

Как мне узнать вероятность того, что строка будет похожа на другую строку в Python?

Я хочу получить десятичное значение, например 0,9 (то есть 90%) и т. Д. Желательно со стандартным Python и библиотекой.

e.g.

similar("Apple","Appel") #would have a high prob.

similar("Apple","Mango") #would have a lower prob.

person tenstar    schedule 30.06.2013    source источник
comment
Я не думаю, что термин «вероятность» здесь подходит. В любом случае см. http://stackoverflow.com/questions/682367/good-python-modules-for-fuzzy-string-comparison   -  person NPE    schedule 30.06.2013
comment
Слово, которое вы ищете, - это соотношение, а не вероятность.   -  person Inbar Rose    schedule 30.06.2013
comment
Взгляните на расстояние Хэмминга.   -  person Diana    schedule 30.06.2013
comment
Фраза - это «метрика сходства», но есть несколько метрик сходства (Жаккар, косинус, Хэмминга, Левеншейна и т. Д.), Поэтому вам нужно указать, какие. В частности, вам нужна метрика сходства между строками; @hbprotoss перечислил несколько.   -  person smci    schedule 26.04.2018
comment
Мне нравятся биграммы из stackoverflow.com/questions/653157/   -  person MarkHu    schedule 09.10.2020


Ответы (13)


Есть встроенный.

from difflib import SequenceMatcher

def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

Используй это:

>>> similar("Apple","Appel")
0.8
>>> similar("Apple","Mango")
0.0
person Inbar Rose    schedule 30.06.2013
comment
Посмотрите этот отличный ответ, сравнивая модуль SequenceMatcher и python-Levenshtein. stackoverflow.com/questions/6690739/ - person ssoler; 09.02.2015
comment
Интересная статья и инструмент: Chairnerd.seatgeek.com/ - person DevLounge; 05.01.2016
comment
Я настоятельно рекомендую проверить весь документ difflib docs.python.org/2/library/ diffflib.html есть встроенный get_close_matches, хотя я нашел sorted(... key=lambda x: difflib.SequenceMatcher(None, x, search).ratio(), ...) более надежным, с пользовательскими sorted(... .get_matching_blocks())[-1] > min_match проверками - person ThorSummoner; 15.09.2016
comment
@ThorSummoner обращает внимание на очень полезную функцию (get_closest_matches). Это удобная функция, которая может быть тем, что вы ищете, AKA прочитайте документацию! В моем конкретном приложении я выполнял некоторую базовую проверку ошибок / сообщал пользователю, предоставляющему неверный ввод, и этот ответ позволяет мне сообщать им о потенциальных совпадениях и, в чем было сходство. Если вам не нужно показывать сходство, обязательно посмотрите get_closest_matches - person svenevs; 04.09.2017
comment
Это сработало отлично. Просто и эффективно. Спасибо :) - person Karthic Srinivasan; 09.05.2020

Думаю, может быть, вы ищете алгоритм, описывающий расстояние между строками. Вот некоторые из них, на которые вы можете сослаться:

  1. Расстояние Хэмминга
  2. Расстояние Левенштейна
  3. Расстояние Дамерау – Левенштейна
  4. Расстояние Яро – Винклера
person hbprotoss    schedule 30.06.2013

Решение # 1: встроенный Python

используйте SequenceMatcher из difflib

плюсы: собственная библиотека Python, дополнительный пакет не требуется.
минусы: слишком ограничен, существует множество других хороших алгоритмов для определения схожести строк.

example :
>>> from difflib import SequenceMatcher
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75

Решение №2: библиотека jellyfish

это очень хорошая библиотека с хорошим освещением и несколькими выпусками. он поддерживает:
- Расстояние Левенштейна
- Расстояние Дамерау-Левенштейна
- Расстояние Яро
- Расстояние Яро-Винклера
- Сравнение рейтингового подхода
- Расстояние Хэмминга

плюсы: простота использования, широкий спектр поддерживаемых алгоритмов, протестировано.
минусы: не встроенная библиотека.

пример:

>>> import jellyfish
>>> jellyfish.levenshtein_distance(u'jellyfish', u'smellyfish')
2
>>> jellyfish.jaro_distance(u'jellyfish', u'smellyfish')
0.89629629629629637
>>> jellyfish.damerau_levenshtein_distance(u'jellyfish', u'jellyfihs')
1
person Iman Mirzadeh    schedule 08.09.2017

Fuzzy Wuzzy - это пакет, который реализует расстояние Левенштейна в Python с некоторыми вспомогательными функциями, которые могут помочь в определенных ситуациях, когда вы можете хотите, чтобы две разные строки считались идентичными. Например:

>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    91
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    100
person BLT    schedule 18.01.2017

Вы можете создать такую ​​функцию, как:

def similar(w1, w2):
    w1 = w1 + ' ' * (len(w2) - len(w1))
    w2 = w2 + ' ' * (len(w1) - len(w2))
    return sum(1 if i == j else 0 for i, j in zip(w1, w2)) / float(len(w1))
person Saullo G. P. Castro    schedule 30.06.2013
comment
но подобный ('аппел', 'яблоко') выше, чем аналогичный ('аппел', 'обезьяна') - person tenstar; 30.06.2013
comment
Ваша функция сравнит данную строку с другими строками. Мне нужен способ вернуть строку с наивысшим коэффициентом сходства - person answerSeeker; 23.02.2017
comment
@SaulloCastro, if self.similar(search_string, item.text()) > 0.80: пока работает. Спасибо, - person answerSeeker; 23.02.2017

Пакет distance включает расстояние Левенштейна:

import distance
distance.levenshtein("lenvestein", "levenshtein")
# 3
person Enrique Pérez Herrero    schedule 10.04.2017

Обратите внимание: difflib.SequenceMatcher только находит самую длинную непрерывную совпадающую подпоследовательность, часто это не то, что нужно, например:

>>> a1 = "Apple"
>>> a2 = "Appel"
>>> a1 *= 50
>>> a2 *= 50
>>> SequenceMatcher(None, a1, a2).ratio()
0.012  # very low
>>> SequenceMatcher(None, a1, a2).get_matching_blocks()
[Match(a=0, b=0, size=3), Match(a=250, b=250, size=0)]  # only the first block is recorded

Обнаружение сходства между двумя строками тесно связано с концепцией попарного выравнивания последовательностей в биоинформатике. Для этого существует множество специализированных библиотек, включая biopython. В этом примере реализуется алгоритм Нидлмана Вунша:

>>> from Bio.Align import PairwiseAligner
>>> aligner = PairwiseAligner()
>>> aligner.score(a1, a2)
200.0
>>> aligner.algorithm
'Needleman-Wunsch'

Использование biopython или другого пакета биоинформатики более гибкое, чем любая часть стандартной библиотеки python, поскольку доступно множество различных схем и алгоритмов оценки. Кроме того, вы можете получить соответствующие последовательности для визуализации происходящего:

>>> alignment = next(aligner.align(a1, a2))
>>> alignment.score
200.0
>>> print(alignment)
Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-
|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-
App-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-el
person Chris_Rands    schedule 04.12.2019

Встроенная функция SequenceMatcher очень медленная при вводе большого объема, вот как это можно сделать с помощью diff-match-patch:

from diff_match_patch import diff_match_patch

def compute_similarity_and_diff(text1, text2):
    dmp = diff_match_patch()
    dmp.Diff_Timeout = 0.0
    diff = dmp.diff_main(text1, text2, False)

    # similarity
    common_text = sum([len(txt) for op, txt in diff if op == 0])
    text_length = max(len(text1), len(text2))
    sim = common_text / text_length

    return sim, diff
person damio    schedule 30.04.2018

Вы можете найти большинство методов схожести текста и способы их расчета по этой ссылке: https://github.com/luozhouyang/python-string-similarity#python-string-similarity Вот несколько примеров;

  • Нормализованный, метрический, подобие и расстояние

  • (Нормализованное) сходство и расстояние

  • Метрические расстояния

  • Опоясывающий лишай (н-грамм) на основе сходства и расстояния
  • Левенштейн
  • Нормализованный Левенштейн
  • Взвешенный Левенштейн
  • Дамерау-Левенштейн
  • Оптимальное выравнивание струн
  • Яро-Винклер
  • Самая длинная общая подпоследовательность
  • Метрическая самая длинная общая подпоследовательность
  • N-грамм
  • Алгоритмы на основе Shingle (n-грамм)
  • Q-грамм
  • Косинусное сходство
  • Индекс Жаккара
  • Коэффициент Соренсена-Дайса
  • Коэффициент перекрытия (например, Шимкевича-Симпсона)
person Mike    schedule 09.04.2020

BLEUscore

BLEU, или Bilingual Evaluation Understudy, - это оценка для сравнения предполагаемого перевода текста с одним или несколькими справочными переводами.

Идеальное совпадение дает оценку 1,0, тогда как полное несоответствие дает оценку 0,0.

Хотя он разработан для перевода, его можно использовать для оценки текста, созданного для набора задач обработки естественного языка.

Код:

import nltk
from nltk.translate import bleu
from nltk.translate.bleu_score import SmoothingFunction
smoothie = SmoothingFunction().method4

C1='Text'
C2='Best'

print('BLEUscore:',bleu([C1], C2, smoothing_function=smoothie))

Примеры: путем обновления C1 и C2.

C1='Test' C2='Test'

BLEUscore: 1.0

C1='Test' C2='Best'

BLEUscore: 0.2326589746035907

C1='Test' C2='Text'

BLEUscore: 0.2866227639866161

Вы также можете сравнить схожесть предложений:

C1='It is tough.' C2='It is rough.'

BLEUscore: 0.7348889200874658

C1='It is tough.' C2='It is tough.'

BLEUscore: 1.0
person Reema Q Khan    schedule 15.02.2021

Как упоминалось выше, существует множество показателей для определения сходства и расстояния между строками. Я дам свои 5 центов, показав пример Jaccard similarity с Q-Grams и пример с edit distance.

Библиотеки

from nltk.metrics.distance import jaccard_distance
from nltk.util import ngrams
from nltk.metrics.distance  import edit_distance

Сходство по Жаккару

1-jaccard_distance(set(ngrams('Apple', 2)), set(ngrams('Appel', 2)))

и получаем:

0.33333333333333337

А для Apple и Mango

1-jaccard_distance(set(ngrams('Apple', 2)), set(ngrams('Mango', 2)))

и получаем:

0.0

Изменить расстояние

edit_distance('Apple', 'Appel')

и получаем:

2

И наконец,

edit_distance('Apple', 'Mango')

и получаем:

5

Косинусное сходство на Q-граммах (q = 2)

Другое решение - работать с библиотекой textdistance. Приведу пример Cosine Similarity

import textdistance
1-textdistance.Cosine(qval=2).distance('Apple', 'Appel')

и получаем:

0.5
person George Pipis    schedule 10.09.2020

Расстояние по тексту:

TextDistance - библиотека Python для сравнения расстояний между двумя и более последовательностями по многим алгоритмам. У него есть Textdistance.

  • 30+ алгоритмов
  • Реализация на чистом питоне
  • Простое использование
  • Сравнение более двух последовательностей
  • Некоторые алгоритмы имеют более одной реализации в одном классе.
  • Дополнительное использование numpy для максимальной скорости.

Пример1:

import textdistance
textdistance.hamming('test', 'text')

Вывод:

1

Пример2:

import textdistance

textdistance.hamming.normalized_similarity('test', 'text')

Вывод:

0.75

Спасибо и ура !!!

person D_Raja    schedule 19.10.2020

Вот что я подумал:

import string

def match(a,b):
    a,b = a.lower(), b.lower()
    error = 0
    for i in string.ascii_lowercase:
            error += abs(a.count(i) - b.count(i))
    total = len(a) + len(b)
    return (total-error)/total

if __name__ == "__main__":
    print(match("pple inc", "Apple Inc."))
person David Emmanuel    schedule 01.12.2020