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