Нечеткое сравнение строк

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

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

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

Text: Sample

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

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

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

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

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

 Franck Dernoncourt07 июн. 2015 г., 09:27
@ FelixKling Жаль, что его удалили ....
 naught10101 февр. 2018 г., 00:49
Почему строки 1 и 24 должны быть равны нулю? У них точно такое же первое предложение. 2-е предложение в 1 почти такое же, как предложение 2 + 3 в 24 (единственное отличие - «нет», и дополнительное «я не был») .. Численно они ОЧЕНЬ похожи. Семантически они разные, но если вы спрашиваете компьютер, чтобы понять значение предложения, то вы можете просить слишком много.
 Felix Kling30 апр. 2012 г., 13:45
Кажется, вы хотите вычислить Левенштейнское расстояние (или какой-то другой расстояние метрика). Если у вас сейчас максимальное расстояние, вам просто нужно масштабировать баллы до диапазон[0,1].
 jacksonstephenc30 апр. 2012 г., 14:32
Спасибо за помощь @ Феликс Клин, возможно, путь к difflib.

Ответы на вопрос(4)

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 Wilson09 июн. 2017 г., 12:29
Как извлечь только текст
 Jaffer Wilson10 июн. 2017 г., 03:59
Спасибо .. :) Я обязательно воспользуюсь этим.
 hobs10 июн. 2017 г., 02:10
@ JafferWilson так же, как вы извлекаете первую строку, последний «столбец» из любого списка кортежей python:fs.get(query)[0][-1]

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

 jacksonstephenc30 апр. 2012 г., 14:30
Спасибо, Мак. Это именно то, что я ищу. Я просто не могу понять, каким образом я могу заставить программу определить, является ли предложение противоположным оригиналу. Есть ли в python библиотека, в которой мне помогут грамматические ситуации решить эту проблему?
 Felix Kling30 апр. 2012 г., 14:34
@ user1365664: Я сомневаюсь, что такая вещь существует, если вы не укажете, что означает «противоположный» в данном случае. Являетсяab противоположноzy? Или этоab противоположноba? так далее
 hangtwenty30 апр. 2012 г., 15:57
@ user1365664 Не забудьте принять этот ответ, если вы удовлетворены.
 AKX30 апр. 2012 г., 14:34
@ user1365664 - Это звучит как очень сложная проблема, но каноническим ответом на все, что касается естественных языков в Python, является NLTK, Nltk.org.
 Felix Kling30 апр. 2012 г., 15:07
@ user1365664: В этом случае вы можете взглянуть на NLP и анализ мнений.

Есть пакет под названием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)
 user273818301 сент. 2017 г., 17:23
got предупреждение, "lib / python2.7 / site-packages / fuzzywuzzy / fuzz.py: 35: предупреждение пользователя: Используя медленный чистый Python SequenceMatcher. Установите python-Levenshtein, чтобы удалить это предупреждение warnings.warn («Использование медленного чистого python SequenceMatcher. Установите python-Levenshtein, чтобы удалить это предупреждение»)"
 Alexander19 дек. 2018 г., 21:38
@ user2738183pip install python-Levenshtein FuzzyWuzzy использует difflib, который является частью стандартной библиотеки. Однако для повышения производительности вы можете установить модуль python-Levenshtein для сопоставления последовательностей, как описано выше. Pypi.org / проект / питон-Левенштейна
 ToonZ16 авг. 2016 г., 19:17
Пытаюсь нечетко. Нашли, если заменить "New York Giants" на, скажем, "New York Giants Dallas Cowboys", process.extract ("New York Jets", choices, limit = 2) производит [('New York Jets', 100), ( «Нью-йоркские гиганты Даллас Ковбойз», 86)]. Знаете ли вы, почему возрастает частота совпадений во втором нечетком матче? Это не имеет особого смысла.

Идентификация парафразы, которая является активной областью исследований в области обработки естественного языка. Я связал несколько современных статей, многие из которых вы можете найти на 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 который ты хотел найти их оценки.

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

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

Ваш ответ на вопрос