1 有监督的分类

1.1 分类相关概念

分类是为给定输入选择正确的类标签的任务。比如判断一封Email是否是垃圾邮件,确定一篇新闻的主题。
如果分类需要人工标准的标签进行训练,则称为有监督分类。有监督的学习使用下图的框架。

在框架中,特征是一个非常重要的概念。使用分类器首先要决定选择什么 样的特征,以及对特征进行编码。如果没有特征直接输入原始数据,则数据会十分离散而难以训练出有用的模型。

1.2 NLTK的分类器介绍

在NLTK中提供了NaiveBayesClassifier,DecisionTreeClassifier,MaxentClassifier三种类型的分类器。分类器都提供了类方法可以训练出一个分类器实例,有了这个实例,便能对新的样本进行分类预测,以及其进行准确度评测。

方法 说明
train(train_set) 类方法,用于生成一个分类器实例
classify(feature) 实例方法,基于训练的模型对输入特征进行分类
show_most_informative_features() 实例方法,显示训练过程中最有效的特性统计

nltk.classify包的工具类提供了下列的方法辅助训练及优化过程

方法 说明
accuracy(classifier,test_set) 评估分类器在测试集上的准确度
apply_feature(func,data) 将特征函数func应用到data上,类似于map操作

1.3 文本分类示例

下面基于nltk的movie_reviews语料库的正负向标注数据训练一个简单的分类器,用来预测评论的正负向。PS:语料库文本被分两类,pos与neg。
代码先统计出最常用2000个词,简单假设这些词的使用情况可以决定一篇评论的正负向情感。针对每篇文档,特征提取器计算其在这2000个词上出现的情况,若出现则在特性中标记为True,否则标记为False。

import random
import nltk
from nltk.corpus import movie_reviewsdocs = [(list(movie_reviews.words(fileid)),category)for category in movie_reviews.categories()for fileid in movie_reviews.fileids(category)]
random.shuffle(docs)all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
most_common_word = [word for (word,_) in all_words.most_common(2000)]def doc_feature(doc):doc_words = set(doc)feature = {}for word in most_common_word:feature[word] = (word in doc_words)return featuretrain_set = nltk.apply_features(doc_feature,docs[:100])
test_set = nltk.apply_features(doc_feature,docs[100:])classifier = nltk.NaiveBayesClassifier.train(train_set)
print nltk.classify.accuracy(classifier,test_set) #0.735
classifier.show_most_informative_features()
'''
Most Informative Features
hard = True                neg : pos    =      8.6 : 1.0
worst = True               neg : pos    =      7.1 : 1.0
giant = True               neg : pos    =      7.1 : 1.0
unlike = True              pos : neg    =      6.8 : 1.0
entire = True              pos : neg    =      5.6 : 1.0
headed = True              neg : pos    =      5.6 : 1.0
gun = True                 neg : pos    =      5.6 : 1.0
attempt = True             neg : pos    =      5.2 : 1.0
small = True               pos : neg    =      5.0 : 1.0
'''

可以看到出现hard,worst,giant词的文档通常是neg的,出现entire,small词的文档通常是正向的。基于特征词的分类器在测试集上达到了73.5%的正确率。精心构造的对于当前任务透彻理解的特性,通常可以显著提高分类的正确性。

nltk.sentiment包提供了两个情感分析器的实现,使用示例见这里。

类名 说明
SentimentAnalyzer 实现和上面代码的思想一致,只是简单做了些封装,支持传入不同的分类器和使用串联的多个特征提取器。可以直接使用此类进行中文的情感分析。
SentimentIntensityAnalyzer 实现基于《VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social Media Text》这篇文章,思想是基于词典对词进行打分,得到了个分值来表示句子情感的极性。这个类由于规则词典的词都是英文,如果想使用它处理中文,需要自己统计提取中文极性词并打分,以替换掉英文词典。

1.4 过拟合和欠拟合

特性如果选择的太多则会导致算法在训练集上正确率很高,而在测试集上较差的情况,此时就出现了过拟合。尤其是训练数据集较小的情况下更容易出现。因此要平衡特征的选取,以取得算法在未知数据上更好泛化能力。
过拟合的反面是欠拟合,即特征不足。此时通过对失败情况进行分析,改进特征提取器以重建分类器是提升模型准确性的一种方法。但要注意防止出现过拟合。

