Подтвердить что ты не робот

Сравнение нечетких строк

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

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

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

Текст: Пример

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

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

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

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

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

4b9b3361

Ответ 1

Существует пакет под названием 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

Коэффициент сортировки токенов

>>> 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

Соотношение токенов

>>> 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)

Ответ 2

В стандартной библиотеке есть модуль (называемый difflib), который может сравнивать строки и возвращать оценку на основе их сходства. Класс SequenceMatcher должен делать то, что вам нужно.

EDIT: Маленький пример из приглашения 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

НТН!

Ответ 3

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

from fuzzyset import FuzzySet
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 в вашем fuzzyset.

Ответ 4

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

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

Если вы заинтересованы в подобном сходстве, вы можете использовать Skip-Thoughts. Установите программное обеспечение в соответствии с руководствами 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_sentences 1, который вы хотели бы найти в своих оценках.

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

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