nltk.org 使用朴素贝叶斯分类器进行句子分割的示例:.sent 如何分隔句子以及 ML 算法如何改进它?

Posted

技术标签:

【中文标题】nltk.org 使用朴素贝叶斯分类器进行句子分割的示例:.sent 如何分隔句子以及 ML 算法如何改进它?【英文标题】:nltk.org example of Sentence segmentation with Naive Bayes Classifier: how does .sent separate sentences and how does the ML algorithm improve it? 【发布时间】:2019-05-16 20:36:21 【问题描述】:

在 nltk.org book (chapter 6) 中有一个示例,他们使用 NaiveBayesian 算法将标点符号分类为完成一个句子或未完成一个......

这就是他们所做的:首先,他们获取一个语料库并使用 .sent 方法来获取句子并从中建立一个索引,用于区分它们的标点符号(boundaries)在哪里。

然后他们“标记”文本(将其转换为单词和标点符号列表)并将以下算法/函数应用于每个标记,以便他们获得 features 列表,这些列表在字典:

def punct_features(tokens, i):
    return 'nextWordCapitalized': tokens[i+1][0].isupper(),
        'prevWord': tokens[i-1].lower(),
        'punct': tokens[i],
        'prevWordis1Char': len(tokens[i-1]) == 1

ML 算法将使用这些特征将标点符号分类为是否完成句子(即作为边界标记)。

使用这个 fn 和 'boundaries' 索引,他们选择所有标点符号,每个都有其特征,并将它们标记为 True 边界或 False 一个,从而创建一个 标记的特征列表- 集

featuresets1 = [(punct_features(tokens, i), (i in boundaries)) for i in range(1, len(tokens)-1)
               if tokens[i] in '.?!;']
print(featuresets1[:4])

这是我们在打印前四组时的输出示例:

[('nextWordCapitalized': False, 'prevWord': 'nov', 'punct': '.', 'prevWordis1Char': False, False), 
('nextWordCapitalized': True, 'prevWord': '29', 'punct': '.', 'prevWordis1Char': False, True), 
('nextWordCapitalized': True, 'prevWord': 'mr', 'punct': '.', 'prevWordis1Char': False, False), 
('nextWordCapitalized': True, 'prevWord': 'n', 'punct': '.', 'prevWordis1Char': True, False)]

通过这个,他们训练和评估标点符号分类器:

size = int(len(featuresets) * 0.1)
train_set, test_set = featuresets[size:], featuresets[:size]
classifier = nltk.NaiveBayesClassifier.train(train_set)

nltk.classify.accuracy(classifier, test_set)

现在,(1) 这样的机器学习算法将如何改进以及改进什么?我无法理解第一个简单的算法如何更好地检查标点符号中的下一个标记是否为大写,而前一个是否为小写。事实上,该算法被用来验证符号是边界......!如果它不改进它,可能有什么用处?

与此相关:(2)这两种算法中的任何一种是nlpk如何真正分离句子?我的意思是,特别是如果最好的是第一个简单的,nltk 是否理解句子只是两个标点符号之间的文本,后面跟着一个单词,第一个图表是大写字母,前一个单词是小写字母?这是 .sent 方法的作用吗?请注意,这与语言学或牛津词典中定义句子的方式相去甚远:

“一组本身完整的单词,通常包含一个 主语和谓语,传达陈述,问题,感叹, 或命令,由主句组成,有时包含一个或多个 从句。”

或者 (3) 像 treebankbrown 这样的原始语料库文本是否已经被手动分割成句子? - 在这种情况下,选择它们的标准是什么?

【问题讨论】:

【参考方案1】:

问题(1):NLTK 可能没有说清楚,但是分句是个难题。就像你说的,我们可以假设一个标点符号结束句子,即前一个字符是小写,当前字符是标点,下一个字符是大写(顺便说一句,中间有空格!别忘了!)。但是,考虑一下这句话:

“Peter 先生在多伦多一家名为 A.B.C. Inc. 的公司工作。他的每月净工资为 $2344.21 美元。22 年前,他以移民身份来到多伦多。” - 现在,按照我们上面的规则,这将如何拆分?

Wikipedia page on sentence boundary disambiguation 说明了其中一些问题。在 Jurafsky 和 ​​Martin 的 NLP 教科书“语音和语言处理”中,他们也有一个 chapter on Text normaliazation,还有更多示例说明为什么单词/句子分割可能具有挑战性 - 了解这一点可能对您有用.我假设我们正在讨论英语分割,但显然其他语言还有其他问题(例如,某些语言没有大写)。

Q 2:这两种算法中的任何一种是如何真正分离句子的? NLTK 使用了一种无监督的句子分割方法,称为PunktSentenceTokenizer

Q3:像treebank或brown这样的原始语料库文本是否已经被手动分割成句子? - 是的,这些是手动分成句子的。这些是 NLP 中用于开发诸如词性标注器、解析器等语言工具的一些常用语料库。选择这些的一个原因可能是它们已经在 NLTK 中可用,我们不必寻找另一个人工注释的语料库来做句子边界检测的监督学习。

【讨论】:

很棒的答案!那么,受监督的 NaiveBayes 永远不会比以前的简单(非 ML)算法/函数做得更好,对吧?那么在这里使用朴素贝叶斯的目的是什么? 受监督的可能会或可能不会学习。我们可以知道的唯一方法是尝试所有三种方法:a)仅使用您提到的规则(之前小写,之后大写); b) 使用监督方法; c) NLTK 当前使用的无监督的。教科书中使用朴素贝叶斯的目的是为了教学。不要忘记 NLTK 的主要目的是教授 NLP :)【参考方案2】:

(否则很好)接受的答案遗漏的一件事是解释 NaiveBayes 算法在应用您描述的规则之外所做的事情。

任何这种类型的分类器都有几个特征,它必须决定它们作为分类线索的重要性。 下一个字母大写 = 非常重要,前一个字母小写 = 重要但不太重要,此标点符号后的空格 = 重要等。机器学习算法使用一些 方法来为每个特征分配权重(= 重要性),以便结果与算法可以提供的一样好。有些人可以一步完成,有些人则分步完成,每次迭代都会对之前的结果有所改进(“爬山”)。

每个机器学习算法的细节都不同,朴素贝叶斯的细节在这里并不重要。但为了完整性:它是基于假设(通常与现实相反,但方便)每个特征在统计上独立于所有其他特征的统计计算。

【讨论】:

以上是关于nltk.org 使用朴素贝叶斯分类器进行句子分割的示例:.sent 如何分隔句子以及 ML 算法如何改进它?的主要内容,如果未能解决你的问题,请参考以下文章

12.朴素贝叶斯-垃圾邮件分类

12.朴素贝叶斯-垃圾邮件分类

12.朴素贝叶斯-垃圾邮件分类

12.朴素贝叶斯-垃圾邮件分类

12.朴素贝叶斯-垃圾邮件分类

12.朴素贝叶斯-垃圾邮件分类