2 基于上下文的词性标注器

在上一篇文章中,主要介绍了N-gramTagger的词性标注器的使用方法,其主要思想是基于词的词性的历史出现次数进行推测。下面介绍实现一种基于分类器的词性标注器,它借助词本身,词的上下文,标注信息的上下文等特征来训练一个词性分类器,从而实现词性标注。

import nltk
from nltk.corpus import browndef pos_feature_use_hist(sentence,i,history):features = {'suffix-1': sentence[i][-1:],'suffix-2': sentence[i][-2:],'suffix-3': sentence[i][-3:],'pre-word': 'START','prev-tag': 'START'}if i>0:features['prev-word'] = sentence[i-1],features['prev-tag'] =  history[i-1]return featuresclass ContextPosTagger(nltk.TaggerI):def __init__(self,train):train_set = []for tagged_sent in train:untagged_sent = nltk.tag.untag(tagged_sent)history = []for i,(word,tag) in enumerate(tagged_sent):features = pos_feature_use_hist(untagged_sent,i,history)train_set.append((features,tag))history.append(tag)print train_set[:10]self.classifier = nltk.NaiveBayesClassifier.train(train_set)def tag(self,sent):history = []for i,word in enumerate(sent):features = pos_feature_use_hist(sent,i,history)tag = self.classifier.classify(features)history.append(tag)return zip(sent,history)tagged_sents = brown.tagged_sents(categories='news')
size = int(len(tagged_sents)*0.8)
train_sents,test_sents = tagged_sents[0:size],tagged_sents[size:]#tagger = nltk.ClassifierBasedPOSTagger(train=train_sents)  # 0.881
tagger = ContextPosTagger(train_sents)  #0.78
tagger.classifier.show_most_informative_features()
print tagger.evaluate(test_sents)

这个简单只考虑前一个词及前一个词的词性的标注器,在测试集上有约78%的准确度,尚没有上节的组合N-gram标注器的正确率高,这主要是例子中的特征提取器考虑十分简单的缘故。nltk默认实现了一个ClassifierBasedPOSTagger类,可以实现约88%的标注准确度。
例子中实现存在的问题是一旦一个词的词定下来,那么后面就无法修改,即使是后面发现前面判断出了错。解决这个问题有两种方法:一种是采用转换策略,即Brill标注器。另一种对所有的词性标记序列打分,选择总分最高的序列。隐含马尔可夫模型即实现此方法,此外更高级的如最大熵马尔可夫模型,线性条件随机场模型。

3 算法评估方法

3.1 精确度与召回率

对于分类算法在测试集上运行之后,数据会被分为下表的四类

预测\类别 正例 负例
分类为正 TP(真正例) FP(假正例)
分类为负 FN(假负例) TN(真负例)

准确度A:(TP+TN)/ALL 分类器正确分类的比例。
精确度P:TP/(TP+FP), 预测为正的样本中,有多少真的正样本
召回率R:TP/(TP+FN),测试集中的正样本,有多少被正确分类
F1评分:(2*P*R)/(P+R),R与P的调和平均数

3.2 混淆矩阵

对于多分类任务,可以使用混淆矩阵来分析错误分类的细分信息。混淆矩阵的元素m[i,j],表示正确的类别i,被预测为类别j的次数。

import nltk
gold = [1,2,3,4]
test = [1,3,2,4]
print nltk.ConfusionMatrix(gold,test)
'''output| 1 2 3 4 |
--+---------+
1 |<1>. . . |
2 | .<.>1 . |
3 | . 1<.>. |
4 | . . .<1>|
--+---------+
'''

4 分类器模型介绍

4.1 决策树分类器

决策树(decision tree)是一个树结构。其每个非叶节点表示一个特征属性上的测试,而每个叶节点存放一个类别。使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。
下面是一棵形象的决策树:

4.2 朴素贝叶斯分类器

由条件概率和乘法法则:

