автоматически исправлять слова из списка в python - PullRequest
3 голосов
/ 30 апреля 2019

Я хочу автоматически исправить слова, которые есть в моем list.

Скажем, у меня есть список

kw = ['tiger','lion','elephant','black cat','dog']

Я хочу проверить, появились ли эти слова в моем предложении,Если они написаны неправильно, я хочу исправить их.Я не собираюсь трогать другие слова, кроме указанного в списке.

Теперь у меня есть список str

s = ["I saw a tyger","There are 2 lyons","I mispelled Kat","bulldogs"]

Ожидаемый результат:

['tiger','lion',None,'dog']

Мои усилия:

import difflib

op = [difflib.get_close_matches(i,kw,cutoff=0.5) for i in s]
print(op)

Мой вывод:

[[], [], [], ['dog']]

Проблема с кодом вышеЯ хочу сравнить все предложение, и мой список kw может содержать более 1 слова (до 4-5 слов).

Если я уменьшу значение cutoff, оно начнет возвращать слова, которыеэто не должно.

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

Так есть ли способ реализовать это?

Я исследовал еще несколько библиотек, таких как autocorrect, hunspell и т. Д., Но безуспешно.

Ответы [ 3 ]

2 голосов
/ 30 апреля 2019

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

def find_similar_word(s, kw, thr=0.5):
    from difflib import SequenceMatcher
    out = []
    for i in s:
        f = False
        for j in i.split():
            for k in kw:
                if SequenceMatcher(a=j, b=k).ratio() > thr:
                    out.append(k)
                    f = True
                if f:
                    break
            if f:
                break
        else:
            out.append(None)    
    return out

Выход

find_similar_word(s, kw)
['tiger', 'lion', None, 'dog'] 
2 голосов
/ 30 апреля 2019

Вы можете реализовать что-то на основе levenshtein distance.

Интересно отметить реализацию эластичного поиска: https://www.elastic.co/guide/en/elasticsearch/guide/master/fuzziness.html

Очевидно, что Бибер далеко от бобра - они слишком далеко друг от друга, чтобы быть считается простым опечаткой. Дамерау заметил, что 80% людей орфографические ошибки имеют расстояние редактирования 1. Другими словами, 80% орфографические ошибки могут быть исправлены с помощью одного редактирования оригинала строка.

Elasticsearch поддерживает максимальное расстояние редактирования, указанное с помощью параметр нечеткости, 2 *. 1010 *

Конечно, влияние, которое одиночное редактирование оказывает на строку, зависит от длина строки. Два изменения слова шляпа могут привести к безумию, поэтому разрешить два редактирования строки длиной 3 - это излишне. Параметр нечеткости может быть установлен на AUTO, что приводит к следующему Максимальные расстояния редактирования:

0 для строк из одного или двух символов

1 для строк из трех, четырех или пяти символов

2 для строк длиной более пяти символов

Мне самому нравится использовать pyxDamerauLevenshtein.

pip install pyxDamerauLevenshtein

Таким образом, вы можете сделать простую реализацию, такую ​​как:

keywords = ['tiger','lion','elephant','black cat','dog']    

from pyxdameraulevenshtein import damerau_levenshtein_distance


def correct_sentence(sentence):
    new_sentence = []
    for word in sentence.split():
        budget = 2
        n = len(word)
        if n < 3:
            budget = 0
        elif 3 <= n < 6:
            budget = 1            
        if budget:            
            for keyword in keywords:        
                if damerau_levenshtein_distance(word, keyword) <= budget:
                    new_sentence.append(keyword)
                    break
            else:
                new_sentence.append(word)
        else:
            new_sentence.append(word)        
    return " ".join(new_sentence)

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

1 голос
/ 30 апреля 2019

Хотя это немного отличается от ожидаемого результата (это список списка вместо списка строк), я думаю, это шаг в правильном направлении.Причина, по которой я выбрал этот метод, заключается в том, что вы можете иметь несколько исправлений в предложении.Вот почему я добавил другое примерное предложение.

import difflib
import itertools

kw = ['tiger','lion','elephant','black cat','dog']
s = ["I saw a tyger","There are 2 lyons","I mispelled Kat","bulldogs", "A tyger is different from a doog"]

op = [[difflib.get_close_matches(j,kw,cutoff=0.5) for j in i.split()] for i in s]
op = [list(itertools.chain(*o)) for o in op]

print(op)

Вывод генерируется так:

[['tiger'], ['lion'], [], ['dog'], ['tiger', 'dog']]

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

...