Разделение слов с помощью модуля nltk в Python

Я пытаюсь найти способ разделения слов в Python с помощью модуля nltk. Я не уверен, как достичь своей цели, учитывая необработанные данные, которые у меня есть, которые представляют собой список токенизированных слов, например

['usingvariousmolecularbiology', 'techniques', 'toproduce', 'genotypes', 'following', 'standardoperatingprocedures', '.', 'Operateandmaintainautomatedequipment', '.', 'Updatesampletrackingsystemsandprocess', 'documentation', 'toallowaccurate', 'monitoring', 'andrapid', 'progression', 'ofcasework']

Как вы можете видеть, многие слова связаны друг с другом (т. Е. "To" и "product" находятся в одной строке "toproduce"). Это артефакт извлечения данных из PDF-файла, и я хотел бы найти способ использования модуля nltk в python для разделения склеенных слов (т. Е. Разделить "toproduce" на два слова: "to" и "yield"; разделите "стандартные операционные процедуры" на три слова: "стандартные", "операционные", "процедуры").

Я ценю любую помощь!

2 ответа

Решение

Я полагаю, что вы захотите использовать сегментацию слов в этом случае, и я не знаю ни одной функции сегментации слов в NLTK, которая будет иметь дело с английскими предложениями без пробелов. Вы могли бы использовать pyenchant вместо. Я предлагаю следующий код только в качестве примера. (Это будет работать для небольшого числа относительно коротких строк - таких как строки в вашем списке примеров - но будет крайне неэффективным для более длинных строк или более многочисленных строк.) Это потребует модификации и не будет успешно сегментировать каждую Строка в любом случае.

import enchant  # pip install pyenchant
eng_dict = enchant.Dict("en_US")

def segment_str(chars, exclude=None):
    """
    Segment a string of chars using the pyenchant vocabulary.
    Keeps longest possible words that account for all characters,
    and returns list of segmented words.

    :param chars: (str) The character string to segment.
    :param exclude: (set) A set of string to exclude from consideration.
                    (These have been found previously to lead to dead ends.)
                    If an excluded word occurs later in the string, this
                    function will fail.
    """
    words = []

    if not chars.isalpha():  # don't check punctuation etc.; needs more work
        return [chars]

    if not exclude:
        exclude = set()

    working_chars = chars
    while working_chars:
        # iterate through segments of the chars starting with the longest segment possible
        for i in range(len(working_chars), 1, -1):
            segment = working_chars[:i]
            if eng_dict.check(segment) and segment not in exclude:
                words.append(segment)
                working_chars = working_chars[i:]
                break
        else:  # no matching segments were found
            if words:
                exclude.add(words[-1])
                return segment_str(chars, exclude=exclude)
            # let the user know a word was missing from the dictionary,
            # but keep the word
            print('"{chars}" not in dictionary (so just keeping as one segment)!'
                  .format(chars=chars))
            return [chars]
    # return a list of words based on the segmentation
    return words

Как видите, этот подход (предположительно) неправильно сегментирует только одну из ваших строк:

>>> t = ['usingvariousmolecularbiology', 'techniques', 'toproduce', 'genotypes', 'following', 'standardoperatingprocedures', '.', 'Operateandmaintainautomatedequipment', '.', 'Updatesampletrackingsystemsandprocess', 'documentation', 'toallowaccurate', 'monitoring', 'andrapid', 'progression', 'ofcasework']
>>> [segment(chars) for chars in t]
"genotypes" not in dictionary (so just keeping as one segment)
[['using', 'various', 'molecular', 'biology'], ['techniques'], ['to', 'produce'], ['genotypes'], ['following'], ['standard', 'operating', 'procedures'], ['.'], ['Operate', 'and', 'maintain', 'automated', 'equipment'], ['.'], ['Updates', 'ample', 'tracking', 'systems', 'and', 'process'], ['documentation'], ['to', 'allow', 'accurate'], ['monitoring'], ['and', 'rapid'], ['progression'], ['of', 'casework']]

Вы можете использовать chain чтобы сгладить этот список списков:

>>> from itertools import chain
>>> list(chain.from_iterable(segment_str(chars) for chars in t))
"genotypes" not in dictionary (so just keeping as one segment)!
['using', 'various', 'molecular', 'biology', 'techniques', 'to', 'produce', 'genotypes', 'following', 'standard', 'operating', 'procedures', '.', 'Operate', 'and', 'maintain', 'automated', 'equipment', '.', 'Updates', 'ample', 'tracking', 'systems', 'and', 'process', 'documentation', 'to', 'allow', 'accurate', 'monitoring', 'and', 'rapid', 'progression', 'of', 'casework']

Вы можете легко установить следующую библиотеку и использовать ее для своих целей:

      pip install wordsegment
import wordsegment
help(wordsegment)

from wordsegment import load, segment
load()
segment('usingvariousmolecularbiology')

Вывод будет таким:

      Out[4]: ['using', 'various', 'molecular', 'biology']

Пожалуйста, обратитесь к http://www.grantjenks.com/docs/wordsegment/ для получения более подробной информации.

Другие вопросы по тегам