P(A|B)=P(AB)P(B)=P(B|A)P(A)P(B)

P(A|B) = \frac{P(AB)}{P(B)} = \frac{P(B|A)P(A)}{P(B)}
对于贝叶斯分类器,假设某个样本集有n项特征(Feature),分别为F1、F2、…、Fn。现有m个类别(Category),分别为C1、C2、…、Cm。分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值:

P(C|F1F2...Fn)=P(F1F2...Fn|C)P(C)P(F1F2...Fn)

P(C|F_1F_2...F_n) = \frac{P(F_1F_2...F_n|C)P(C)}{P(F_1F_2...F_n)}
由于 P(F1F2...Fn) P(F_1F_2...F_n) 对于所有的类别都是相同的,可以省略,问题就变成了求 P(F1F2...Fn|C)P(C) P(F_1F_2...F_n|C)P(C)的最大值。
朴素贝叶斯分类器则是更进一步,假设所有特征都彼此独立,因此有

P(F1F2...Fn|C)P(C)=P(F1|C)P(F2|C)...P(Fn|C)P(C)

P(F_1F_2...F_n|C)P(C) = P(F_1|C)P(F_2|C)...P(F_n|C)P(C)
上式等号右边的每一项,都可以从统计资料中得到,由此就可以计算出每个类别对应的概率,从而找出最大概率的那个类。

4.3 最大熵分类器

在信息论中,熵表示离散随机事件的出现概率。一个系统越是有序,信息熵就越低;反之,一个系统越是混乱,信息熵就越高。下面给出一些定义:

4.3.1 熵

如果一个随机变量X的可能取值为X = {x1, x2,…, xk},其概率分布为P(X = xi) = pi(i = 1,2, …, n),则随机变量X的熵定义为:

H(X)=−∑i=1kP(xi)∗log2P(xi)

H(X)=-\sum_{i=1}^kP(x_i)*log_2P(x_i)

4.3.2 条件熵

对于两个随机变量X,Y的联合分布,可以形成联合熵Joint Entropy,用H(X,Y)表示。

在随机变量X发生的前提下,随机变量Y发生所新带来的熵定义为Y的条件熵,用H(Y|X)表示,用来衡量在已知随机变量X的条件下随机变量Y的不确定性,定义为:

H(Y|X)=H(X,Y)–H(X)

H(Y|X) = H(X,Y) – H(X)

4.3.3 相对熵

又称互熵,交叉熵。设p(x)、q(x)是X中取值的两个概率分布,则p对q的相对熵是:

D(p||q)=∑xp(x)logp(x)q(x)=Ep(x)logp(x)q(x)

D(p||q)=\sum_xp(x)log\frac{p(x)}{q(x)}=E_{p(x)}log\frac{p(x)}{q(x)}

4.3.4 互信息

互信息:两个随机变量X,Y的互信息定义为X,Y的联合分布和各自独立分布乘积的相对熵,用I(X,Y)表示。

I(X,Y)=∑x,yp(x,y)logp(x,y)p(x)p(y)=H(X)+H(Y)−H(X,Y)

I(X,Y)=\sum_{x,y}p(x,y)log\frac{p(x,y)}{p(x)p(y)}=H(X)+H(Y)-H(X,Y)

4.3.5 最大熵模型

最大熵模型的本质,就是已知X,计算Y的概率,且尽可能让Y的概率最大(实践中,X可能是某单词的上下文信息,Y是该单词翻译成me,I,us、we的各自概率),从而根据已有信息,尽可能最准确的推测未知信息。模型表示为:

maxH(Y|X)=−∑x,yP(x,y)logP(y|x)

maxH(Y|X)=-\sum_{x,y}P(x,y)logP(y|x)
求解最大熵参数的算法有GIS,IIS,MEGAM,TADM,可以在nltk.classify.maxent类中找到实现。

5 参考文献

1 贝叶斯分类应用:
http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html
2 最大熵模型中的数学推导:
http://blog.csdn.net/v_july_v/article/details/40508465

