nlp---使用NLTK进行建构词性标注器
2018-01-31 15:03
323 查看
自然语言是人类在沟通中形成的一套规则体系。规则有强有弱,比如非正式场合使用口语,正式场合下的书面语。要处理自然语言,也要遵循这些形成的规则,否则就会得出令人无法理解的结论。下面介绍一些术语的简单区别。 文法:等同于语法(grammar),文章的书写规范,用来描述语言及其结构,它包含句法和词法规范。 句法:Syntax,句子的结构或成分的构成与关系的规范。 词法:Lexical,词的构词,变化等的规范。 词性标注,或POS(Part Of Speech),是一种分析句子成分的方法,通过它来识别每个词的词性。下面简要列举POS的tagset含意,详细可看nltk.help.brown_tagset()
标记 | 词性 | 示例 |
---|---|---|
ADJ | 形容词 | new, good, high, special, big, local |
ADV | 动词 | really, already, still, early, now |
CONJ | 连词 | and, or, but, if, while, although |
DET | 限定词 | the, a, some, most, every, no |
EX | 存在量词 | there, there’s |
MOD | 情态动词 | will, can, would, may, must, should |
NN | 名词 | year,home,costs,time |
NNP | 专有名词 | April,China,Washington |
NUM | 数词 | fourth,2016, 09:30 |
PRON | 代词 | he,they,us |
P | 介词 | on,over,with,of |
TO | 词to | to |
UH | 叹词 | ah,ha,oops |
VB | 动词 | |
VBD | 动词过去式 | made,said,went |
VBG | 现在分词 | going,lying,playing |
VBN | 过去分词 | taken,given,gone |
WH | wh限定词 | who,where,when,what |
1 使用NLTK对英文进行词性标注
1.1 词性标注示例
import nltk sent="I am going to Beijing tomorrow"; tokens = nltk.word_tokenize(sent) taged_sent = nltk.pos_tag(tokens) print taged_sent #[('I', 'PRP'), ('am', 'VBP'), ('going', 'VBG'), ('to', 'TO'), ('Beijing', 'NNP'), ('tomorrow', 'NN'), ('.', '.')]1
2
3
4
5
6
7
1.2 语料库的已标注数据
语料类提供了下列方法可以返回预标注数据。方法 | 说明 |
---|---|
tagged_words(fileids,categories) | 返回标注数据,以词列表的形式 |
tagged_sents(fileids,categories) | 返回标注数据,以句子列表形式 |
tagged_paras(fileids,categories) | 返回标注数据,以文章列表形式 |
2 标注器
2.1 默认标注器
最简单的词性标注器是将所有词都标注为名词NN。这种标注器没有太大的价值。正确率很低。下面演示NLTK提供的默认标注器的用法。import nltk from nltk.corpus import brown default_tagger = nltk.DefaultTagger('NN') sents = 'I am going to Beijing.' print default_tagger.tag(sents) #[('I', 'NN'), ('am', 'NN'), ('going', 'NN'), ('to', 'NN'), ('Beijing', 'NN')] tagged_sents = brown.tagged_sents(categories='news') print default_tagger.evaluate(tagged_sents) #0.1313041
2
3
4
5
6
7
8
9
10
2.2 基于规则的标注器
从默认标注器的评估来看,只有13%的正确率。为了改进这一效果,我们使用一些规则来提高正确率。比如对于ing结尾则柡注为VG,ed结尾则标注为VD。可以通过正则表达式标注器实现这个想法。import nltk from nltk.corpus import brown pattern =[ (r'.*ing$','VBG'), (r'.*ed$','VBD'), (r'.*es$','VBZ'), (r'.*\'s$','NN$'), (r'.*s$','NNS'), (r'.*', 'NN') #未匹配的仍标注为NN ] sents = 'I am going to Beijing.' tagger = nltk.RegexpTagger(pattern) print tagger.tag(nltk.word_tokenize(sents)) #[('I', 'NN'), ('am', 'NN'), ('going', 'VBG'), ('to', 'NN'), ('Beijing', 'VBG'), ('.', 'NN')] tagged_sents = brown.tagged_sents(categories='news') print default_tagger.evaluate(tagged_sents) #0.18751
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2.3 基于查表的标注器
经过增加简单的规则,可以提升默认标注器的准确度,但仍不够好。为此我们统计一下部分高频词的词性,比如经常出现的100个词的词性。利用单个词的词性的统计知识来进行标注,这就是Unigram模型的思想。import nltk from nltk.corpus import brown fdist = nltk.FreqDist(brown.words(categories='news')) common_word = fdist.most_common(100) cfdist = nltk.ConditionalFreqDist(brown.tagged_words(categories='news')) table= dict((word, cfdist[word].max()) for (word, _) in common_word) uni_tagger = nltk.UnigramTagger(model=table,backoff=nltk.DefaultTagger('NN')) print uni_tagger.evaluate(tagged_sents) #0.58171
2
3
4
5
6
7
8
9
10
11
只利用前100个词的历史统计数据便能获得58%的正确率,加大这个词的数量更可以继续提升标注的正确率,当为8000时可以达到90%的正确率。这里我们对不在这100个词的其他词统一回退到默认标注器。
3 训练N-gram标注器
3.1 一般N-gram标注
在上一节中,已经使用了1-Gram,即Unigram标注器。考虑更多的上下文,便有了2/3-gram,这里统称为N-gram。注意,更长的上正文并不能带来准确度的提升。除了向N-gram标注器提供词表模型,另外一种构建标注器的方法是训练。N-gram标注器的构建函数如下:__init__(train=None, model=None, backoff=None),可以将标注好的语料作为训练数据,用于构建一个标注器。
import nltk from nltk.corpus import brown brown_tagged_sents = brown.tagged_sents(categories='news') train_num = int(len(brown_tagged_sents) * 0.9) x_train = brown_tagged_sents[0:train_num] x_test = brown_tagged_sents[train_num:] tagger = nltk.UnigramTagger(train=x_train) print tagger.evaluate(x_test) #0.811
2
3
4
5
6
7
8
9
对于UniGram,使用90%的数据进行训练,在余下10%的数据上测试的准确率为81%。如果改为BiGram,则正确率会下降到10%左右。
3.2 组合标注器
可以利用backoff参数,将多个组合标注器组合起来,以提高识别精确率。import nltk from nltk.corpus import brown pattern =[ (r'.*ing$','VBG'), (r'.*ed$','VBD'), (r'.*es$','VBZ'), (r'.*\'s$','NN$'), (r'.*s$','NNS'), (r'.*', 'NN') #未匹配的仍标注为NN ] brown_tagged_sents = brown.tagged_sents(categories='news') train_num = int(len(brown_tagged_sents) * 0.9) x_train = brown_tagged_sents[0:train_num] x_test = brown_tagged_sents[train_num:] t0 = nltk.RegexpTagger(pattern) t1 = nltk.UnigramTagger(x_train, backoff=t0) t2 = nltk.BigramTagger(x_train, backoff=t1) print t2.evaluate(x_test) #0.8631
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
从上面可以看出,不需要任何的语言学知识,只需要借助统计数据便可以使得词性标注做的足够好。
对于中文,只要有标注语料,也可以按照上面的过程训练N-gram标注器。
4 更进一步
nltk.tag.BrillTagger实现了基于转换的标注,在基础标注器的结果上,对输出进行基于规则的修正,实现更高的准确度。5 示例:中文标注器的训练
下面基于Unigram训练一个中文词性标注器,语料使用网上可以下载得到的人民日报98年1月的标注资料。百度网盘链接。# coding=utf-8 import nltk import json lines = open('9801.txt').readlines() all_tagged_sents = [] for line in lines: line = line.decode('utf-8') sent = line.split() tagged_sent = [] for item in sent: pair = nltk.str2tuple(item) tagged_sent.append(pair) if len(tagged_sent)>0: all_tagged_sents.append(tagged_sent) train_size = int(len(all_tagged_sents)*0.8) x_train = all_tagged_sents[:train_size] x_test = all_tagged_sents[train_size:] tagger = nltk.UnigramTagger(train=x_train,backoff=nltk.DefaultTagger('n')) tokens = nltk.word_tokenize(u'我 认为 不丹 的 被动 卷入 不 构成 此次 对峙 的 主要 因素。') tagged = tagger.tag(tokens) print json.dumps(tagged,encoding='UTF-8', ensure_ascii=False) #["我", "R"], ["认为", "V"], ["不丹", "n"], ["的", "U"], ["被动", "A"], ["卷入", "V"], ["不", "D"], ["构成", "V"], ["此次", "R"], ["对峙", "V"], ["的", "U"], ["主要", "B"], ["因素。", "n"] print tagger.evaluate(x_test) #0.8711
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
28
29
简单的训练,标注器便取得了87.1%的成绩,还是不错的。
相关文章推荐
- 使用opennlp进行词性标注
- Python 使用nltk对数据进行自然语言处理(nlp)
- nlp--使用NLTK进行简单文本分析
- 使用NLPIR 进行中文分词并标注词性
- NLTK学习之二:建构词性标注器
- 如何使用斯坦福pos tagger进行词性标注[转—英文]
- NLTK在去停用词、分词、分句以及词性标注的使用
- 使用NLTK对中文文本进行简单分析
- 【语言处理与Python】5.1使用词性标注器/5.2标注语料库
- 结巴分词和哈工大ltp词性标注结合使用
- 项目自动化之道-1.使用ant进行单步建构
- 使用隐马尔科夫模型Viterbi算法解决词性标注问题
- 使用RNN解决NLP中序列标注问题的通用优化思路
- NLTK中文词性自动标注
- 使用pyltp对分词后的结果进行词性标记
- 使用opennlp进行文档分类
- 使用opennlp进行依存句法分析
- Python NLTK学习6(创建词性标注器)除特别注明外,本站所有文章均为刘杰的个人网站原创 转载请注明出处: http://www.burnelltek.com/blog/60740e24d2f
- JAXB: 使用JAXB标注POJO,进行XML转换
- 百度开源其NLP主题模型工具包,文本分类等场景可直接使用L——LDA进行主题选择本质就是降维,然后用于推荐或者分类