文本分类--普通分类

1 基本概念

文本分类
文本分类(text classification),指的是将一个文档归类到一个或多个类别的自然语言处理任务。文本分类的应用场景非常广泛,包括垃圾邮件过滤、自动打标等任何需要自动归档文本的场合。
文本分类在机器学习中属于监督学习,其流程是:人工标注文档类别、利用语料训练模型、利用模型训练文档的类别。

2 问题

总结文本分类的一般流程;

3 解决思路

3.1 文本的特征提取

特征选择是特征工程中的重要一环,其主要目的是从所有特征中选出相关特征 (relevant feature),或者说在不引起重要信息丢失的前提下去除掉无关特征 (irrelevant feature) 和冗余特征 (redundant feature)。进行特征选择的好处主要有以下几种:

  1. 降低过拟合风险,提升模型效果
  2. 提高训练速度,降低运算开销
  3. 更少的特征通常意味着更好的可解释性
    在向量空间模型中,表示文本的特征项可以选择文字、词、短语、甚至“概念”等多种元素,目前常用的特征提取方法有:基于文档频率的特征提取法、信息增益法、 χ2
    统计量法、互信息法等。

3.2 卡方特征选择

在文本分类时会有这样一个问题,比如汉语中的虚词“的”,这些词在所有类别的文档中均匀出现,为了消除这些单词的影响,一方面可以用停用词表,另一方面可以用卡方非参数检验来过滤掉与类别相关程度不高的词语。

在统计学上,卡方检验常用于检验两个事件的独立性,如果两个随机事件 A 和 B 相互独立,则两者同时发生的概率P(AB)= P(A)P(B)。如果将词语的出现与类别的出现作为两个随机事件则类别独立性越高的词语越不适合作为特征。如果将某个事件的期望记作 E,实际出现(观测)的频次记作 N,则卡方检验衡量期望与观测的相似程度。卡方检验值越高,则期望和观测的计数越相化也更大程度地否定了独立性。

具体细节可参考宗成庆《统计自然语言处理》第二版13.3.3 χ2\chi^2χ2t统计量

3.3 分类器的选择和训练

理论上讲,在文本特征抽取之后,就进入了常规机器学习分类模型的框架,但作为文本分类也有其特殊性,主要有以下几点:

  1. 自变量(词条)数量极多;
  2. 各自变量之间(词条)不可能完全独立;
  3. 大部分自变量(词条)都是干扰项,对分类没有贡献;

所以在分类模型选择上主要考虑以下几点:

  1. 速度-文本数据量一般比较大;
  2. 变量筛选能力-能够从大部分是无效变量的情况下筛选出有效变量;
  3. 容错性-分类模型是建立在特征抽取的基础上,特征抽取过程本身不可避免的带来部分信息差错;
  4. 共线容忍度-词条之间不可能相互独立,很多模型都有变量的独立性假设。
    基于上面两个方面的考虑,文本分类的模型通常使用朴素贝叶斯、svm两个模型。

关于Naive Bayes、svm数学细节参考《统计学习方法》;

3.4 非常规方法

文本分类不一定需要分词,根据清华大学2016年的工作THUCTC:An Efficient Chinese Text Classifier,将文中相邻两个字符构成的所有二元语法作为“词”,反而可以取得更好的分类准确率;

4 实现

4.1 准备文本分类语料库

数据的目录结构如下:
搜狗门户数据(汽车(1000个txt文档)、教育(1000个txt文档)、健康(1000个txt文档)、军事(1000个txt文档)、体育(1000个txt文档))

from pyhanlp import *
corpus_path = r'/Users/kitty/Work/Projects/text_mining/data/搜狗文本分类语料库迷你版'
# 把数据加载到内存中,查看数据属性
MemoryDataSet = JClass('com.hankcs.hanlp.classification.corpus.MemoryDataSet')
dataSet = MemoryDataSet()  # 将数据集加载到内存中
dataSet.load(corpus_path)  # 加载data/test/搜狗文本分类语料库迷你版
allClasses = dataSet.getCatalog().getCategories()  # 获取标注集
print("标注集:%s" % (allClasses))
for document in dataSet.iterator():print("第一篇文档的类别:" + allClasses.get(document.category))break

运行结果:

标注集:[教育, 汽车, 健康, 军事, 体育]
第一篇文档的类别:教育

4.2 准备分词器

BigramTokenizer = JClass('com.hankcs.hanlp.classification.tokenizers.BigramTokenizer')
HanLPTokenizer = JClass('com.hankcs.hanlp.classification.tokenizers.HanLPTokenizer')
BlankTokenizer = JClass('com.hankcs.hanlp.classification.tokenizers.BlankTokenizer')
tokenizer = BigramTokenizer()

