第六章 -文本分类

6.1 监督分类

本章问题

1.我们应该如何识别语言数据中对特征分类非常重要的特殊特征?
2.我们如何构建可以用来自动执行语言处理任务的语言模型?
3.我们能从这些模型中学习到关于语言的什么内容?
分类任务的例子?
1.决定邮件是不是垃圾邮件
2.决定一个文章是哪个话题区域下的?例如:运动,科技,政治
3.确定一个出现的单词"bank"是不是指"river bank"还是指一个金融机构(银行),还是指倾斜,还是将…存入银行
如果分类器是基于包含每个输入都有正确标签的训练语料库构建的,则称为有监督分类器。

6.1.1性别鉴定

我们看到男性和女性的名字有一些独特的特点。
以a、e和i结尾的名字很可能是女性,而以k、o、r、s和t结尾的名字很可能是男性。
让我们构建一个分类器来更精确地建模这些差异。

输出名字的最后一个字母作为性别特征

def gender_features(word):
  return {'last_letter': word[-1]}
print(gender_features('Shrek'))

打乱带标签的名字列表

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

获取特征集,后面得作为训练集,前面的作为测试集,用贝叶斯分类器训练,随机给一个名字测试分类器是否正确

featuresets = [(gender_features(n), gender) for (n, gender) in labeled_names]
train_set, test_set = featuresets[500:], featuresets[:500]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print(classifier.classify(gender_features('Neo'))) #male
print(classifier.classify(gender_features('Trinity'))) #female

测试分类器的正确率

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

通过分类器得到对性别最有效,最有区分度的前五个字母

classifier.show_most_informative_features(5)

在处理大型语料库时,构造一个包含每个实例特性的列表可能会占用大量内存。
在这些情况下,使用nltk.classification.apply_features函数,它返回一个对象,
该对象的作用类似于列表,但不将所有特性集存储在内存中

train_set = apply_features(gender_features, labeled_names[500:])
test_set = apply_features(gender_features, labeled_names[:500])

6.1.2 选择正确的特征

通常情况下,分类器是通过反复试验的过程构建的,由与问题相关的信息的直觉指导。通常从“kitchen sink”方法开始,包括您能想到的所有特性,然后检查哪些特性实际上是有用的。
分析词的特征,一个单词中每个字母包含几个,是否包含

def gender_features2(name):
  features = {}
  features["first_letter"] = name[0].lower()
  features["last_letter"] = name[-1].lower()
  for letter in 'abcdefghijklmnopqrstuvwxyz':
    features["count({})".format(letter)] = name.lower().count(letter)
    features["has({})".format(letter)] = (letter in name.lower())
  return features
print(gender_features2('John'))

然而,对于给定的学习算法,您应该使用的特性的数量通常是有限制的——如果您提供了太多的特性,那么该算法将更有可能依赖于您的训练数据的特性,而这些特性不能很好地推广到新样本中。这个问题被称为过度拟合,给features2计算accuracy
一旦选择了一组初始特征,一种非常有效的细化特征集的方法是错误分析。首先,我们选择一个开发集,其中包含用于创建模型的语料库数据。然后将这个开发集细分为训练集和开发测试集。
训练集用于训练模型,开发测试集用于进行误差分析。测试集用于我们对系统的最终评估。
由于下面讨论的原因,重要的是我们使用一个单独的开发测试集来进行错误分析,而不仅仅是使用测试集。语料库数据划分为不同子集的方法如1.3所示。
将语料库划分为适当的数据集之后,我们使用训练集训练一个模型,然后在开发测试集上运行它。

train_names = labeled_names[1500:]
devtest_names = labeled_names[500:1500]
test_names = labeled_names[:500]

train_set = [(gender_features(n), gender) for (n, gender) in train_names]
devtest_set = [(gender_features(n), gender) for (n, gender) in devtest_names]
test_set = [(gender_features(n), gender) for (n, gender) in test_names]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print(nltk.classify.accuracy(classifier, devtest_set)) #0.758

使用dev-test集,我们可以生成一个分类器在预测姓名性别时产生的错误列表:

6.1.3文档分类

获取电影评论里的所有文件

documents = [([movie_reviews.words(fileid)], category)
             for category in movie_reviews.categories()
             for fileid in movie_reviews.fileids(category)]
random.shuffle(documents)

电影评论里所有词中用的最多的前2000个词

all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
word_features = [all_words][:2000]

某一个文件里是否包含前2000个词

def document_features(documents):
    document_words = documents
    features = {}
    for word in word_features:
      features['contains({})'.format(word)] = (word in document_words)
    return features
print(document_features(movie_reviews.words('D:/nltk_data/corpora/movie_reviews/neg/cv000_29416.txt')))

6.1.4词性标注

前100个高频后缀(1,2,3一共3个长度)

suffix_fdist = nltk.FreqDist()
for word in brown.words():
    word = word.lower()
    suffix_fdist[word[-1:]] += 1
    suffix_fdist[word[-2:]] += 1
    suffix_fdist[word[-3:]] += 1 
common_suffixes = [suffix for (suffix, count) in suffix_fdist.most_common(100)]

给定一个词,看它的后缀是不是在那100个高频的后缀里

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

获取brown news类别下有标签的词的特征集合(是否以那100个高频后缀结尾&这个词的词性)

tagged_words = brown.tagged_words(categories='news')
featuresets = [(pos_features(n), g) for (n,g) in tagged_words]

取前1/10做测试集,后面的数据做训练集,然后用决策树训练得到分类器

train_set, test_set = featuresets[size:], featuresets[:size]
classifier = nltk.DecisionTreeClassifier.train(train_set)

用测试集测试分类器的准确率
print(nltk.classify.accuracy(classifier, test_set))
print(classifier.classify(pos_features(‘cats’))) #0.6270512182993535
print(classifier.pseudocode(depth=4))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值