NLTK word_tokenize на французском тексте не просыпается должным образом

Я пытаюсь использовать NLTK word_tokenize на текст на французском языке с помощью:

txt = ["Le télétravail n'aura pas d'effet sur ma vie"]
print(word_tokenize(txt,language='french'))

он должен напечатать:

['Le', 'télétravail', 'n'','aura', 'pas', 'd'','effet', 'sur', 'ma', 'vie','.']

Но я получаю:

['Le', 'télétravail', "n'aura", 'pas', "d'effet", 'sur', 'ma', 'vie','.']

Кто-нибудь знает, почему он не разделяет токены должным образом на французском языке и как преодолеть это (и другие потенциальные проблемы) при выполнении НЛП на французском языке?

2 ответа

Глядя на источник word_tokenize показывает, что language Аргумент используется только для определения того, как разбить ввод на предложения. И для токенизации на уровне слов (слегка измененный) TreebankWordTokenizer используется, что лучше всего подойдет для английского ввода и сокращений, как не. От nltk/tokenize/__init__.py:

_treebank_word_tokenizer = TreebankWordTokenizer()
# ... some modifications done
def word_tokenize(text, language='english', preserve_line=False):
    # ...
    sentences = [text] if preserve_line else sent_tokenize(text, language)
    return [token for sent in sentences
            for token in _treebank_word_tokenizer.tokenize(sent)]

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

txt = "Le télétravail n'aura pas d'effet sur ma vie"
pattern = r"[dnl]['´`]|\w+|\$[\d\.]+|\S+"
tokenizer = RegexpTokenizer(pattern)
tokenizer.tokenize(txt)
# ['Le', 'télétravail', "n'", 'aura', 'pas', "d'", 'effet', 'sur', 'ma', 'vie']

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

Я не думаю, что есть явная французская модель для word_tokenize (который является модифицированным токенайзером treebank, используемым для английского Penn Treebank). '

word_tokenize Функция выполняет токенизацию предложений, используя sent_tokenize функционировать перед фактическим токенизацией слова. language аргумент в word_tokenize используется только для sent_tokenize часть.

Кроме того, вы можете использовать MosesTokenizer у него есть некоторые зависимые от языка регулярные выражения (и он поддерживает французский язык):

>>> from nltk.tokenize.moses import MosesTokenizer
>>> moses = MosesTokenizer(lang='fr')
>>> sent = u"Le télétravail n'aura pas d'effet sur ma vie"
>>> moses.tokenize(sent)
[u'Le', u't\xe9l\xe9travail', u'n'', u'aura', u'pas', u'd'', u'effet', u'sur', u'ma', u'vie']

Если вам не нравится, что Моисей экранирует специальные символы XML, вы можете сделать:

>>> moses.tokenize(sent, escape=False)
[u'Le', u't\xe9l\xe9travail', u"n'", u'aura', u'pas', u"d'", u'effet', u'sur', u'ma', u'vie']

Чтобы объяснить, почему расщепление n' а также d' полезно во французском НЛП.

Лингвистически, отделяя n' а также d' действительно имеет смысл, потому что это clitique, которые имеют свои собственные синтаксические и семантические свойства, но привязаны к корню / хосту.

На французском, ne ... pas было бы прерывистым компонентом для обозначения отрицания, clitique природы ne собирается n' из-за появления гласного в следующем слове neтак расщепляя n' от aura облегчает идентификацию ne ... pas,

В случае d'это та же фонетическая мотивация появления гласного в следующем слове de effet -> d'effet,

Здесь мы видим, что обработка французской элизии неудовлетворительна. Итак, рекомендую исправить проблему с постобработкой элизии из НЛТК.word_tokenize выход.

compiled_pattern = re.compile(r"([a-zA-ZÀ-Ÿ]+['’])([a-zA-ZÀ-Ÿ]*)")

def split_in_words_fr(text):
    tokens = word_tokenize(text)
    new_tokens = []
    for token in tokens:
        search_results = re.findall(r"['’]",token)
        if search_results and len(search_results) == 1:
            new_tokens.extend(re.split(compiled_pattern,token)[1:3])
        else:
            new_tokens.append(token)
    return new_tokens

Потом:

print(split_in_words_fr("Le télétravail n'aura pas d'effet sur ma vie"))

дает:

['Le', 'télétravail', "n'", 'aura', 'pas', "d'", 'effet', 'sur', 'ma', 'vie']

Менее удовлетворительным решением является использование wordpunct_tokenize, которое разбивается на все символы, отличные от букв.

from nltk.tokenize import wordpunct_tokenize

print(wordpunct_tokenize("Le télétravail n'aura pas d'effet sur ma vie"))

который дает

['Le', 'télétravail', 'n', "'", 'aura', 'pas', 'd', "'", 'effet', 'sur', 'ma', 'vie']
Другие вопросы по тегам