4.3 准备训练集

FileDataSet = JClass('com.hankcs.hanlp.classification.corpus.FileDataSet')
training_corpus = FileDataSet().setTokenizer(tokenizer).load(corpus_path, "UTF-8", 0.9)

4.4 卡方特征选择

这个方法和相应的参数都被隐藏的模型中,用户只需知道分词后需要进行卡方特征选择。

4.5 准备分类器

NaiveBayesClassifier = JClass('com.hankcs.hanlp.classification.classifiers.NaiveBayesClassifier')
LinearSVMClassifier = JClass('com.hankcs.hanlp.classification.classifiers.LinearSVMClassifier')
model_class = LinearSVMClassifier

4.6 训练模型

IOUtil = SafeJClass('com.hankcs.hanlp.corpus.io.IOUtil')
model_path = r'/Users/kitty/anaconda3/envs/nlp/lib/python3.6/site-packages/pyhanlp/static/data/test/'
def train_or_load_classifier(model_class, model_path, training_corpus):classifier = model_class()model_path += classifier.getClass().getSimpleName() + '.ser'if os.path.isfile(model_path):print(model_path)return model_class(IOUtil.readObjectFrom(model_path))classifier.train(training_corpus)model = classifier.getModel()IOUtil.saveObjectTo(model, model_path)return model_class(model)classifier = train_or_load_classifier(model_class, model_path, training_corpus)

4.7 评测训练效果

精细评测:对于每个分类都有一套P、R、F1P、R、F_1PRF1
整体评测:衡量模型在所有类目上的整体性能,则可以利用这些指标在文档颗粒度进行微平均,具体如下:
P‾=∑ci∈CTP∑ci∈CTP+∑ci∈CFPP‾=∑ci∈CTP∑ci∈CTP+∑ci∈CFNF1‾=2×P‾×R‾P‾+R‾\begin{aligned} \overline{P} &= \frac{\sum_{c_i \in C}TP}{\sum_{c_i \in C}TP + \sum_{c_i \in C}FP} \\ \overline{P} &= \frac{\sum_{c_i \in C}TP}{\sum_{c_i \in C}TP + \sum_{c_i \in C}FN} \\ \overline{F_1} &= \frac{2 \times \overline{P} \times \overline{R}}{\overline{P} + \overline{R}} \end{aligned} PPF1=ciCTP+ciCFPciCTP=ciCTP+ciCFNciCTP=P+R2×P×R

下面实现采用后一种方式:

Evaluator = JClass('com.hankcs.hanlp.classification.statistics.evaluations.Evaluator')def evaluate(classifier, corpus_path, tokenizer):testing_corpus = MemoryDataSet(classifier.getModel()).load(corpus_path, "UTF-8", -0.1)result = Evaluator.evaluate(classifier, testing_corpus)print(classifier.getClass().getSimpleName() + "+" + tokenizer.getClass().getSimpleName())print(result)evaluate(classifier, corpus_path, tokenizer)

运行结果:

LinearSVMClassifier+BigramTokenizerP	     R	    F1	     A	      93.27	 97.00	 95.10	 98.00	教育98.02	 99.00	 98.51	 99.40	汽车98.97	 96.00	 97.46	 99.00	健康98.00	 98.00	 98.00	 99.20	军事
100.00	 98.00	 98.99	 99.60	体育97.65	 97.60	 97.63	 97.60	avg.
data size = 500, speed = 7936.51 doc/s

4.8 {NB, SVM} ❌ {中文分词、二元语法}

在这里插入图片描述
中文文本分类的确不需要分词,不分词直接用元语法反而能够取得更高的准确率。只不过由于二元语法数量比单词多,导致参与运算的特征更多,相应的分类速度减半。
线性支持向量机的分类准确率更高,而且分类速度更快,推荐使用。

5 参考文献

  1. 何晗《自然语言处理入门》;
  2. 宗成庆《统计自然语言处理》;
  3. 李航《统计学习方法》;

6 需要解决的问题

  1. 当文档被转化为向量后,就彻底脱离了语言、句子等语料的约束,进入机器学习的范畴了,所以文本特征选择是关键的一步,尤其在传统机器学习中。总结文本特征选择的常用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 烧写(1)

第一部分: 一、BootLoader的概念 BootLoader是系统加电启运行的第一段软件代码.回忆一下PC的体系结构我们可以知道,PC机中的引导加载程序由BIOS(其本质就是一段固件程序)和位于硬盘MBR中的引导程序一起组成。BIOS在完成硬件检测和…

