关于分类文本,有三个问题

怎么识别出文本中用于明显分类的特征

怎么构建自动分类文本的模型

相关的语言知识

按照这个思路,博主进行了艰苦学习(手动捂脸。。)

一、监督式分类:建立在训练语料基础上的分类

训练过程中,特征提取器将输入转化为特征集,并且记录对应的正确分类。生成模型。预测过程中,未见过的输入被转换特征集,通过模型产生预测标签。

特征提取器和朴素贝叶斯分类器

特征提取器返回字典,这个字典被称为特征集。然后利用

nltk自带的朴素贝叶斯分类器 NaiveBayesClassifier 生成分类器。并且可以用nltk.classify.accuracy(分类器,测试集) 测试准确度。

import nltk

from nltk.corpus import names

import random

def gender_features(word): #特征提取器

return {'last_letter':word[-1]} #特征集就是最后一个字母

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

random.shuffle(names)#将序列打乱

features = [(gender_features(n),g) for (n,g) in names]#返回对应的特征和标签

train,test = features[500:],features[:500] #训练集和测试集

classifier = nltk.NaiveBayesClassifier.train(train) #生成分类器

print('Neo is a',classifier.classify(gender_features('Neo')))#分类

print(nltk.classify.accuracy(classifier,test)) #测试准确度

classifier.show_most_informative_features(5)#得到似然比,检测对于哪些特征有用

当然,当我们训练大的语料库的时候,链表会占用很大内存。这时候nltk提供了:apply_features,会生成链表,但是不会在内存中存储所有对象。

from nltk.classify import apply_features

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

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

过拟合:当特征过多

当特征过多的时候(特征集的键值过多),会对一般化的新例子不起作用,称为过拟合。如果抉择特征集的大小,需要不停的测试,找到最吻合的特征集。

错误分析

为了使特征提取器准确度更高,一般将源数据分为两大部分,三小部分:

开发集:

训练集:负责开发

开发测试集:负责错误分析

测试集:负责最终评估

下面是查找报错信息的案例:

import nltk

from nltk.corpus import names

import random

def gender_features(word): #特征提取器

return {'last_letter':word[-1]} #特征集就是最后一个字母

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

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.NaiveBayesClassifier.train(train_set)

print(nltk.classify.accuracy(classifier,devtest_set))

######################记录报错的案例###############################

errors = []

for (name,tag) in devtest_names:

guess = classifier.classify(gender_features(name))

if guess!=tag:

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

##################################################################

我们发现准确度低,因为倒数第二个字母也很有关联。所以我们可以改进特征提取器:

def gender_features(word): #特征提取器

return {'last_letter':word[-1],'last__letter':word[-2]} #特征集就是最后一个字母和倒数第二个字母

观察结果,发现,准确度提高了12%。重复这个过程,使得特征提取器更加完善。

二、实例:文本分类和词性标注

文本分类

这里的分类标签选成词汇,通过对文本前N个词的观察,得到预测标签。

import nltk

from nltk.corpus import movie_reviews

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

word_features = all_words.most_common(2) #前两千个最常出现的单词

def document_features(document):

document_words = set(document)

features = {}

for (word,freq) in word_features:

features['contains(%s)'%word] = (word in document_words) #参数文档中是否包含word:True/False

return features

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

random.shuffle(documents)

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

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

classifier = nltk.NaiveBayesClassifier.train(train_set)

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

词性标注:“决策树”分类器

这里的分类器是决策树分类器:DecisionTreeClassifier。可以通过classifier.pseudocode(depth = ?) 这查询深度为depth的树,并且打印出来。顺便表示,我再走下面的程序的时候,电脑炸了。建议在集群上运行。

from nltk.corpus import brown

import nltk

suffix_fdist = nltk.FreqDist()

for word in brown.words():

word = word.lower()

#suffix_fdist.inc(word[-1:]) python2

suffix_fdist[word[-1:]] += 1 #python3

suffix_fdist[word[-2:]] += 1

suffix_fdist[word[-3:]] += 1

common_suffixes = suffix_fdist.most_common(100) #获得常见特征链表

#定义特征提取器:

def pos_features(word):

features = {}

for (suffix,times) in common_suffixes:

features['endswith(%s)' % suffix] = word.lower().endswith(suffix)

return features

tagged_words = brown.tagged_words(categories='news')

featuresets = [(pos_features(n),g)for (n,g) in tagged_words]

