python自然语言处理第六章

1.分类是为给定的输入选择正确的类标签。建立在训练语料基础之上的分类,叫做监督式分类。创建分类器第一步是决定什么样的特征是相关的,以及如何为这些特征编码。下面的特征提取器函数建立了一个字典,其中包含给定名称的相关信息。
 

def gender_features(word):

return {'last_letter':word[-1]}

gender_features('shrek')

这个函数返回的字典叫做特征集,能把特征映射到他们的值。
2.定义一个特征提取器,同时准备一些例子和与其对应的类标签。
 

from nltk.corpus import names

import random

names=([(name,'male') for name in names.words('male.txt')]+

[(name,'female') for name in names.words('female.txt')])

random.shuffle(names) #对元素重新排序

接下来,使用特征提取器处理names数据,并把特征集的结果链表划分为训练集和测试集。训练集用于训练新的“朴素贝叶斯”分类器。
 

featuresets=[(gender_features(n), g) for (n,g) in names] #the last word of each name and it's gender

train_set,test_set=featuresets[500:],featuresets[:500]

classifier=nltk.NaiveBayesClassifier.train(train_set)

#测试没有出现过的名字

classifier.classify(gender_features('Neo')) #male

#利用大量没有出现过的数据评估分类器

print nltk.classify.accuracy(classifier,test_set) #0.785

#检查分类器

classifier.show_most_informative_features(5)

出现的比例叫做似然比,可以用于比较不同特征-结果关系。

3.添加新的特征后再次训练,并且测试其准确性。
 

def gender_features(word):

return {'last_word':word[-1],'first_word':word[0],'length':len(word)}

import nltk

from nltk.corpus import names

import random

names=([(name,'male') for name in names.words('male.txt')]+

[(name,'female') for name in names.words('female.txt')])

random.shuffle(names)

#准备训练集和测试集,训练朴素贝叶斯分类器。

featuresets=[(gender_features(n) ,g) for (n,g) in names]

train_sets,test_sets=featuresets[500:],featuresets[:500]

classifier=nltk.NaiveByvesClassifier(train_sets)

#测试分类器

classifier.calssify(gender_features('Neo'))

#评估分类器

print nltk.classify.accurcy(classifier,test_set)

#检查分类器

classifier.show_most_informative_features(5)

4.在处理大量语料库时,构建包含所有实例特征的单独链表会占用大量的内存。在这种情况下,使用函数nltk.classify_features,返回一个像链表但是不会在内存中存储的所有特征集的对象。
 

from nltk.classify import apply_features

train_set=apply_features(gender_features,name[500:])

test_set=apply_features(gender_features,name[:500])

5.特征提取器过拟合性别特征。这个特征提取器返回的特征集中包括大量的指定特征,从而导致相对较小的名字语料库产生了过拟合。
 

def gender_features2(name):

features={}

feature["firstletter"]=name[0].lower()

features["lastletter"]=name[-1].lower()

for letter in 'abcdefghijklmnopqrstuvwxyz':

features["count(%s)" % letter]=name.lower().count(letter)

features["has(%s)" %letter]=(letter in name.lower())

return feature

gender_features2('John') #调用

{'count(j)':1,'has(d)':False,'count(b)':0,.....}

过拟合:如果你提供太多的特征,那么算法将高度依赖训练数据的特征而对一般化的新例子不起作用。在小型训练集上容易出现这种问题。
 

featuresets=[(gender_features2(n),g) for (n,g) in names]

train_set,test_set=featuresets[500:],featuresets[:500]

classifier=nltk.NaiveBayvesClassifier.train(train_set)

print nltk.classify.accuracy(classifier,test_set)

选定那个初始特征集,一种能有效完善特征集的方法叫做错误分析。首先,选择开发集,其中包含用于创建模型的语料数据。然后将这种开发集分为训练集和开发测试集。训练集用于训练模型,开发测试集用于执行错误分析,测试集用于系统的最终评估。
 

train_names=names[1500:]

devtest_names=names[500:1500]

test_names=names[:500]

将语料分为适当的数据集,然后使用训练集来训练模型,之后在开发集上运行。
 

train_set=[(gender_features(n),g) for (n,g) in train_names]

devtest_set=[(gender_features(n),g) for (n,g) in devtest_names]

test_set=[(gender_features(n),g) for (n,g) in test_names]

classifier=nltk.NaivNayvesClassifier.train(train_set)

pritn nltk.calssity.accuracy(classifier,dectest_set)

使用开发测试集可以生成分类器在预料名字性别时出现错误列表。
 

errors=[ ]

for (name,tag) in devtest_names:

guess=classifier.classify(gender_features(name))

if guess!=tag:

errors.append((tag,guess,name))

6.文档分类。
 

from nltk.corpus import movie_reviews

documents=[(list(movie_review.words(fileid)),category)

for catogiry in movie_reviews.categories()

for fileid in moive_review.fileids(category)]

random.shuffle(documents)

文档分类的特征提取器,其特征表示每个词是否在一个给定的文档中。
 

all_words=nltk.FreqDist(w.lower() for w in movie_reviews.words())

word_features=all_words.keys()[:2000]

def features(document):
document_words=set(document)
features={}
for word in word_features:
features['cotains(%S)' %word]=(word in document_words)
return features
print document_features(movie_reviews.words('pos/cv957_8737.txt'))

训练和测试分类器以进行文档分类。
 

featuresets=[(document_features(d),c) for (d,c) in documents]