NLTK学习之三:文本分类与构建基于分类的词性标注器相关推荐

  1. 《大数据》2015年第3期“网络大数据专题”——基于特征学习的文本大数据内容理解及其发展趋势...

    基于特征学习的文本大数据内容理解及其发展趋势 袁书寒,向 阳,鄂世嘉 (同济大学计算机科学与技术系 上海 201804) 摘要:大数据中蕴含着重要的价值信息,文本大数据作为大数据的重要组成部分,是人类 ...

  2. 基于深度学习的文本分类2

    文本表示方法 Part3 词向量 本节通过word2vec学习词向量.word2vec模型背后的基本思想是对出现在上下文环境里的词进行预测.对于每一条输入文本,我们选取一个上下文窗口和一个中心词,并基 ...

  3. Datawhale NLP入门:Task5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

  4. 基于深度学习的文本分类6大算法-原理、结构、论文、源码打包分享

    导读:文本分类是NLP领域一项基础工作,在工业界拥有大量且丰富的应用场景.传统的文本分类需要依赖很多词法.句法相关的human-extracted feature,自2012年深度学习技术快速发展之后 ...

  5. Task5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

  6. Datawhale零基础入门NLP day5/Task5基于深度学习的文本分类2

    基于深度学习的文本分类 本章将继续学习基于深度学习的文本分类. 学习目标 学习Word2Vec的使用和基础原理 学习使用TextCNN.TextRNN进行文本表示 学习使用HAN网络结构完成文本分类 ...

  7. DataWhale NLP组队学习 Task5 基于深度学习的文本分类2

    文章目录 文本表示方法 Part3 词向量 TextCNN TextRNN 基于TextCNN.TextRNN的文本表示 TextCNN TextRNN 使用HAN用于文本分类 本章小结 本章作业 后 ...

  8. Datawhale零基础入门NLP赛事 - Task5 基于深度学习的文本分类2

    在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习基于深度学习的文本分类. 学习目标 学 ...

  9. 新闻文本分类--任务5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

最新文章

  1. 量子计算机 漫画,漫画 | 10分钟看懂量子比特、量子计算和量子算法
  2. wasm + ffmpeg实现前端截取视频帧功能
  3. TypeError: 'module' object is not callable 原因分析(python模块导入注意事项)
  4. 群晖docker_利用群晖docker搭建Minecraft服务器:图形界面操作,傻瓜式教程(附官方服务器端地址)_NAS存储...
  5. 科学家利用计算机模型,科学家尝试利用计算机模拟整个宇宙的演化
  6. inline-block是html5,详解CSS display:inline-block的应用
  7. 用友u8采购发票如何取消审核
  8. R爬虫小白入门:Rvest爬链家网+分析(三)
  9. Android TV开发总结【焦点】
  10. 如何自定义安装mysql_安装MySQL
  11. 第9届蓝桥杯Java组省赛
  12. 万元怎样保留小数点_excel中数值转换成万元后如何只保留两位小数?,excle 万元 元...
  13. AssertionError: Invalid device id
  14. 【Android】关于Call requires API level **(current min is **)却没有错误提示及抛异常...
  15. 【论文简述】CVP-MVSNet:Cost Volume Pyramid Based Depth Inference for Multi-View Stereo(CVPR 2020)
  16. 短信网关协议(cmpp、sgip、smgp、smpp)长短信开发要点
  17. 大学英语综合教程一 Unit 2 课文内容英译中 中英翻译
  18. 12.面向对象(继承/super/接口/抽象类)
  19. 最新Python 实现自动登录抖音(京东),实现滑块自动滑过
  20. Dijkstra算法和A*算法总结

热门文章

  1. 服务器采购项目实施方案
  2. 成为计算几何master之路——记算法竞赛中常用的计几算法及思想
  3. Geant4在Ubuntu(WSL)中,安装过程详解,附Geant4一键安装脚本
  4. 【C++】超级详细,多元一次方程的求解方法
  5. jmeter控制请求执行顺序
  6. 初学编程之代码战争过关体验
  7. 一天彻底搞懂 Git 《Git 原理详解及实用指南》
  8. 移动端canvas画图中遇到的坑
  9. 数学/数论专题:莫比乌斯函数与欧拉函数
  10. HTML解析库Gumbo的使用(一)