size = int(len(featuresets)*0.1)

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

classifier = nltk.DecisionTreeClassifier.train(train_set) #“决策树分类器”

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

三、更近一步的连续分类或贪婪序列分类:在朴素贝叶斯和“决策树”之后

这种分类模型是为了获取相关分类之间的依赖关系。为第一个输入找到最佳标签,然后再次基础上找到对应的下一个输入的最佳标签。不断重复,以至所有输入都被贴上标签。所以,我们需要提供一个参数history,用来扩展特征。

事实证明,我的电脑又炸了。

利用联合分类器模型进行词性标注:

import nltk

from nltk.corpus import brown

#带有历史的特征提取器

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:#当它在分界线的时候,没有前置word 和 word-tag

features['prev-word'] = ''

features['prev-tag'] = ''

else:#记录前面的history

features['prev-word'] = sentence[i-1]

features['prev-tag'] = history[i-1]

return features

'''

###########流程式###############

tagged_sents = brown.tagged_sents(categories="news")

size = int(len(tagged_sents)*0.1)

train_sents,test_sents = tagged_sents[size:],tagged_sents[:size]

train_set = []

for tagged_sent in train_sents:

untagged_set = nltk.tag.untag(tagged_sent)

history = []

for i,(word,tag) in enumerate(tagged_sent):

featureset = pos_features(untagged_set,i,history)

history.append(tag)

train_set.append((featureset,tag))

classifier = nltk.NaiveBayesClassifier.train(train_set)

'''

#########类思想重写##################

class ConsecutivePosTagger(nltk.TaggerI): #这里定义新的选择器类,继承nltk.TaggerI

def __init__(self,train_sents):

train_set = []

for tagged_sent in train_sents:

untagged_set = nltk.tag.untag(tagged_sent) #去标签化

history = []

for i,(word,tag) in enumerate(tagged_sent):

featureset = pos_features(untagged_set,i,history)

history.append(tag) #将tag添加进去

train_set.append((featureset,tag)) #拿到了训练集

self.classifier = nltk.NaiveBayesClassifier.train(train_set) #创建训练模型

def tag(self,sentence): #必须定义tag方法

history = []

for i,word in enumerate(sentence):

featureset = pos_features(sentence,i,history)

tag = self.classifier.classify(featureset)

history.append(tag)

return zip(sentence,history)

tagged_sents = brown.tagged_sents(categories="news")

size = int(len(tagged_sents)*0.1)

train_sents,test_sents = tagged_sents[size:],tagged_sents[:size]

#print(train_sents)

tagger = ConsecutivePosTagger(train_sents)

print(tagger.evaluate(test_sents))

四、评估

之前我们选择测试集和开发集,都是在一个原有集合下。这样,示例相似程度很大,不利于推广到其他数据集。而评估最简单的度量就是准确度,即:accuracy()函数。除了这个,精确度、召回率和F-度量值也确实影响了准确度。

- 精确度:发现项目中多少是相关的。TP/(TP+FP)

- 召回率:表示相关项目发现了多少。TP(TP+FN)

- F-度量值:精确度和召回率的调和平均数。

其中,T:true;P:Positive;F:false;N:negative。组合即可。例如TP:真阳性(正确识别为相关的),TN:真阴性(相关项目中错误识别为不想关的)

五、三种分类器的总结

之前我们发现。同样的特征集,朴素贝叶斯分类器就可以轻松跑完,但是决策树分类器不行。除了过拟合的因素外,还是因为树结构强迫特征按照特定的顺序检查,即便他是重复的,而在回溯的过程中,又有重复运算,导致时间和空间的双重浪费。

朴素贝叶斯分类器允许所有恩正“并行”起作用,从计算每个标签的先验概率开始。并且建立朴素贝叶斯的时候采用了平滑技术(在给定的贝叶斯模型上)。

最后的最大熵分类器,使用搜索技术找出一组能最大限度的提高分类器性能的参数。由于他会用迭代优化技术选择参数,花费时间很长。

六、后记

努力地看书了,然而还是没有看懂。感觉是因为相应的数学知识和算法知识没到位。以后积累充足会重看。

当然,对于现在用的层面来说,较深入的了解原理,基本可以解决大多数问题。但是要是做到算法优化,还是要自己去调参,或者改进算法。

由于博主水平有限,希望各路大牛不li赐教。