train_set,test_set=featuresets[100:],featuresets[:100]

calssifier=nltk.NaiveBayvesClassifier.train(train_set)

print nltk.classify.accuracy(calssifier,test_set)

classifier.show_most_informative_features(5)

7.词性标注。首先找出最常见的后缀。
 

from nltk.corpus import brown

suffix_fdist=nltk.FreqDist()

for word in brown.words():

word=word.lower()

suffix_fdist.inc(word[-1:])

suffix_fdist.inc(word[-2:])

sufix_fdist.inc(word[-3:])

common_suffixes=suffix_fdist.keys()[:100]

print common_suffixes

接下来定义一个提取器函数,来检查给定单词的后缀。
 

def pos_features(word):
features={ }
for suffix in common_suffixes:
features['endswith(%s)' %suffix]=word.lower().endswith(suffix)
return features

定义特征提取器,可以用它来训练新的‘决策树’的分类器。
 

tagged_words=brown.tagged_words(categories='news')
features=[(pos_features(n),g) for (n,g) in tagged_words]
size=int(len(features)*01.)
train_set,test_set=featuresets[size:],featuresets[:size]
classifier=nltk.NaiveBayvesClassifier.train(train_set)
nltk.Classify.accuracy(classifier,test_set)
classifier.classify(pos_features('cast'))

print classifier.pseudicode(depth=4)

8.探索上下文语境。
 

def pos_features(sentence,i):
features={"suffix(1)":sentence[i][-1:],
"suffix(2):"sentence[i][-2:],
"suffix(3):"sentence[i][-3:]}
if i==0:
features["prev-word"]="<START>"
else:
features["prev-word"]=sentence[i-1]
return features
pos_features(brown.sents()[0],8)
tagged_words=brown.tagged_words(categoories='news')
featuresets=[ ]
for tagged_sent in tagged_sents:
untagged_sent =nltk.tag.untag(tagged_sent)
for i,(word,tag) in enumerate(tagged_sent):
featuresets.apend(
(pos_features(untagged_seng,i),tag))
size=int(len(featuresets)*0.1)
train_set,test_set=featuresets[size:],featuresets[:size]
classifier=nltk.NaiveBayvesClassifier.train(train_set)
nltk.classity.accuracy(classifier,test_set)

9.使用连续分类器进行词性标注。
 
 

def pos_features(sentence,i,history):
features={"suffix(1)":sentence[i][-1:],
"suffix(2)":sentence[i][-2:],
"suffix(3)":sentence[i][-3:]}
if i==0:
features["pre_word"]="<START>"
features["pre_word"]="<START>"
else:
features["pre_word"]=sentence[i-1]
features["pre_word"]=sentence[i-1]
return reatures

class ConsecutivePosTagger(nltk.TaggerI):
def __init__(self,train_sents):
train_set=[]
for tagged_sent in tagged_sents:
untagged_sent=nltk.tag.untag(tagged_sent)
history=[]
for i,(word,tag) in enumerate(tagger_sent):
featureset=pos_reatures(untagged_sent,i,history)
train_set.append((featureset,tag))
history.append(tag)
self.classifier=nltk.NaiveBayvesClassifier.train(train_set)

def tag(self,sentence):
history=[]
for i,word in enumerate(sentence):
featureset=pos_feaures(sentence,i,history)
tag=self.classifier.classify(featureset)
history.append(tag)
return zip(sentence,history)

tagged_sent=brown.tagged_sent(categories='news')
size=int(len(tagged_sents)*0.1)
train_sents,test_sents=tagged_sents[size:],tagged_sents[:size]
tagger=ConsecutivePosTagger(train_sents)
print tagger.evaluate(test_sents)

10.监督式分类举例。
第一步:获得一些已被分割成句子的数据,将它转换成一种适合提取特征的形式。
 
 

sents=nltk.corpus.treebank_raw.sents()
tokens=[]
boundaries=set()
offset=0
for sent in nltk.corpus.treebank_raw.sents():
tokens.extend(sent)
offset+=len(sent)
boundaries.add(offset-1)

下一步,指定用于决定标点是否表示句子边界的数据特征。tokens是单独句子标识符的合并链表,boundaries是一个包含所有句子边界标识符索引的集合。
 
 

def punct_features(tokens,i):
return {'netx-word-capitalized':tokens[i+1][0].isupper(), #判断首字母是否为大写
'prevword':tokens[i-1].lower(), #判断是否为小写
'punct':tokens[i],
'prev-word-is-one-char':len(token[i-1])==1}

基于这一特征提取器,我们可以通过选择所有的标点符号创建一个加标签的特征集链表,然后标注他们是否是边界标识符。
 
 

featuresets=[(punct_features(tokens,i),(i in boundaries))
for i in range(1,len(tokens)-1)
if tokens[i] in '.?!']

11.“认识文字蕴涵“的特征提取器。RTEFeatureExtractor类建立的一个在文本和假设中都有的并已经除去了一些停用词后的词汇包。然后计算重叠性和差异性。
 
 

def rte_features(retpair):
extractor=nltk.RTEFeatuerExtractor(rtepair)
features={}
features['word_overlap']=len(extractor.overlap('word'))
features['word_hyp_extra']=len(extractor.hyp_extra('word'))
features['ne_overlap']=len(extractor.overlap('ne'))
features['ne_hyp_extra']=len(extractor.hyp_extra('ne'))
return features

12.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值