一 使用词型标注器
一个词性标注器(part-of-speech tagger 或POS tagger)处理一个词序列,为每个词附加一个词性标记。
nltk.pos_tag() 对单词词性进行标记
import nltk
text=nltk.word_tokenize("And now for something completely different")
print(nltk.pos_tag(text))
import nltk
# 同形同音异义词
text=nltk.word_tokenize("They refuse to permit us to obtain the refuse permit")
print(nltk.pos_tag(text))
refuse和permit都以现在动词(VBP)和名词(NN)形式出现。
二 已经标注的语料库
1.表示已经标注的词符
nltk.tag.str2tuple
一个已标注的词符使用一个由词符和标记组成的元组来表示
可以使用函数str2tuple()从表示一个已标注的词符的标准字符串创建一个这样的特殊元组(从字符串→元组)
构建已标注词符列表的字符串
第一步对字符串分词便能访问单独的单词/标记 字符串,然后将每一个转换成一个元组(使用str2tuple())
import nltk
sent = '''
The/AT grand/JJ jury/NN commented/VBD on/IN a/AT number/NN of/IN
other/AP topics/NNS ,/, AMONG/IN them/PPO the/AT Atlanta/NP and/CC
Fulton/NP-tl County/NN-tl purchasing/VBG departments/NNS which/WDT it/PPS
said/VBD ``/`` ARE/BER well/QL operated/VBN and/CC follow/VB generally/RB
accepted/VBN practices/NNS which/WDT inure/VB to/IN the/AT best/JJT
interest/NN of/IN both/ABX governments/NNS ''/'' ./.
'''
print([nltk.tag.str2tuple(t) for t in sent.split()])
2.读取已标注的语料库
其他语料库使用各种格式存储词性标记。
只要语料库包含已标注的文本,NLTK的语料库接口都将有一个tagged_words()方法,输出文本及对应标注
tagset=‘universal’ 转换成统一词型名称
nltk.corpus.brown.tagged_words()
nltk.corpus.brown.tagged_words(tagset='universal')
3 通用词型标记集
三 使用python字典映射单词到其他属性
字典数据类型
1 python中的字典
做任意类型之间的映射
定义pos为一个空字典 添加一些词的词型
pos={}
pos['colorless']='ADJ'
pos['ideas']='N'
pos['sleep']='V'
pos['furiously']='ADV'
print(pos)
在字典pos中,键’colorless’被分配了值’ADJ’
pos中的值 就是键-值对的集合
可以使用键来检索值
print(pos['ideas'])
print(pos['colorless'])
请注意它们的顺序与最初放入它们的顺序不同;这是因为字典不是序列而是映射,键没有固定地排序。(?)
将字典转换成列表 使用list(pos) / sorted(pos)
用for循环遍历字典中所有键
for word in sorted(pos):
print(word+":",pos[word])
字典的方法keys()、values()和items()允许我们以单独的列表访问键、值以及键-值对。
我们甚至可以排序元组,按它们的第一个元素排序(如果第一个元素相同,就使用它们的第二个元素)。
print(list(pos.keys()))
print(list(pos.values()))
print(list(pos.items()))
for key,val in sorted(pos.items()):
print(key+":",val)
使用列表值存储多个值
pos['sleep'] = ['N', 'V']
2 默认字典
如果我们试图访问一个不在字典中的键,会得到一个错误。然而,如果一个字典能为这个新键自动创建一个条目并给它一个默认值,如0或者一个空链表,将是有用的。由于这个原因,可以使用一种特殊的称为defaultdict的字典。为了使用它,我们必须提供一个参数,用来创建默认值,如int, float, str, list, dict, tuple。
from collections import defaultdict
fre=defaultdict(int)
fre['colorless']=4
print(fre['ideas'])
pos=defaultdict(list)
pos['sleep']=['N','V']
print(pos['ideas'])
这些默认值实际上是将其他对象转换为指定类型的函数(例如int(“2”), list(“2”))。当它们不带参数被调用时——int(),
list()——它们分别返回0和[] 。
前面是指定字典项的默认值为一个特定的数据类型的默认值。然而,也可以指定任何我们喜欢的默认值
from collections import defaultdict
pos=defaultdict(lambda :'N')
pos['colorless']='ADJ'
print(pos['blog'])
3 更新字典
from collections import defaultdict
from nltk.corpus import brown
from operator import itemgetter
# 计数文本中的每个词型标记。如果标记之前没有出现,则默认为零。每次遇到一个标记,使+=递增计数
# counts tag和相应计数的映射
counts=defaultdict(int)
for (word,tag) in brown.tagged_words(categories='news',tagset='universal'):
counts[tag]+=1
# 按值排序一个字典,按频率递减顺序显示词汇
# sorted()的第一个参数是要排序的项目,它是由一个词性标记和一个频率组成的元组的列表。
# 第二个参数使用函数itemgetter()指定排序的键。
# 最后一个参数指定项目是否应被按相反的顺序返回,即频率值递减。
print(sorted(counts.items(),key=itemgetter(1),reverse=True))
print([t for t,c in sorted(counts.items(),key=itemgetter(1),reverse=True)])
更新字典方法
初始化一个defaultdict,用for循环更新其值
按单词最后两个字母索引词汇
from collections import defaultdict
import nltk
last_letters=defaultdict(list)
words=nltk.corpus.words.words('en')
for word in words:
key=word[-2:]
last_letters[key].append(word)
print(last_letters['ly'])
print(last_letters['zy'])
创建一个将单词中的字母按序排列的字典
from collections import defaultdict
import nltk
anagrams=defaultdict(list)
words=nltk.corpus.words.words('en')
for word in words:
key=''.join(sorted(word))
anagrams[key].append(word)
print(anagrams['aeilnrt'])
其中sorted重新生成一个list,使单词中的字母按顺序排列
word='entrail'
print(sorted(word))
四 自动标注
1 默认标注器
将所有词都标注成NN的标注器
raw='I do not like green eggs and ham, I do not like them Sam I am!'
tokens=nltk.word_tokenize(raw)
default_tagger=nltk.DefaultTagger('NN')
print(default_tagger.tag(tokens))
2 正则表达式标注器
nltk.RegexpTagger
from nltk.corpus import brown
import nltk
brown_tagged_sents=brown.tagged_sents(categories='news')
brown_sents=brown.sents(categories='news')
patterns=[
(r'.*ing$','VBG'), # ing结尾的 现在进行
(r'.*ed$','VBD'), # ed结尾 简单过去
(r'.*es$','VBZ'), # 第三人称
(r'.*ould$','MD'), # 情态动词
(r'.*\'s$','NN$'), # 名词所有格
(r'.*s$','NNS'), # 名词复数
(r'^-?[0-9]+(.[0-9]+)?$','CD'), # 基数
(r'.*','NN') # 名词(默认)
]
regexp_tagger = nltk.RegexpTagger(patterns)
print(regexp_tagger.tag(brown_sents[3]))
注意!正则表示式是顺序处理的,第一个匹配上的会被使用
此例中标注所有词为名词
3 查询标注器
NLTK UnigramTagger(一元标注器)
# 找到100个最频繁的词 存储最有可能的标记
fd=nltk.FreqDist(brown.words(categories='news'))
cfd=nltk.ConditionalFreqDist(brown.tagged_words(categories='news'))
most_freq_words=fd.most_common(100)
likely_tags=dict((word,cfd[word].max()) for (word,_) in most_freq_words)
# 使用这个信息作为“查找标注器”的模型
baseline_tagger=nltk.UnigramTagger(model=likely_tags)
sent=brown.sents(categories='news')[3]
print(baseline_tagger.tag(sent))
要先使用查找表,如果它不能指定一个标记就使用默认标注器,这个过程叫做回退
配置默认标注器
baseline_tagger=nltk.UnigramTagger(model=likely_tags,backoff=nltk.DefaultTagger('NN'))
五 N-gram标注
1 组合标注器
尝试使用二元标注器标注标识符。
如果二元标注器无法找到一个标记,尝试一元标注器。
如果一元标注器也无法找到一个标记,使用默认标注器。
from nltk.corpus import brown
import nltk
brown_tagged_sents = brown.tagged_sents(categories='news')
# 分离训练和测试数据
size=int(len(brown_tagged_sents)*0.9)
train_sents=brown_tagged_sents[:size]
test_sents=brown_tagged_sents[size:]
# 组合标注器
t0=nltk.DefaultTagger('NN')
t1=nltk.UnigramTagger(train_sents,backoff=t0)
t2=nltk.BigramTagger(train_sents,backoff=t1)
print(t2.evaluate(test_sents))
六 基于转换的标注
Brill标注 基于转换的学习
猜每个词的标记,然后返回和修复错误