NLTK 中文词性自动标注

#自然语言处理

1 说明

学习自然语言处理,一定会参考 NLTK,主要是学习它的思路, 从设计地角度看看能做什么. 其本质就是把语言看成字符串,字符串组,字符串集,寻找其间规律.

NLTK 是多语言支持的, 但目前网上的例程几乎没有用 NLTK 处理中文的,其实可以做。比如标注功能, 它自身提供了带标注的中文语库 (繁体语料库 sinica_treebank). 下面来看看怎样通过数据训练来实现中文词性自动标注.

可以利用它来标注中本,也可以寻找和验证一些隐性的规律.

2 相关知识

2.1.1 词性标注

词汇按它们的词性 (parts-of-speech,POS) 分类以及相应的标注它们的过程, 词性包括: 名词、动词、形容词, 副词等.

2.1.2 中文字符的显示

Python 内部编码是 unicode, 所以输出中文常常像这样"ebade5", 用 print 函数输出时, 将自动转换成本地字符集, 也可以使用 encode(‘utf-8’) 函数转换.

2.1.3 数据集,训练集,评估

有监督的机器学习一般都是把数据分成两个部分, 一部分用于训练, 一部分用于测试, 还可以通过不同分组交叉验证. Nltk 提供了 evaluate() 函数评估标注效果.

2.1.4 默认标注(Default Tagger)

事先对语料库做了统计 (利用 nltk.FreqDist()), 出现最多的是名词.

在这里,默认标注为名词.

2.1.5 正则表达式标注(Regexp Tagger)

用匹配模式分配标记给标识符.在英文处理中,常用此方式识别各种形态(时态,后缀等),中文识别中也可以使用它来识别标点,数字等.

2.1.6 一元标注(Unigram Tagger)

一元标注基于一个简单的统计算法: 对每个标识符分配这个独特的标识符最有可能的标记.

在这里就是分配给具体单词,它最常出现的词性.

2.1.7 多元标注(N-gram Tagger)

多元标注使用训练集来确定对每个上下文哪个词性标记最有可能。上下文指当前词和它前面 n-1 个标识符的词性标记.

在这里,就是找一些规律, 比如: XX 常出现在名词之前, YY 常出现在动词之后. 通过某个词以及它之前那个词的词性来判断它的词性. 这就是二元标注. 同理,可以生成三元甚至多元标注.词的距离越远影响越小, 也更占用资源, 一般二元到三元就够了.

2.1.8 组合标注

更精确的算法在很多时候落后于具有更广覆盖范围的算法(比如满足三元标的词可能非常少), 所以有时我们组合多个标注器,

在这里,组合 bigram 标注器、unigram 标注器和一个默认标注器

3 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# encoding=utf-8

import nltk
from nltk.corpus import sinica_treebank # 带标注的中文语料库

# 用print输出本地字符格式
def dump_result(result):
for item in result:
print item[0],",",item[1],
print

# 等标注的词,以空格分词(分词问题不在此讨论)
raw = '讓 人工 智能 能夠 更 有效地 甄別 虛假 和 低俗 內容 並 控制 其 傳播 是 當前 業界 和 學界 要 重點 研究 的 問題'.decode('utf-8')
tokens = nltk.word_tokenize(raw)

sinica_treebank_tagged_sents = sinica_treebank.tagged_sents() # 以句为单位标
size = int(len(sinica_treebank_tagged_sents) * 0.9)
train_sents = sinica_treebank_tagged_sents[:size] # 90% 数据作为训练集
test_sents = sinica_treebank_tagged_sents[size:] # 10% 数据作为测试集

t0 = nltk.DefaultTagger('Nab') # 词性的默认值为名词
t1 = nltk.UnigramTagger(train_sents, backoff=t0) # 一元标注
t2 = nltk.BigramTagger(train_sents, backoff=t1) # 多元(二元)标注

dump_result(t2.tag(tokens))
print t2.evaluate(test_sents) # 根据带标注的文本,评估标注器的正确率

4 主要思想

词性标注的主要思想是提炼最容易出现的可能性 (在不同层次: 所有词, 具体词, 词间关系),它是一套统计方法,也是分类器的一个应用.

NLTK 的词性标注只是抛砖引玉,使用同样方法,还也可以实现标注词义 (一词多义的消歧), 字音 (多音字) 等等.

通过它来看看自然语言的处理方法, 有了自己的工具, 也能更灵活地使用这个功能, 目前还很简陋,下面来看看怎么改进它.

5 改进

5.1.1 缺少训练数据

训练数据不足, 或者一些标注本身的问题, 需要改进和增加训练数据.错误分类可以通过大量数据的校正,同时也需考虑语境,选择不同训练集.

上例中的 sinica_treebank 语料库自带 1 万个句子, 10 万左右的词,文本也比较单一,执行以上程序后可以看到, 准确率在 75% 左右.

想要训练出更理想的标注器, 需要更多带标注的数据 (有监督学习). 数据从哪儿来呢? 其实也简单, 可以用现有靠谱的分词工具 (比如: 在线的”语言云”, 离线的”结巴”) 的标注结果去训练你自己的标注器.

5.1.2 有一些词本身就是特例, 就如同”海豚不是鱼类”

统计归类本身无法处理, 除了统计的方案, 还可以添加一一对应的词与标注的映射表来解决此类问题.

5.1.3 新词/不常用词

未被训练过的词,可以用一些特殊标记加入字典,在数据积累到一定数量时总结其规律.

N 元标注再抽象一个层次是发现词性间的规律,比如"名词前是形容词的可能性比较大",借此来处理不能识别的"新词".

也可以通过 WordNet 等字典查看具体词的词性.有一些词虽然很少出现, 但词义和词性比较单一. 对多义词,可以选择其最常用的词性.

5.1.4 特殊规则

有些专业领域会有一些特殊的习惯用法, 也可以通过它制定一些规则. 通过正则表达式标注器实现.

5.1.5 语义, 形态…

更深层次的语义分析

6 模型下载

报错连接不成功时,直接下载数据:在 https://www.nltk.org/nltk_data/中下载插件

下载后解压到:$HOME/nltk_data/corpora/目录下

7 参考

7.1.1 Categorizing and Tagging Words

http://www.nltk.org/book_1ed/ch05.html

7.1.2 结巴词性标注

http://www.mamicode.com/info-detail-562618.html##