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

Фиксировать слова с пробелами, используя словарь, искать в python?

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

У меня есть предложения, такие как "more recen t ly the develop ment, wh ich is a po ten t "

Я хотел бы исправить такие предложения, используя словарь поиска? для удаления нежелательных пробелов.

Конечный результат должен быть "more recently the development, which is a potent "

Я бы предположил, что это прямая задача в препроцессорном тексте? Мне нужна помощь с некоторыми указателями, чтобы искать такие подходы. Спасибо.

4b9b3361

Ответ 1

Взгляните на слово или текст segmentation. Проблема состоит в том, чтобы найти наиболее вероятное разбиение строки на группу слов. Пример:

 thequickbrownfoxjumpsoverthelazydog

Наиболее вероятная сегментация должна быть, конечно:

 the quick brown fox jumps over the lazy dog

Здесь статья, включающая прототипический исходный код для проблемы с использованием Google Ngram corpus:

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

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

$ python segmentation.py t hequi ckbrownfoxjum ped
thequickbrownfoxjumped
['the', 'quick', 'brown', 'fox', 'jumped']

Используя данные, это можно изменить:

$ python segmentation.py lmaoro fll olwt f pwned
lmaorofllolwtfpwned
['lmao', 'rofl', 'lol', 'wtf', 'pwned']

Обратите внимание, что алгоритм довольно медленный - он прототип.

Другой подход, использующий NLTK:

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

Ответ 2

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

В основном вам нужен большой словарь. Если вы будете использовать его много, я бы закодировал его как "дерево префикса" (aka trie), чтобы вы может быстро узнать, является ли фрагмент началом реального слова. Nltk обеспечивает реализацию Trie.

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

Ответ 3

- Решение 1:

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

(more)(recen)(t)(ly)(the)(develop)(ment,)(wh)(ich)(is)(a)(po)(ten)(t)

Это решает две подзадачи:

a) Бусина - это единое целое, поэтому нам не нужны перестановки внутри бусинки, т.е. перестановки "больше" невозможны.

b) Порядок шариков постоянный, изменяется только интервал между ними. то есть "больше" всегда будет до "recen" и т.д.

Теперь сгенерируем все перестановки этих бусинок, которые выдадут результат следующим образом:

morerecentlythedevelopment,which is a potent
morerecentlythedevelopment,which is a poten t
morerecentlythedevelop ment, wh ich is a po tent
morerecentlythedevelop ment, wh ich is a po ten t
morerecentlythe development,whichisapotent

Затем оценивайте эти перестановки, исходя из того, сколько слов из вашего соответствующего словаря они содержат, наиболее правильные результаты можно легко отфильтровать. more recently the development, which is a potent будет стоить больше, чем morerecentlythedevelop ment, wh ich is a po ten t

Код, который выполняет перестановочную часть бусин:

import re

def gen_abacus_perms(frags):
    if len(frags) == 0:
        return []
    if len(frags) == 1:
        return [frags[0]]

    prefix_1 = "{0}{1}".format(frags[0],frags[1])
    prefix_2 = "{0} {1}".format(frags[0],frags[1])
    if len(frags) == 2:
        nres = [prefix_1,prefix_2]
        return nres

    rem_perms = gen_abacus_perms(frags[2:])
    res = ["{0}{1}".format(prefix_1, x ) for x in rem_perms] + ["{0} {1}".format(prefix_1, x ) for x in rem_perms] +  \
["{0}{1}".format(prefix_2, x ) for x in rem_perms] + ["{0} {1}".format(prefix_2 , x ) for x in rem_perms]
    return res



broken = "more recen t ly the develop ment, wh ich is a po ten t"
frags = re.split("\s+",broken)
perms = gen_abacus_perms(frags)
print("\n".join(perms))

demo: http://ideone.com/pt4PSt


- Решение # 2:

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

Я не очень хорошо осведомлен о такой публичной/платной apis, поэтому мой пример основан на результатах Google.

Давайте попробуем использовать Google:

  • Вы можете оставить свои недопустимые условия для Google, для нескольких проходов и продолжать оценивать результаты для некоторого балла на основе словаря поиска. вот два релевантных результата, используя 2 прохода вашего текста:

