如何调整NLTK句子标记器
nlp
nltk
python
7
0

我正在使用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\'s a 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\'s a rather cold and clammy reception in the winter time, ain\'t it, Mrs.
-----
Hussey?
-----
"
'''

考虑到梅尔维尔(Melville)的语法有些陈旧,我不希望在这里达到完美,但是NLTK应该能够处理终端双引号和标题,例如“ Mrs”。但是,由于令牌生成器是无监督训练算法的结果,所以我不知道该如何进行修补。

有人建议使用更好的句子标记器吗?我更喜欢可以破解的简单启发式方法,而不必训练自己的解析器。

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

通过将realign_boundaries参数设置为True可以告诉PunktSentenceTokenizer.tokenize方法在句子的其余部分包括“终端”双引号。有关示例,请参见下面的代码。

我不知道一种干净的方法可以防止像Mrs. Hussey这样的文本分成两句话。但是,这里有一个hack

  • 将所有出现的Mrs. Hussey Mrs._HusseyMrs._Hussey
  • 然后使用sent_tokenize.tokenize将文本拆分为句子,
  • 然后针对每个句子,将Mrs._Hussey Mrs. Hussey Mrs._HusseyMrs. Hussey

我希望我知道更好的方法,但是这可能会在紧急情况下起作用。


import nltk
import re
import functools

mangle = functools.partial(re.sub, r'([MD]rs?[.]) ([A-Z])', r'\1_\2')
unmangle = functools.partial(re.sub, r'([MD]rs?[.])_([A-Z])', 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\'s a 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?"
收藏
评论

您需要向令牌生成器提供缩写列表,如下所示:

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('."', '. "')
收藏
评论

因此,我遇到了类似的问题,并尝试了上述vpekar的解决方案。

也许我的是某种极端情况,但是在应用替换后,我观察到了相同的行为,但是,当我尝试用标点符号之前的标点替换标点符号时,得到了我想要的输出。大概缺乏遵守MLA的重要性不如将原始报价单保留为一个句子那么重要。

更清楚地说:

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

如果MLA很重要,尽管您可以随时返回并撤消这些更改,无论它在哪里都重要。

收藏
评论

您可以通过将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)

请注意,必须在没有最后一个句点的情况下指定缩写,但必须包括任何内部句点,如上面的'ie'所示。有关其他令牌生成器参数的详细信息,请参阅相关文档。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号