Вопрос по python – Нечеткое сравнение строк

54

То, что я пытаюсь завершить, - это программа, которая читает файл и сравнивает каждое предложение в соответствии с исходным предложением. Предложение, которое идеально соответствует оригиналу, получит 1 балл, а предложение, которое является полностью противоположным, получит 0. Все другие нечеткие предложения получат оценку от 1 до 0.

Я не уверен, какую операцию использовать, чтобы позволить мне завершить это в Python 3.

Я включил образец текста, в котором текст 1 является оригиналом, а другие предыдущие строки - сравнения.

Text: Sample

Текст 1: Это была темная и бурная ночь. Я был один, сидя на красном стуле. Я был не совсем один, у меня было три кошки.

Текст 20: Это была темная и бурная ночь. Я был один, сидя на малиновом стуле. Я был не совсем один, так как у меня было три кошачьих // Должен набрать рекорд, но не 1

Текст 21: Это была темная и бурная ночь. Я был один, сидя на малиновой кафедре. Я был не совсем один, так как у меня было три кошачьих // Должен быть ниже, чем текст 20

Текст 22: Я был один, сидя на алой кафедре. Я был не совсем один, у меня было три кошачьих. Это была темная и бурная ночь. // Должен быть ниже, чем текст 21, но НЕ 0

Текст 24: Это была темная и бурная ночь. Я был не один. Я не сидел на красном стуле. У меня было три кошки. // Должен набрать 0!

Спасибо за помощь @ Феликс Клин, возможно, путь к difflib. jacksonstephenc
Кажется, вы хотите вычислить Левенштейнское расстояние (или какой-то другой расстояние метрика). Если у вас сейчас максимальное расстояние, вам просто нужно масштабировать баллы до диапазон[0,1]. Felix Kling
@ FelixKling Жаль, что его удалили .... Franck Dernoncourt
Почему строки 1 и 24 должны быть равны нулю? У них точно такое же первое предложение. 2-е предложение в 1 почти такое же, как предложение 2 + 3 в 24 (единственное отличие - «нет», и дополнительное «я не был») .. Численно они ОЧЕНЬ похожи. Семантически они разные, но если вы спрашиваете компьютер, чтобы понять значение предложения, то вы можете просить слишком много. naught101

Ваш Ответ

4   ответа
87

Есть пакет под названиемfuzzywuzzy. Установить через pip:

pip install fuzzywuzzy

Простое использование:

>>> from fuzzywuzzy import fuzz
>>> fuzz.ratio("this is a test", "this is a test!")
    96

Пакет построен поверхdifflib. Вы спросите, почему бы просто не использовать это? Помимо того, что он немного проще, он имеет ряд различных методов сопоставления (например, нечувствительность к порядку следования токенов, частичное сопоставление строк), которые делают его более мощным на практике.process.extractункции @ особенно полезны: найдите лучшие подходящие строки и соотношения из набора. Из их readme:

Частичное соотношение

>>> fuzz.partial_ratio("this is a test", "this is a test!")
    100

Token Sort Ratio

>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    90
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    100

Token Set Ratio

>>> fuzz.token_sort_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
    84
>>> fuzz.token_set_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
    100

Процес

>>> choices = ["Atlanta Falcons", "New York Jets", "New York Giants", "Dallas Cowboys"]
>>> process.extract("new york jets", choices, limit=2)
    [('New York Jets', 100), ('New York Giants', 78)]
>>> process.extractOne("cowboys", choices)
    ("Dallas Cowboys", 90)
