当前位置: 首页 > 科技观察

Java基于朴素贝叶斯实现情感词分析

时间:2023-03-14 14:36:31 科技观察

朴素贝叶斯(NaiveBayesian)是一种基于贝叶斯定理和特征条件独立假设的分类方法。它是一种基于概率论方法的监督学习,广泛应用于自然语言处理,在机器学习领域占有非常重要的地位。在之前的一个项目中,使用了朴素贝叶斯分类器,将其应用于情感词的分析处理,取得了不错的效果。在本文中,我们将介绍朴素贝叶斯分类的理论基础及其实际应用。在学习朴素贝叶斯分类并正式开始情感词分析之前,我们首先需要了解贝叶斯定理的数学基础。贝叶斯定理贝叶斯定理是关于随机事件A和B的条件概率的定理,公式如下:上式中,每一项含义如下:P(A):先验概率(先验概率),是事件A在没有任何条件约束的情况下发生的概率,也称为基本概率,是对A事件发生概率P(A|B)的主观判断:在B发生的条件下A发生的可能性,也称为是A的后验概率(posteriorprobability)P(B|A):Likelihood,也称为条件似然(conditionallikelihood)P(B):不管A是否发生,B发生的概率在所有情况下,这称为总体似然或归一化常数(normalizingconstant)。根据上面的解释,贝叶斯定理可以表示为:后验概率=先验概率*似然/归一化常数通俗地说,可以理解为当我们无法确定一个事件发生的概率时,我们可以依靠概率事件发生的概率与事件的本质属性相关联,以推断事件发生的概率。用数学语言表达,支持某种属性的事件发生的次数越多,该事件发生的可能性就越大。这种推理过程也称为贝叶斯推理。在查阅的一些文献中,P(B|A)/P(B)可以称为可能性函数,作为调整因子,表示新信息B对事件A带来的调整,其作用是结合先验概率(主观判断)调整为更接近真实概率的概率。那么,贝叶斯定理也可以理解为:新信息出现后A的概率=A的先验概率*新信息带来的调整我举个例子,帮助大家更直观的理解这个过程。假设计算了一段时间的天气和温度对运动条件的影响,如下:天气,温度,运动,晴天,很高,游泳,晴天,高,足球,阴天,钓鱼,阴天,游泳,晴天,低天,游泳,阴天,低天,钓鱼现在请计算晴天,气温适中时去游泳的概率是多少?根据贝叶斯定理,计算过程如下:P(游泳|晴天,中温)=P(晴天,中温|游泳)*P(游泳)/P(晴天,中温)=P(晴天|游泳)*P(中温|游泳)*P(游泳)/[P(晴天)*P(中温)]=2/3*1/3*1/2/(1/2*1/3)=2/3最后游泳的概率是2/3。以上就是基于贝叶斯定理根据给定的特征计算事件发生概率的过程。贝叶斯分析的思想在从证据的积累中推断事件发生的概率方面发挥着重要作用。当我们要预测一个事件时,我们首先根据已有的经验和知识推断出一个先验概率,然后继续使用新的证据。在累积的情况下调整此概率。通过积累证据来获得事件发生概率的整个过程称为贝叶斯分析。这样,贝叶斯的底层思想可以概括为,如果你能掌握一个事件的所有信息,就可以计算出它的客观概率。另外,根据贝叶斯公式,可以得到如下公式:其中B1,B2,...,Bj是一个完整的事件群,上式可以表示在事件A已经发生的情况下,求原因A各种“原因”发生的Bi概率。朴素贝叶斯在学习朴素贝叶斯之前,首先需要了解贝叶斯分类。贝叶斯分类预测一个对象属于某个类别的概率,并通过比较不同类别的概率来预测其最可能的归属。的范畴是根据贝叶斯定理形成的。贝叶斯分类器在处理大规模数据集时表现出很高的分类精度。贝叶斯分类在处理未知类型的样本X时,可以先计算X属于每个类别Ci的概率P(Ci|X),然后选择概率最大的类别。假设有两个特征变量x和y,有两个分类类别C1和C2,结合贝叶斯定理:如果P(C1|x,y)>P(C2|x,y),则表示在x和y在出现的条件下,C1比C2更容易出现,那么它应该属于类别C1反之,如果P(C1|x,y)parameters=newHashMap<>();try(BufferedReaderbr=newBufferedReader(newFileReader(trainingData))){//训练集数据Stringsentence;while(null!=(sentence=br.readLine())){String[]content=sentence.split("\t|");//带制表符或空格的分词parameters.put(content[0],parameters.getOrDefault(content[0],0)+1);for(inti=1;iparameters){try(BufferedWriterbw=newBufferedWriter(newFileWriter(modelFilePath))){parameters.keySet().stream().forEach(key->{try{bw.append(key+"\t"+parameters.get(key)+"\r\n");}catch(IOExceptione){e.printStackTrace();}});bw.flush();}catch(IOExceptione){e.printStackTrace();}}查看保存的模型,数据格式如下:无好评3差评-真讨厌1好评-赠品3差评-脏乱差6好评-解决15个差评-被宰1...训练好的模型保存在这里,以后如果有相同的分类任务,可以直接在训练集的基础上计算。对于分类速度要求高的任务,可以有效提高计算速度3.加载模型加载训练好的模型:privatestaticHashMapparameters=null;//用于存储模型privatestaticMapcatagory=null;privatestaticString[]labels={"goodreview","bad审查“,”总计“,”先验好“,”先验坏“};privatestaticvoidloadModel()throwsIOException{parameters=newHashMap<>();ListparameterData=Files.readAllLines(Paths.get(modelFilePath));parameterData。stream().forEach(参数->{String[]split=parameter.split("\t");Stringkey=split[0];intvalue=Integer.parseInt(split[1]);parameters.put(key,价值);});calculateCatagory();//Category}对词进行分类,统计正负词频的总数,并据此计算先验概率://计算模型中的类别总数publicstaticvoidcalculateCatagory(){catagory=newHashMap<>();doublegood=0.0;//有利词总频数doublebad=0.0;//负面词总频数doubletotal;//总词频for(Stringkey:parameters.keySet()){Integervalue=parameters.get(key);if(key.contains("好评-")){good+=value;}elseif(key.contains("差评-")){bad+=value;}}total=good+坏;catagory.put(标签[0],好);catagory.put(标签[1],坏);catagory.put(标签[2],总计);catagory.put(标签[3],好/总计);//好评先验概率catagory.put(labels[4],bad/total);//差评先验概率}执行后查看统计值:“好评”对应的词出现的总次数为46316个“差评”对应的词的总出现次数为77292,训练集中的词频总数为123608,根据它们可以计算出它们的先验概率:条件概率文档属于某个类别=该类别所有词条的总词频/所有词条的总词频4.测试阶段在测试阶段,加载我们事先准备好的测试集,预测该类别的主观情绪每行分词后的注释语句:privatestaticvoidpredictAll(){doubleaccuracyCount=0.;//精确数intamount=0;//测试集数据总量{Stringconclusion=instance.substring(0,instance.indexOf("\t"));//已标注Stringsentence=instance.substring(instance.indexOf("\t")+1);Stringprediction=predict(sentence);//预测结果bw.append(conclusion+":"+prediction+"\r\n");if(conclusion.equals(prediction)){accuracyCount+=1.;}amount+=1;}//计算准确率System.out.println("accuracyCount:"+accuracyCount/amount);}catch(Exceptione){e.printStackTrace();}}在测试过程中调用如下predict方法进行分类判断。在计算之前,我们先回顾一下上面的公式,在程序中进行了简化:对于同一个预测样本,分母是一样的,所以我们只能比较分子的大小。为了进一步简化分子部分,我们可以对相乘的预算进行对数运算,成为各部分的相加:这样,概率的比较可以简化为比较先验概率和每个似然概率的对数后的和添加。先验概率在上一步已经计算并保存了,所以这里我们只计算每个词汇在分类条件下的似然概率。predict方法的实现如下:privatestaticStringpredict(Stringsentence){String[]features=sentence.split("");Stringprediction;//分别预测正面和负面评论doublegood=likelihoodSum(labels[0],features)+Math.log(catagory.get(labels[3]));doublebad=likelihoodSum(labels[1],features)+Math.log(catagory.get(labels[4]));returngood>=bad?labels[0]:labels[1];}调用似然法计算似然概率的对数和://计算似然概率publicstaticdoublelikelihoodSum(Stringlabel,String[]features){doublep=0.0;Doubletotal=catagory.get(label)+1;//分母平滑处理for(Stringword:features){Integercount=parameters.getOrDefault(label+"-"+word,0)+1;//分子平滑处理//计算词在该类别中的概率,将词除词频乘以类别总词频p+=Math.log(count/total);}returnp;}在计算似然概率的方法中,如果有一个词没有被包含在训练集中,那么就会出现似然概率为0的情况,为了防止出现这种情况,进行了分子分母加1的平滑操作。最后在main函数中调用以上步骤。最后,如果根据样本计算出的好评概率大于等于差评概率,则归类为“好评”,否则归类为“差评”,训练完成了。以及测试的全过程:publicstaticvoidmain(String[]args)throwsIOException{train();loadModel();predictAll();}执行所有代码,结果如下,可以看到准确率为93.35%已获得。将最终输出文档中的标签与预测结果进行对比,可以看出预测结果的准确率还是很高的。5.总结在上面的例子中,还有一些可以改进的地方。例如可以在前期建立一个情感词库,在特征值抽取过程中只抽取情感词,去掉其他无用词(如介词等),归类为受影响,只选择关键的代表词作为特征提取,以达到更高的分类效率。另外,在建词库时,也可以将测试集的情感词放入词库中,避免在某种分类条件下出现似然概率为零的情况,简化平滑步骤。另外,朴素贝叶斯的分类非常适合额外训练集的情况。如果训练集继续增加,可以在已有训练模型的基础上增加新的样本值,或者修改已有样本值的属性,在此基础上,可以实现增量模型修改。