利用websocket实现一对一聊天

一对一聊天websocket1. 效果展示2. 业务分析(逻辑展示...)3. 技术点功能 即时发送消息||随时发送消息历史消息显示已读未读状态 1. 效果展示 由于没做登录,就以jack和rose两人聊天 两人可相互发消息 持续输出. . 当只有jack在线时 嘤…

中文分词--词典分词--最长匹配

(个人学习笔记,慎重参考) 1 基本概念 中文分词 指的是将一段文本拆分为一系列单词的过程,这些单词顺序拼接后等于原文本。 作为中文信息处理的第一站,是后续nlp任务的基础,中文分词算法大致可分为词典规则…

PLSQL Developer 运用Profiler 分析存储过程性能

最近应公司需要,需要编写ORACLE存储过程。本人新手,在完成存储过程的编写后,感觉需要对存储过程中各个语句的执行时间进行分析,以便 对整个存储过程进行优化。 由于用的是PLSQL Developer 客户端工具,而网上大多介绍的…

四、Dynamic-programming algorithm Dynamic--LCS

(学习笔记,无什参考价值!) 1 问题 2 算法 2.1 Brute-force LCS algorithm 检查每一个subsequence是否是yyy的子列时,遍历yyy的每一个元素,看是否依次可以全部覆盖subsequence所有元素,所以其复杂度为O(n)O(n)O(n); …

五、分治法应用--矩阵乘法

1 朴素算法 这个算法就是矩阵乘法的定义: 很容易看出这个算法复杂度是Θ(n3)\Theta(n^3)Θ(n3)。 2 递归算法 分治法首先是从分割问题开始的,得到数学上的递归关系后,然后使用递归的方式实现。 由上面的数学性质,可以使用递…

POJ 1300 Door Man(欧拉回路的判定)

题目链接 题意 : 庄园有很多房间,编号从0到n-1,能否找到一条路径经过所有开着的门,并且使得通过门之后就把门关上,关上的再也不打开,最后能回到编号为0的房间。 思路 : 这就是一个赤裸裸的判断欧拉通路的问…

bootstrap guide

bootstrap1. bootstrap 简单介绍2. demo演示3. 关于bootstrap使用注意的点1. bootstrap 简单介绍 起源 来自Twitter,是目前最受欢迎的前端框架。基于HTML、CSS、Javascript。Bootstrap js组件依赖于jquery 3.X简洁灵活,使得Web开发更加快捷。官网 https…

六、Analysis of quicksort

1 引言 如题目所示,本节的精华在于用数学解决一个直觉上看似纷乱复杂的问题,里面有一些一般性的分析方法,如引入Indicator变量,从而把不确定问题引入到概率框架进行分析,一步一步把直觉上混乱的问题理清楚&#xff0c…

Javaweb maven项目tomcat报错: javax.naming.NamingException: 无法创建资源实例

报错地址 2. 原因分析 1. Resource注解无效,注入失败,你得从容器中把bookInfoServie取去来,用getBean的方式创建BookInfoServiceImpl对象 2.删掉Resource注解,重新部署搞定。3.不要在意写了个Contorller, 初学spring,…

如何给APK文件签名

转载地址:http://www.apkbus.com/forum.php?modviewthread&tid1264211.签名的意义   为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序,我们需要对我们发布的APK文件进行唯一…

七、基于比较的排序算法总结

1 问题 至此,总结一下已经研究过的排序算法: insertion sort,Θ(n2)\Theta(n^2)Θ(n2) merge sort, Θ(nlogn)\Theta(nlogn)Θ(nlogn) quicksort, Θ(nlogn)\Theta(nlogn)Θ(nlogn) heapsort,Θ(nlogn)\Theta(nlogn)Θ(nlogn) 从上面这个现象…

转账为demo,spring事务

spring 事务使用1. 业务代码2. xml配置3. 注解配置1. 业务代码 数据表结构 dao package com.lovely.dao.impl;import com.lovely.dao.AccountDao; import org.springframework.jdbc.core.JdbcTemplate;/*** author echo lovely* date 2020/8/9 11:01*/ public class AccountD…

八、计数排序及其应用分析

1 本节思路 之前的算法的最基本的思想是比较元素大小,所以算法复杂度最好是Θ(nlogn)\Theta(nlogn)Θ(nlogn),本节不再基于元素比较,而是基于计数的Counting sort,然后应用在Radix sort上。 2 Counting sort 2.1 算法思想 Cou…