got предупреждение, "lib / python2.7 / site-packages / fuzzywuzzy / fuzz.py: 35: предупреждение пользователя: Используя медленный чистый Python SequenceMatcher. Установите python-Levenshtein, чтобы удалить это предупреждение warnings.warn («Использование медленного чистого python SequenceMatcher. Установите python-Levenshtein, чтобы удалить это предупреждение»)" user2738183
@ user2738183pip install python-Levenshtein FuzzyWuzzy использует difflib, который является частью стандартной библиотеки. Однако для повышения производительности вы можете установить модуль python-Levenshtein для сопоставления последовательностей, как описано выше. Pypi.org / проект / питон-Левенштейна Alexander
Пытаюсь нечетко. Нашли, если заменить "New York Giants" на, скажем, "New York Giants Dallas Cowboys", process.extract ("New York Jets", choices, limit = 2) производит [('New York Jets', 100), ( «Нью-йоркские гиганты Даллас Ковбойз», 86)]. Знаете ли вы, почему возрастает частота совпадений во втором нечетком матче? Это не имеет особого смысла. ToonZ
76

difflib) которые могут сравнивать строки и возвращать оценки на основе их сходства.SequenceMatcher класс должен делать то, что вы после.

РЕДАКТИРОВАТЬ Небольшой пример из приглашения Python:

>>> from difflib import SequenceMatcher as SM
>>> s1 = ' It was a dark and stormy night. I was all alone sitting on a red chair. I was not completely alone as I had three cats.'
>>> s2 = ' It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines.'
>>> SM(None, s1, s2).ratio()
0.9112903225806451

HTH

Спасибо, Мак. Это именно то, что я ищу. Я просто не могу понять, каким образом я могу заставить программу определить, является ли предложение противоположным оригиналу. Есть ли в python библиотека, в которой мне помогут грамматические ситуации решить эту проблему? jacksonstephenc
@ user1365664: В этом случае вы можете взглянуть на NLP и анализ мнений. Felix Kling
@ user1365664 Не забудьте принять этот ответ, если вы удовлетворены. hangtwenty
@ user1365664 - Это звучит как очень сложная проблема, но каноническим ответом на все, что касается естественных языков в Python, является NLTK, Nltk.org. AKX
@ user1365664: Я сомневаюсь, что такая вещь существует, если вы не укажете, что означает «противоположный» в данном случае. Являетсяab противоположноzy? Или этоab противоположноba? так далее Felix Kling
13

fuzzyset намного быстрее чемfuzzywuzzy (difflib) для индексации и поиска.

corpus = """It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines
    It was a murky and tempestuous night. I was all alone sitting on a crimson cathedra. I was not completely alone as I had three felines
    I was all alone sitting on a crimson cathedra. I was not completely alone as I had three felines. It was a murky and tempestuous night.
    It was a dark and stormy night. I was not alone. I was not sitting on a red chair. I had three cats."""
corpus = [line.lstrip() for line in corpus.split("\n")]
fs = FuzzySet(corpus)
query = "It was a dark and stormy night. I was all alone sitting on a red chair. I was not completely alone as I had three cats."
fs.get(query)
# [(0.873015873015873, 'It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines')]

Предупреждение: будьте осторожны, чтобы не перепутатьunicode а такжеbytes в твоем нечетком наборе.

Спасибо .. :) Я обязательно воспользуюсь этим. Jaffer Wilson
@ JafferWilson так же, как вы извлекаете первую строку, последний «столбец» из любого списка кортежей python:fs.get(query)[0][-1] hobs
Как извлечь только текст Jaffer Wilson
1

Идентификация парафразы, которая является активной областью исследований в области обработки естественного языка. Я связал несколько современных статей, многие из которых вы можете найти на GitHub с открытым исходным кодом.

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

Если вы заинтересованы в подобном сходстве, вы можете использовать Пропуск Мысль. Установите программное обеспечение в соответствии с руководствами GitHub и перейдите к разделу обнаружения перефразирования в файле readme:

import skipthoughts
model = skipthoughts.load_model()
vectors = skipthoughts.encode(model, X_sentences)

Это преобразует ваши предложения (X_sentences) в векторы. Позже вы можете найти сходство двух векторов по:

similarity = 1 - scipy.spatial.distance.cosine(vectors[0], vectors[1])

где мы предполагаем вектор [0] и вектор1 - вектор, соответствующий X_sentences [0], X_sentences1 который ты хотел найти их оценки.

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

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

Похожие вопросы