文本分类 决策树 python_NLTK学习笔记(六):利用机器学习进行文本分类相关推荐

  1. 吴恩达《机器学习》学习笔记六——过拟合与正则化

    吴恩达<机器学习>学习笔记六--过拟合与正则化 一. 过拟合问题 1.线性回归过拟合问题 2.逻辑回归过拟合问题 3.过拟合的解决 二. 正则化后的代价函数 1.正则化思想 2.实际使用的 ...

  2. 吴恩达《机器学习》学习笔记七——逻辑回归(二分类)代码

    吴恩达<机器学习>学习笔记七--逻辑回归(二分类)代码 一.无正则项的逻辑回归 1.问题描述 2.导入模块 3.准备数据 4.假设函数 5.代价函数 6.梯度下降 7.拟合参数 8.用训练 ...

  3. ROS学习笔记六:理解ROS服务和参数

    ROS学习笔记六:理解ROS服务和参数 主要介绍ROS服务和参数,同时使用命令行工具rosservice和rosparam. ROS service service是节点之间互相通信的另一种方式,se ...

  4. JS学习笔记六:js中的DOM操作

    1. JS学习笔记六:js中的DOM操作 文章目录 1. JS学习笔记六:js中的DOM操作 1.1. 获取Dom节点 1.2. 元素属性的操作方式 1.3. DOM节点的创建.插入和删除 1.4. ...

  5. Python学习笔记六——画小猪佩奇

    目录 Python学习笔记六--画小猪佩奇 画布 画笔 属性设置 操纵命令 运动命令 画笔控制命令 全局控制命令 其他命令 Python学习笔记六--画小猪佩奇 使用Python的turtle库可以绘 ...

  6. Ethernet/IP 学习笔记六

    Ethernet/IP 学习笔记六 EtherNet/IP defines two primary types of communications: explicit and implicit (Ta ...

  7. 数据结构学习笔记:利用栈实现进制转换

    数据结构学习笔记:利用栈实现进制转换 一.除基倒取余法示意图 二.编写十进制转换成二进制Python程序 1.源代码 2.运行结果 其实Python提供了一

  8. 数据结构学习笔记:利用Python列表实现栈结构

    数据结构学习笔记:利用Python列表实现栈结构 利用Python列表实现栈结构.有两种实现方式: 1.将列表的末尾(rear)作为栈顶(top) 2.将列表的前端(front)作为栈顶(top) 一 ...

  9. Python学习笔记:利用timeit计算函数调用耗时

    Python学习笔记:利用timeit计算函数调用耗时 一.timeit模块简介 Timer对象包含两个参数:第一个参数是你想要计时的Python语句,第二个参数运行一次来建立测试. 默认情况time ...

最新文章

  1. 算法--------删除重复元素,但保留两个
  2. suricata的简介以及安装过程
  3. ThreadLocal的原理与使用
  4. layui表格弹窗修改_layUI 实现自定义弹窗
  5. 分享到JavaScript实现
  6. codeforces1437 E. Make It Increasing——最长上升子序列
  7. jQuery 利用 $.getJson() 实现跨域
  8. 深度学习福利入门到精通第五讲——ResNet模型
  9. linux环境下创建postgis数据库,Linux下安装Postgis数据库
  10. Windows Server 2012 虚拟化实战:网络(一)
  11. Android应用开发之统计App时长
  12. 在线体验四大名著情景(地图、游戏)
  13. word/excel 通配符
  14. SparkStreaming的背压机制
  15. 微信小程序之分享海报生成
  16. 6、取得平均薪水最高的部门的部门名称【bjpowernode34道SQL题】
  17. 数据可视化第3篇:安装linux操作系统5系列
  18. 《数据结构与算法之二叉平衡树(AVL)》
  19. Linux修改root密码
  20. 《演讲之禅》读书笔记

热门文章

  1. python视频网站项目_Python Flask 项目实战—构建微电影视频网站
  2. 宫崎骏用动漫教给我们的人生哲理,每一句都能说到心里[转]
  3. WifiDisplay开启流程
  4. Spring cloud 通过父工程打包多个子工程
  5. 构筑数字底座,同济医院用全闪存提速智慧医疗
  6. SDN 岗位轮换实验报告
  7. 干货:如何把淘宝买家批量转成微信好友
  8. pdb断点命令_python的pdb调试命令的命令整理及实例
  9. 视频直播点播平台EasyDSS如何通过接口调用实现截取视频的功能?
  10. 计算app用户的留存率