- 自然语言工具包教程
- 自然语言工具包 - 首页
- 自然语言工具包 - 简介
- 自然语言工具包 - 入门
- 自然语言工具包 - 分词
- 训练分词器 & 过滤停用词
- 在 WordNet 中查找单词
- 词干提取 & 词形还原
- 自然语言工具包 - 词语替换
- 同义词 & 反义词替换
- 语料库读取器和自定义语料库
- 词性标注 (POS) 基础
- 自然语言工具包 - 一元标注器
- 自然语言工具包 - 组合标注器
- 自然语言工具包 - 更多 NLTK 标注器
- 自然语言工具包 - 语法分析
- 组块 & 信息提取
- 自然语言工具包 - 转换组块
- 自然语言工具包 - 转换树
- 自然语言工具包 - 文本分类
- 自然语言工具包资源
- 自然语言工具包 - 快速指南
- 自然语言工具包 - 有用资源
- 自然语言工具包 - 讨论
自然语言工具包 - 组合标注器
组合标注器
组合标注器或将标注器彼此链接是 NLTK 的重要功能之一。组合标注器背后的主要概念是,如果一个标注器不知道如何标注一个单词,它将被传递给链接的标注器。为了实现这一目的,SequentialBackoffTagger 为我们提供了回退标注功能。
回退标注
如前所述,回退标注是SequentialBackoffTagger 的重要功能之一,它允许我们以以下方式组合标注器:如果一个标注器不知道如何标注一个单词,则该单词将传递给下一个标注器,依此类推,直到没有剩余的回退标注器可供检查。
它是如何工作的?
实际上,SequentialBackoffTagger 的每个子类都可以接受一个“backoff”关键字参数。此关键字参数的值是SequentialBackoffTagger 的另一个实例。现在,每当初始化此SequentialBackoffTagger 类时,都会创建一个回退标注器内部列表(自身作为第一个元素)。此外,如果给定了一个回退标注器,则此回退标注器的内部列表将被追加。
在下面的示例中,我们采用DefaulTagger 作为上述 Python 代码中训练UnigramTagger 的回退标注器。
示例
在此示例中,我们使用DefaulTagger 作为回退标注器。每当UnigramTagger 无法标注一个单词时,回退标注器(在本例中为DefaulTagger)将用“NN”对其进行标注。
from nltk.tag import UnigramTagger from nltk.tag import DefaultTagger from nltk.corpus import treebank train_sentences = treebank.tagged_sents()[:2500] back_tagger = DefaultTagger('NN') Uni_tagger = UnigramTagger(train_sentences, backoff = back_tagger) test_sentences = treebank.tagged_sents()[1500:] Uni_tagger.evaluate(test_sentences)
输出
0.9061975746536931
从以上输出可以看出,通过添加回退标注器,准确率提高了约 2%。
使用 pickle 保存标注器
正如我们所看到的,训练一个标注器非常麻烦,而且需要时间。为了节省时间,我们可以将训练好的标注器进行 pickle 处理,以便以后使用。在下面的示例中,我们将对我们已经训练好的名为“Uni_tagger”的标注器进行此操作。
示例
import pickle f = open('Uni_tagger.pickle','wb') pickle.dump(Uni_tagger, f) f.close() f = open('Uni_tagger.pickle','rb') Uni_tagger = pickle.load(f)
NgramTagger 类
从前面单元中讨论的层次结构图中,UnigramTagger 继承自NgarmTagger 类,但NgarmTagger 类还有另外两个子类:
BigramTagger 子类
实际上,n 元组是 n 个项目的子序列,因此,顾名思义,BigramTagger 子类会查看两个项目。第一个项目是前一个已标注的单词,第二个项目是当前已标注的单词。
TrigramTagger 子类
与BigramTagger 同理,TrigramTagger 子类会查看三个项目,即前两个已标注的单词和一个当前已标注的单词。
实际上,如果我们像使用 UnigramTagger 子类一样单独应用BigramTagger 和TrigramTagger 子类,它们的性能都非常差。让我们在下面的示例中看看。
使用 BigramTagger 子类
from nltk.tag import BigramTagger from nltk.corpus import treebank train_sentences = treebank.tagged_sents()[:2500] Bi_tagger = BigramTagger(train_sentences) test_sentences = treebank.tagged_sents()[1500:] Bi_tagger.evaluate(test_sentences)
输出
0.44669191071913594
使用 TrigramTagger 子类
from nltk.tag import TrigramTagger from nltk.corpus import treebank train_sentences = treebank.tagged_sents()[:2500] Tri_tagger = TrigramTagger(train_sentences) test_sentences = treebank.tagged_sents()[1500:] Tri_tagger.evaluate(test_sentences)
输出
0.41949863394526193
您可以将之前使用的 UnigramTagger 的性能(准确率约为 89%)与 BigramTagger(准确率约为 44%)和 TrigramTagger(准确率约为 41%)进行比较。原因是 Bigram 和 Trigram 标注器无法从句子中的第一个单词(或单词)学习上下文。另一方面,UnigramTagger 类不关心之前的上下文,并猜测每个单词最常见的标签,因此能够获得较高的基准准确率。
组合 n 元标注器
从以上示例可以看出,当我们将 Bigram 和 Trigram 标注器与回退标注相结合时,它们可以做出贡献。在下面的示例中,我们将 Unigram、Bigram 和 Trigram 标注器与回退标注相结合。该概念与之前将 UnigramTagger 与回退标注器组合的代码相同。唯一的区别是我们使用 tagger_util.py 中提供的名为 backoff_tagger() 的函数进行回退操作,如下所示。
def backoff_tagger(train_sentences, tagger_classes, backoff=None): for cls in tagger_classes: backoff = cls(train_sentences, backoff=backoff) return backoff
示例
from tagger_util import backoff_tagger from nltk.tag import UnigramTagger from nltk.tag import BigramTagger from nltk.tag import TrigramTagger from nltk.tag import DefaultTagger from nltk.corpus import treebank train_sentences = treebank.tagged_sents()[:2500] back_tagger = DefaultTagger('NN') Combine_tagger = backoff_tagger(train_sentences, [UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger) test_sentences = treebank.tagged_sents()[1500:] Combine_tagger.evaluate(test_sentences)
输出
0.9234530029238365
从以上输出可以看出,准确率提高了约 3%。