enter image description here

Этот вывод используется для второго прохода:

enter image description here

Что дает вам преобразование как "в последнее время развитие, которое является мощным".

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

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

>>> import difflib
>>> import re
>>> input = "more recen t ly the develop ment, wh ich is a po ten t "
>>> output = "more recently the development, which is a potent "
>>> input_norm = re.sub(r'\W+', '', input).lower()
>>> output_norm = re.sub(r'\W+', '', output).lower()
>>> input_norm
'morerecentlythedevelopmentwhichisapotent'
>>> output_norm
'morerecentlythedevelopmentwhichisapotent'
>>> difflib.SequenceMatcher(None,input_norm,output_norm).ratio()
1.0

Ответ 4

Я бы рекомендовал удалить пробелы и искать словарные слова, чтобы сломать их. Есть несколько вещей, которые вы можете сделать, чтобы сделать его более точным. Чтобы получить первое слово в тексте без пробелов, попробуйте взять всю строку и перейти через словарные слова из файла (вы можете загрузить несколько таких файлов из http://wordlist.sourceforge.net/), самые длинные сначала, чем удаление букв с конца строки, которую вы хотите сегментировать. Если вы хотите, чтобы он работал с большой строкой, вы можете автоматически отбирать буквы со спины, так что строка, в которой вы ищете первое слово, равно только длинному словарю слова. Это должно привести к тому, что вы найдете самые длинные слова и сделаете менее вероятным сделать что-то вроде классификации "асинхронный" как "синхронный". Вот пример, который использует исходный ввод для исправления текста и словарный файл, называемый dictionary.txt:

dict = open("dictionary.txt",'r')                                #loads a file with a list of words to break string up into
words = raw_input("enter text to correct spaces on: ")
words = words.strip()                                            #strips away spaces
spaced = []                                                      #this is the list of newly broken up words
parsing = True                                                   #this represents when the while loop can end
while parsing:
    if len(words) == 0:                                          #checks if all of the text has been broken into words, if it has been it will end the while loop
        parsing = False
    iterating = True
    for iteration in range(45):                                  #goes through each of the possible word lengths, starting from the biggest
        if iterating == False:
            break
        word = words[:45-iteration]                              #each iteration, the word has one letter removed from the back, starting with the longest possible number of letters, 45
        for line in dict:
            line = line[:-1]                                     #this deletes the last character of the dictionary word, which will be a newline. delete this line of code if it is not a newline, or change it to [1:] if the newline character is at the beginning
            if line == word:                                     #this finds if this is the word we are looking for
                spaced.append(word)
                words = words[-(len(word)):]                     #takes away the word from the text list
                iterating = False
                break
print ' '.join(spaced)                                           #prints the output

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

Ответ 5

Здесь что-то действительно основное:

chunks = []
for chunk in my_str.split():
    chunks.append(chunk)
    joined = ''.join(chunks)
    if is_word(joined):
        print joined,
        del chunks[:]

# deal with left overs
if chunks:
    print ''.join(chunks)

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

def is_word(wd):
    if not wd:
        return False
    # Strip of trailing punctuation. There might be stuff in front
    # that you want to strip too, such as open parentheses; this is
    # just to give the idea, not a complete solution.
    if wd[-1] in ',.!?;:':
        wd = wd[:-1]
    return wd in valid_words

Ответ 6

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

def iterate(word,dictionary):
   for word in dictionary:
      if words in possibleWord:
        finished_sentence.append(words)
        added = True
      else:
        added = False
      return [added,finished_sentence]
sentence = "more recen t ly the develop ment, wh ich is a po ten t "
finished_sentence = ""
sentence = sentence.split()
for word in sentence:
  added,new_word = interate(word,dictionary)
  while True:   
    if added == False:
      word += possible[sentence.find(possibleWord)]
      iterate(word,dictionary)
    else:
      break
  finished_sentence.append(word)

Это должно сработать. Для переменной dictionary загрузите txt файл каждого отдельного английского слова, затем откройте его в своей программе.