Как настроить токенизатор предложения NLTK

Я использую NLTK для анализа нескольких классических текстов, и я работаю над тем, чтобы помечать текст по предложению. Например, вот что я получаю за фрагмент от Moby Dick :

import nltk sent_tokenize = nltk.data.load('tokenizers/punkt/english.pickle') ''' (Chapter 16) A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but that's a rather cold and clammy reception in the winter time, ain't it, Mrs. Hussey?" ''' sample = 'A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but that\'sa rather cold and clammy reception in the winter time, ain\'t it, Mrs. Hussey?"' print "\n-----\n".join(sent_tokenize.tokenize(sample)) ''' OUTPUT "A clam for supper? ----- a cold clam; is THAT what you mean, Mrs. ----- Hussey? ----- " says I, "but that\'sa rather cold and clammy reception in the winter time, ain\'t it, Mrs. ----- Hussey? ----- " ''' 

Я не ожидаю совершенства здесь, учитывая, что синтаксис Melville немного устарел, но NLTK должен иметь возможность обрабатывать терминальные двойные кавычки и названия, такие как «Mrs.», Однако, поскольку токенизатор является результатом неконтролируемого тренировочного алгоритма, я не могу понять, как его использовать.

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

Вам нужно предоставить список сокращений для токенизатора, например:

 from nltk.tokenize.punkt import PunktSentenceTokenizer, PunktParameters punkt_param = PunktParameters() punkt_param.abbrev_types = set(['dr', 'vs', 'mr', 'mrs', 'prof', 'inc']) sentence_splitter = PunktSentenceTokenizer(punkt_param) text = "is THAT what you mean, Mrs. Hussey?" sentences = sentence_splitter.tokenize(text) 

предложения теперь:

 ['is THAT what you mean, Mrs. Hussey?'] 

Обновление: это не работает, если последнее слово предложения имеет апостроф или прикрепленный к нему кавычек (например, Hussey? ). Таким образом, быстрый и грязный способ заключается в том, чтобы помещать пробелы перед апострофами и кавычками, которые следуют символам конца предложения (.!?):

 text = text.replace('?"', '? "').replace('!"', '! "').replace('."', '. "') 

Вы можете изменить предквалификатор английского языка NLTK, чтобы узнать больше аббревиатур, добавив их в набор _params.abbrev_types . Например:

 extra_abbreviations = ['dr', 'vs', 'mr', 'mrs', 'prof', 'inc', 'i.e'] sentence_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle') sentence_tokenizer._params.abbrev_types.update(extra_abbreviations) 

Обратите внимание, что аббревиатуры должны быть указаны без конечного периода, но включать любые внутренние периоды, как в 'i.e' выше. Подробнее о других параметрах токенизатора см. В соответствующей документации.

Вы можете указать метод PunktSentenceTokenizer.tokenize включить двойные кавычки терминала с остальной частью предложения, установив для параметра realign_boundaries значение True . См. Приведенный ниже код.

Я не знаю чистого способа предотвратить распространение текста, например, Mrs. Hussey , на два предложения. Однако, вот хак, который

  • управляет всеми проявлениями Mrs. Hussey ,
  • затем разбивает текст на предложения с sent_tokenize.tokenize ,
  • затем для каждого предложения, не Mrs._Hussey Mrs. Hussey обратно Mrs. Hussey

Хотелось бы, чтобы я знал лучший способ, но это может сработать.


 import nltk import re import functools mangle = functools.partial(re.sub, r'([MD]rs?[.]) ([AZ])', r'\1_\2') unmangle = functools.partial(re.sub, r'([MD]rs?[.])_([AZ])', r'\1 \2') sent_tokenize = nltk.data.load('tokenizers/punkt/english.pickle') sample = '''"A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?" says I, "but that\'sa rather cold and clammy reception in the winter time, ain\'t it, Mrs. Hussey?"''' sample = mangle(sample) sentences = [unmangle(sent) for sent in sent_tokenize.tokenize( sample, realign_boundaries = True)] print u"\n-----\n".join(sentences) 

доходность

 "A clam for supper? ----- a cold clam; is THAT what you mean, Mrs. Hussey?" ----- says I, "but that's a rather cold and clammy reception in the winter time, ain't it, Mrs. Hussey?" 

Таким образом, у меня была аналогичная проблема и опробовал решение vpekar выше.

Возможно, мой – это своего рода краевой случай, но я заметил такое же поведение после применения замен, однако, когда я попытался заменить пунктуацию на котировки, размещенные перед ними, я получил результат, который я искал. Предположительно, отсутствие приверженности MLA менее важно, чем сохранение первоначальной цитаты в виде одного предложения.

Чтобы быть более ясным:

 text = text.replace('?"', '"?').replace('!"', '"!').replace('."', '".') 

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