深度 | 朴素贝叶斯模型算法研究与实例分析 (2)

我们在前面两篇文章介绍了朴素贝叶斯模型训练方法,我们在该方法下稍微改动就得到如下实现:

'''朴素贝叶斯模型训练数据优化''' def trainNB0(trainMatrix, trainCategory): numTrainDocs = len(trainMatrix) # 总文件数 numWords = len(trainMatrix[0]) # 总单词数 p1Num=p2Num=p3Num=p4Num=p5Num = ones(numWords) # 各类为1的矩阵 p1Denom=p2Denom=p3Denom=p4Denom=p5Denom = 2.0 # 各类特征和 num1=num2=num3=num4=num5 = 0 # 各类文档数目 pNumlist=[p1Num,p2Num,p3Num,p4Num,p5Num] pDenomlist =[p1Denom,p2Denom,p3Denom,p4Denom,p5Denom] Numlist = [num1,num2,num3,num4,num5] for i in range(numTrainDocs): # 遍历每篇训练文档 for j in range(5): # 遍历每个类别 if trainCategory[i] == j: # 如果在类别下的文档 pNumlist[j] += trainMatrix[i] # 增加词条计数值 pDenomlist[j] += sum(trainMatrix[i]) # 增加该类下所有词条计数值 Numlist[j] +=1 # 该类文档数目加1 pVect,pi = [],[] for index in range(5): pVect.append(log(pNumlist[index] / pDenomlist[index])) pi.append(Numlist[index] / float(numTrainDocs)) return pVect, pi

构建分类函数,其优化后的代码实现如下:

'''朴素贝叶斯分类函数,将乘法转换为加法''' def classifyNB(vec2Classify, pVect,pi): # 计算公式 log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) bnpi = [] # 文档分类到各类的概率值列表 for x in range(5): bnpi.append(sum(vec2Classify * pVect[x]) + log(pi[x])) # print([bnp for bnp in bnpi]) # 分类集合 reslist = ['Art','Literature','Education','Philosophy','History'] # 根据最大概率,选择索引值 index = [bnpi.index(res) for res in bnpi if res==max(bnpi)] return reslist[index[0]] # 返回分类值 测试算法

我们加载构建的数据集方法,然后创建单词集合,集合词袋模型进行特征向量化,构建训练模型和分类方法,最终我们从复旦新闻语料中选择一篇未加入训练集的教育类文档,进行开放测试,具体代码如下:

'''朴素贝叶斯新闻分类应用''' def testingNB(): # 1. 加载数据集 dataSet,Classlabels = loadDataSet() # 2. 创建单词集合 myVocabList = createVocabList(dataSet) # 3. 计算单词是否出现并创建数据矩阵 trainMat = [] for postinDoc in dataSet: trainMat.append(bagOfWords2VecMN(myVocabList, postinDoc)) with open('./word-bag.txt','w') as f: for i in trainMat: f.write(str(i)+'\r\n') # 4. 训练数据 pVect,pi= trainNB0(array(trainMat), array(Classlabels)) # 5. 测试数据 testEntry = textParse(open('./fudan/test/C5-1.txt',encoding='UTF-8').read()) thisDoc = array(bagOfWords2VecMN(myVocabList, testEntry)) print(testEntry[:10], '分类结果是: ', classifyNB(thisDoc, pVect,pi))

实现结果如下:

Building prefix dict from the default dictionary ... Loading model from cache C:\Users\ADMINI~1\AppData\Local\Temp\jieba.cache Loading model cost 0.892 seconds. Prefix dict has been built succesfully. ['全国/n ', '举办/v ', '电影/n ', '新华社/nt ', '北京/ns ', '国家教委/nt ', '广播电影电视部/nt ', '文化部/n ', '联合/v ', '决定/v '] 分类结果是: Literature 耗时:29.4882 s

结果分析:我们运行分类器得出结果易知,预测结果是文化类,且运行时间为29s。首先分析为什么预测错误,这里面主要是训练集样本比较少和特征选择的原因。运行时间是由于将特征矩阵存储本地后,后面直接读取文本,相当于加载缓存,大大缩短运行时间。但是这里还有值得优化的地方,比如每次运行都会加载训练模型,大大消耗时间,我们能不能训练模型加载一次,多次调用呢?当然是可以的,这个问题下文继续优化。我们重点关注下特征选择问题

特征选择问题讨论

做文本分类的时候,遇到特征矩阵1.5w。在测试篇幅小的文章总是分类错误?这个时候如何做特征选择?是不是说去掉特征集中频率极高和极低的一部分,对结果有所提升?
答:你说的这个情况是很普遍的现象,篇幅小的文章,特征小,所以模型更容易判断出错!去掉高频和低频通常是可以使得训练的模型泛化能力变强

比如:艺术,文化,历史,教育。界限本来就不明显,比如测试数据“我爱艺术,艺术是我的全部”。结果会分类为文化。其实这个里面还有就是不同特征词的权重问题,采用tf-idf优化下应该会好一些?

答:我个人觉得做文本特征提取,还是需要自己去分析文本本身内容的文字特点,你可以把每一类的文本的实体提取出来,然后统计一下每个词在每一类上的数量,看看数量分布,也许可以发现一些数据特点

我就是按照这个思路做的,还有改进时候的停用词,其实可以分析特征文本,针对不同业务,使用自定义的停用词要比通用的好
还有提前各类见最具表征性的词汇加权,凸显本类的权重是吧?
答:比如,艺术类文章中,哪些词出现较多,哪些词出现少,再观察这些词的词性主要是哪些,这样可能会对你制定提取特征规则方式的时候提供一定的思路参考,我可以告诉你的是,有些词绝对会某一类文章出出现多,然后在其他类文章出现很少,这一类的词就是文章的特征词

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdysg.html