【机器学习】基于朴素贝叶斯的新闻分类
实验介绍
1.实验内容
本实验介绍如何使用贝叶斯算法解决一个实际问题:新闻分类。
2.实验目标
通过本实验进一步掌握贝叶斯算法的原理,掌握如何使用贝叶斯算法解决实际问题,掌握实际世界中贝叶斯算法的解决流程。
3. 实验知识点
- 贝叶斯算法
- 数据预处理
- 梯度下降
- sklearn
4. 实验环境
- python 3.6.5
- jieba
5.预备知识
- 概率论与数理统计
- Linux命令基本操作
- Python编程基础
准备工作
点击屏幕右上方的下载实验数据模块,选择下载bayes_news.tgz到指定目录下,然后再依次选择点击上方的File->Open->Upload,上传刚才下载的数据集压缩包,再使用如下命令解压:
!tar -zxvf bayes_news.tgz
bayes_news/ bayes_news/Sample/ bayes_news/Sample/C000008/ bayes_news/Sample/C000008/10.txt bayes_news/Sample/C000008/11.txt bayes_news/Sample/C000008/12.txt bayes_news/Sample/C000008/13.txt bayes_news/Sample/C000008/14.txt bayes_news/Sample/C000008/15.txt bayes_news/Sample/C000008/16.txt bayes_news/Sample/C000008/17.txt bayes_news/Sample/C000008/18.txt bayes_news/Sample/C000008/19.txt~~~
框架
本实验使用Python3编程实现一个简单的新闻分类算法。
1.朴素贝叶斯理论
朴素贝叶斯是贝叶斯决策理论的一部分,所以在讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。
2.新闻分类
接下来我们开始用朴素贝叶斯算法进行新闻分类实战。
中文语句切分
考虑一个问题,英文的语句可以通过非字母和非数字进行切分,但是汉语句子呢?就比如我打的这一堆字,该如何进行切分呢?我们自己写个规则?幸运地是,这部分的工作不需要我们自己做了,可以直接使用第三方分词组件,即jieba,没错就是”结巴”。新闻分类数据集可在实验目录下找到,数据集已经做好分类,分文件夹保存,分类结果如下:
数据集已经准备好,接下来,让我们直接进入正题。切分中文语句,编写如下代码:
# -*- coding: UTF-8 -*-
import os
import jiebadef TextProcessing(folder_path):folder_list = os.listdir(folder_path) #查看folder_path下的文件data_list = [] #训练集class_list = []#遍历每个子文件夹for folder in folder_list:new_folder_path = os.path.join(folder_path, folder) #根据子文件夹,生成新的路径files = os.listdir(new_folder_path) #存放子文件夹下的txt文件的列表j = 1#遍历每个txt文件for file in files:if j > 100: #每类txt样本数最多100个breakwith open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f: #打开txt文件raw = f.read()word_cut = jieba.cut(raw, cut_all = False) #精简模式,返回一个可迭代的generatorword_list = list(word_cut) #generator转换为listdata_list.append(word_list)class_list.append(folder)j += 1print(data_list)print(class_list)
if __name__ == '__main__':#文本预处理folder_path = 'bayes_news/Sample' #训练集存放地址TextProcessing(folder_path)
结果:
可以看到,我们已经顺利将每个文本进行切分,并进行了类别标记。
词频统计
我们将所有文本分成训练集和测试集,并对训练集中的所有单词进行词频统计,并按降序排序。也就是将出现次数多的词语在前,出现次数少的词语在后进行排序。编写代码如下:
# -*- coding: UTF-8 -*-
import os
import random
import jieba"""
函数说明:中文文本处理Parameters:folder_path - 文本存放的路径test_size - 测试集占比,默认占所有数据集的百分之20
Returns:all_words_list - 按词频降序排序的训练集列表train_data_list - 训练集列表test_data_list - 测试集列表train_class_list - 训练集标签列表test_class_list - 测试集标签列表
"""
def TextProcessing(folder_path, test_size = 0.2):folder_list = os.listdir(folder_path) #查看folder_path下的文件data_list = [] #数据集数据class_list = [] #数据集类别#遍历每个子文件夹for folder in folder_list:new_folder_path = os.path.join(folder_path, folder) #根据子文件夹,生成新的路径files = os.listdir(new_folder_path) #存放子文件夹下的txt文件的列表j = 1#遍历每个txt文件for file in files:if j > 100: #每类txt样本数最多100个breakwith open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f: #打开txt文件raw = f.read()word_cut = jieba.cut(raw, cut_all = False) #精简模式,返回一个可迭代的generatorword_list = list(word_cut) #generator转换为listdata_list.append(word_list) #添加数据集数据class_list.append(folder) #添加数据集类别j += 1data_class_list = list(zip(data_list, class_list)) #zip压缩合并,将数据与标签对应压缩random.shuffle(data_class_list) #将data_class_list乱序index = int(len(data_class_list) * test_size) + 1 #训练集和测试集切分的索引值train_list = data_class_list[index:] #训练集test_list = data_class_list[:index] #测试集train_data_list, train_class_list = zip(*train_list) #训练集解压缩test_data_list, test_class_list = zip(*test_list) #测试集解压缩all_words_dict = {} #统计训练集词频for word_list in train_data_list:for word in word_list:if word in all_words_dict.keys():all_words_dict[word] += 1else:all_words_dict[word] = 1#根据键的值倒序排序all_words_tuple_list = sorted(all_words_dict.items(), key = lambda f:f[1], reverse = True)all_words_list, all_words_nums = zip(*all_words_tuple_list) #解压缩all_words_list = list(all_words_list) #转换成列表return all_words_list, train_data_list, test_data_list, train_class_list, test_class_listif __name__ == '__main__':#文本预处理folder_path = 'bayes_news/Sample' #训练集存放地址all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)print(all_words_list)
all_words_list就是将所有训练集的切分结果通过词频降序排列构成的单词合集。观察一下打印结果,不难发现,这里包含了很多标点符号,很显然,这些标点符号是不能作为新闻分类的特征的。为了降低这些高频的符号对分类结果的影响,需要将这些标点符号删除。除了这些,还有”在”,”了”这样对新闻分类没有帮助的词。此外,还有一些数字,数字显然也不能作为分类新闻的特征。所以要消除它们对分类结果的影响,可以定制一个规则。
一个简单的规则可以这样制定:
- 首先去掉高频词,至于去掉多少个高频词,我们可以通过观察去掉高频词个数和最终检测准确率的关系来确定。
- 然后,去除数字,不把数字作为分类特征。
- 最后,去除一些特定的词语,比如:”的”,”一”,”在”,”不”,”当然”,”怎么”这类的对新闻分类无影响的介词、代词、连词。
数据清洗
可以使用已经整理好的stopwords_cn.txt文本来去除这些词,stopwords_cn.txt位于当前实验的数据集目录下。
可以使用head命令查看该文件内容的前40行:
!head -n 40 bayes_news/stopwords_cn.txt
所以可以根据这个文档,将这些单词去除,不作为分类的特征。先去除前100个高频词汇,然后编写代码如下:
"""
函数说明:读取文件里的内容,并去重Parameters:words_file - 文件路径
Returns:words_set - 读取的内容的set集合
"""
def MakeWordsSet(words_file):words_set = set() #创建set集合with open(words_file, 'r', encoding = 'utf-8') as f: #打开文件for line in f.readlines(): #一行一行读取word = line.strip() #去回车if len(word) > 0: #有文本,则添加到words_set中words_set.add(word) return words_set #返回处理结果"""
函数说明:文本特征选取Parameters:all_words_list - 训练集所有文本列表deleteN - 删除词频最高的deleteN个词stopwords_set - 指定的结束语
Returns:feature_words - 特征集
"""
def words_dict(all_words_list, deleteN, stopwords_set = set()):feature_words = [] #特征列表n = 1for t in range(deleteN, len(all_words_list), 1):if n > 1000: #feature_words的维度为1000break #如果这个词不是数字,并且不是指定的结束语,并且单词长度大于1小于5,那么这个词就可以作为特征词if not all_words_list[t].isdigit() and all_words_list[t] not in stopwords_set and 1 < len(all_words_list[t]) < 5:feature_words.append(all_words_list[t])n += 1 return feature_wordsif __name__ == '__main__':#文本预处理folder_path = 'bayes_news/Sample' #训练集存放地址all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)#生成stopwords_setstopwords_file = 'bayes_news/stopwords_cn.txt'stopwords_set = MakeWordsSet(stopwords_file)feature_words = words_dict(all_words_list, 100, stopwords_set)print(feature_words)
可以看到,我们已经滤除了那些没有用的词组,这个feature_words就是我们最终选出的用于新闻分类的特征。随后,我们就可以根据feature_words,将文本向量化,然后用于训练朴素贝叶斯分类器。
Sklearn接口说明
数据已经处理好了,接下来就可以使用sklearn构建朴素贝叶斯分类器了。
官方英文文档地址:sklearn.naive_bayes.MultinomialNB — scikit-learn 1.2.dev0 documentation
朴素贝叶斯是一类比较简单的算法,scikit-learn中朴素贝叶斯类库的使用也比较简单。相对于决策树,KNN之类的算法,朴素贝叶斯需要关注的参数是比较少的,这样也比较容易掌握。在scikit-learn中,一共有3个朴素贝叶斯的分类算法类。分别是GaussianNB,MultinomialNB和BernoulliNB。其中GaussianNB就是先验为高斯分布的朴素贝叶斯,MultinomialNB就是先验为多项式分布的朴素贝叶斯,而BernoulliNB就是先验为伯努利分布的朴素贝叶斯。上篇文章讲解的先验概率模型就是先验概率为多项式分布的朴素贝叶斯。
对于新闻分类,属于多分类问题。我们可以使用MultinamialNB()完成我们的新闻分类问题。另外两个函数的使用暂且不再进行扩展,可以自行学习。MultinomialNB假设特征的先验概率为多项式分布,即如下式:
参数说明如下:
- alpha:浮点型可选参数,默认为1.0,其实就是添加拉普拉斯平滑,即为上述公式中的λ ,如果这个参数设置为0,就是不添加平滑;
- fit_prior:布尔型可选参数,默认为True。布尔参数fit_prior表示是否要考虑先验概率,如果是false,则所有的样本类别输出都有相同的类别先验概率。否则可以自己用第三个参数class_prior输入先验概率,或者不输入第三个参数class_prior让MultinomialNB自己从训练集样本来计算先验概率,此时的先验概率为P(Y=Ck)=mk/m。其中m为训练集样本总数量,mk为输出为第k类别的训练集样本数。
- class_prior:可选参数,默认为None。
总结如下:
除此之外,MultinamialNB也有一些方法供我们使用:
MultinomialNB一个重要的功能是有partial_fit方法,这个方法的一般用在如果训练集数据量非常大,一次不能全部载入内存的时候。这时我们可以把训练集分成若干等分,重复调用partial_fit来一步步的学习训练集,非常方便。GaussianNB和BernoulliNB也有类似的功能。 在使用MultinomialNB的fit方法或者partial_fit方法拟合数据后,可以进行预测。
此时预测有三种方法,包括predict,predict_log_proba和predict_proba。predict方法就是我们最常用的预测方法,直接给出测试集的预测类别输出。predict_proba则不同,它会给出测试集样本在各个类别上预测的概率。容易理解,predict_proba预测出的各个类别概率里的最大值对应的类别,也就是predict方法得到类别。predict_log_proba和predict_proba类似,它会给出测试集样本在各个类别上预测的概率的一个对数转化。转化后predict_log_proba预测出的各个类别对数概率里的最大值对应的类别,也就是predict方法得到类别。具体细节可参照官网手册。
【练习】基于Sklearn实现分类
了解了这些,我们就可以编写代码,通过观察取不同的去掉前deleteN个高频词的个数与最终检测准确率的关系,确定deleteN的取值:
# -*- coding: UTF-8 -*-
from sklearn.naive_bayes import MultinomialNB
import matplotlib.pyplot as plt"""
函数说明:根据feature_words将文本向量化Parameters:train_data_list - 训练集test_data_list - 测试集feature_words - 特征集
Returns:train_feature_list - 训练集向量化列表test_feature_list - 测试集向量化列表
"""
def TextFeatures(train_data_list, test_data_list, feature_words):def text_features(text, feature_words): #出现在特征集中,则置1 text_words = set(text)features = [1 if word in text_words else 0 for word in feature_words]return featurestrain_feature_list = [text_features(text, feature_words) for text in train_data_list]test_feature_list = [text_features(text, feature_words) for text in test_data_list]return train_feature_list, test_feature_list #返回结果"""
函数说明:新闻分类器Parameters:train_feature_list - 训练集向量化的特征文本test_feature_list - 测试集向量化的特征文本train_class_list - 训练集分类标签test_class_list - 测试集分类标签
Returns:test_accuracy - 分类器精度
"""
def TextClassifier(train_feature_list, test_feature_list, train_class_list, test_class_list):### Start Code Here ####创建朴素贝叶斯对象classifier = MultinomialNB().fit(train_feature_list, train_class_list)#使用fit函数进行模型训练test_accuracy = classifier.score(test_feature_list, test_class_list)#调用score函数计算模型在测试集上的得分test_accuracy### End Code Here ###return test_accuracyif __name__ == '__main__':#文本预处理folder_path = 'bayes_news/Sample' #训练集存放地址all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)# 生成stopwords_setstopwords_file = 'bayes_news/stopwords_cn.txt'stopwords_set = MakeWordsSet(stopwords_file)test_accuracy_list = []deleteNs = range(0, 1000, 20) #0 20 40 60 ... 980for deleteN in deleteNs:feature_words = words_dict(all_words_list, deleteN, stopwords_set)train_feature_list, test_feature_list = TextFeatures(train_data_list, test_data_list, feature_words)test_accuracy = TextClassifier(train_feature_list, test_feature_list, train_class_list, test_class_list)test_accuracy_list.append(test_accuracy)plt.figure()plt.plot(deleteNs, test_accuracy_list)plt.title('Relationship of deleteNs and test_accuracy')plt.xlabel('deleteNs')plt.ylabel('test_accuracy')plt.show()
我们绘制出了deleteNs和test_accuracy的关系,这样我们就可以大致确定去掉前多少的高频词汇了。每次运行程序,绘制的图形可能不尽相同,我们可以通过多次测试,来决定这个deleteN的取值,然后确定这个参数,这样就可以顺利构建出用于新闻分类的朴素贝叶斯分类器了。
可以看到450还不错,最差的分类准确率也可以达到百分之50以上。
将if name == 'main'下的代码修改如下:
if __name__ == '__main__':#文本预处理folder_path = 'bayes_news/Sample' #训练集存放地址all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)# 生成stopwords_setstopwords_file = 'bayes_news/stopwords_cn.txt'stopwords_set = MakeWordsSet(stopwords_file)test_accuracy_list = []feature_words = words_dict(all_words_list, 450, stopwords_set)train_feature_list, test_feature_list = TextFeatures(train_data_list, test_data_list, feature_words)test_accuracy = TextClassifier(train_feature_list, test_feature_list, train_class_list, test_class_list)test_accuracy_list.append(test_accuracy)ave = lambda c: sum(c) / len(c)print(ave(test_accuracy_list))
0.7894736842105263
实验总结
通过本实验,您应该能达到以下两个目标:
- 掌握朴素贝叶斯算法原理。
- 熟悉朴素贝叶斯算法的初步应用。
参考文献及延伸阅读
参考资料:
- 1.哈林顿,李锐. 机器学习实战 : Machine learning in action[M]. 人民邮电出版社, 2013.
- 2.周志华. 机器学习:Machine learning[M]. 清华大学出版社, 2016.
延伸阅读:
- 1.李航. 统计学习方法[M]. 清华大学出版社, 2012.
【机器学习】基于朴素贝叶斯的新闻分类相关推荐
- 朴素贝叶斯网络matlab实现_基于朴素贝叶斯的文本分类方法实战
基于朴素贝叶斯的文本分类方法 一.朴素贝叶斯原理的介绍 二.朴素贝叶斯分类器的代码实现 分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同时会给出这个猜测的概率估计值.朴素贝叶 ...
- 基于朴素贝叶斯实现文本分类
基于朴素贝叶斯实现文本分类 数据集介绍 数据集为网上公开的新闻数据,其中数据集包含10个类别. 模型选择 贝叶斯分类 贝叶斯公式 朴素贝叶斯 拉普拉斯平滑引入 某个属性的条件概率为0,则会导致整体概率 ...
- 基于朴素贝叶斯的文本分类算法
基于朴素贝叶斯的文本分类算法 摘要:常用的文本分类方法有支持向量机.K-近邻算法和朴素贝叶斯.其中朴素贝叶斯具有容易实现,运行速度快的特点,被广泛使用.本文详细介绍了朴素贝叶斯的基本原理,讨论多项式模 ...
- 朴素贝叶斯基于朴素贝叶斯的文本分类算法
朴素贝叶斯 以及 基于朴素贝叶斯的文本分类算法 参考文章: https://www.cnblogs.com/jorbin/articles/1915888.html
- 朴素贝叶斯文本分类java_基于朴素贝叶斯的文本分类算法
基于朴素贝叶斯的文本分类算法 摘要:常用的文本分类方法有支持向量机.K-近邻算法和朴素贝叶斯.其中朴素贝叶斯具有容易实现,运行速度快的特点,被广泛使用.本文详细介绍了朴素贝叶斯的基本原理,讨论多项式模 ...
- HanLP 基于朴素贝叶斯 训练 文本分类
一.HanLP 朴素贝叶斯分类器 HanLP 针对文本分类算法已经帮我们实现 朴素贝叶斯法 ,用户可以无需关心内部细节,HanLP 也提供了相关自定义训练接口,前提需要将数据集根据分类放到不同的目录中 ...
- 【机器学习】朴素贝叶斯(多分类版本)—— python3 实现方案
根据<统计学习方法>第四章朴素贝叶斯算法流程写成,引入贝叶斯估计(平滑处理). 本例旨在疏通算法流程,理解算法思想,故简化复杂度,只考虑离散型数据集.如果要处理连续型数据,可以考虑将利用& ...
- 基于朴素贝叶斯的垃圾邮件分类-着重理解拉普拉斯变换
1. 引言 在正式学习朴素贝叶斯之前,需要明确的是机器学习所要实现的是基于有限的训练样本集尽可能准确地估计出后验概率P(c|x),即根据特征得到所属类别的概率,首先引入两个概念. 判别式模型(disc ...
- 机器学习之朴素贝叶斯(Naive Bayes)
1 朴素贝叶斯算法介绍 朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法.朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实 ...
- 详解基于朴素贝叶斯的情感分析及 Python 实现
相对于「 基于词典的分析 」,「 基于机器学习 」的就不需要大量标注的词典,但是需要大量标记的数据,比如: 还是下面这句话,如果它的标签是: 服务质量 - 中 (共有三个级别,好.中.差) ╮(╯-╰ ...
最新文章
- python3根据地址批量获取百度地图经纬度
- Python中json模块,字典和字符串相互转换
- 伦敦大学 机器人科学(研究型硕士) 项目介绍!干货满满!
- servlet与MySQL商品管理系统_servlet和mysql实现宿舍管理系统
- http://me.rice.edu/~akin/
- uniapp 如何配置MySQL_uniapp后台api设计(微信user表)
- 计算机应用基础教学计划第二学期,计算机应用基础教学计划(中职) (1)
- Kindle刷安卓双系统的方法
- matlab 拟合保存函数,matlab如何拟合函数
- IDEA安装阿里巴巴Java开发手册
- Windows server 2016中文语言包安装教程
- ios 系统状态栏样式修改_IOS修改状态栏的字体颜色以及修改状态栏的背景颜色...
- 酒类企业1919获阿里20亿入股 已与天猫及饿了么有深度合作
- 书评 | 赋能 - 打造应对不确定性的敏捷团队
- vue项目手机端适配
- 全球及中国电化学研磨设备行业盈利模式与竞争态势分析报告2022-2028年
- POE 供电设备原理详解
- mysql将查询结果作为临时表查询_mysql使用查询结果作为临时表
- 复杂美公司Chain33区块链开发
- burpsuite第一次爬行扫描