Java实现基于朴素贝叶斯的情感词分析 (3)

加载训练好的模型:

private static HashMap<String, Integer> parameters = null; //用于存放模型 private static Map<String, Double> catagory=null; private static String[] labels = {"好评", "差评", "总数","priorGood","priorBad"}; private static void loadModel() throws IOException { parameters = new HashMap<>(); List<String> parameterData = Files.readAllLines(Paths.get(modelFilePath)); parameterData.stream().forEach(parameter -> { String[] split = parameter.split("\t"); String key = split[0]; int value = Integer.parseInt(split[1]); parameters.put(key, value); }); calculateCatagory(); //分类 }

对词进行分类,统计出好评及差评的词频总数,并基于它们先计算得出先验概率:

//计算模型中类别的总数 public static void calculateCatagory() { catagory = new HashMap<>(); double good = 0.0; //好评词频总数 double bad = 0.0; //差评的词频总数 double total; //总词频 for (String key : parameters.keySet()) { Integer value = parameters.get(key); if (key.contains("好评-")) { good += value; } else if (key.contains("差评-")) { bad += value; } } total = good + bad; catagory.put(labels[0], good); catagory.put(labels[1], bad); catagory.put(labels[2], total); catagory.put(labels[3],good/total); //好评先验概率 catagory.put(labels[4],bad/total); //差评先验概率 }

查看执行完后的统计值:

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

“好评”对应的词汇出现的总次数是46316个,“差评”对应的词汇出现的总次数是77292个,训练集词频总数为123608个,并可基于它们计算出它们的先验概率:

该文档属于某个类别的条件概率= 该类别的所有词条词频总数 / 所有词条的词频总数 4、测试阶段

测试阶段,加载我们提前准备好的测试集,对每一行分词后的评论语句进行主观情感的预测:

private static void predictAll() { double accuracyCount = 0.;//准确个数 int amount = 0; //测试集数据总量 try (BufferedWriter bw = new BufferedWriter(new FileWriter(outputFilePath))) { List<String> testData = Files.readAllLines(Paths.get(testFilePath)); //测试集数据 for (String instance : testData) { String conclusion = instance.substring(0, instance.indexOf("\t")); //已经打好的标签 String sentence = instance.substring(instance.indexOf("\t") + 1); String prediction = predict(sentence); //预测结果 bw.append(conclusion + " : " + prediction + "\r\n"); if (conclusion.equals(prediction)) { accuracyCount += 1.; } amount += 1; } //计算准确率 System.out.println("accuracyCount: " + accuracyCount / amount); } catch (Exception e) { e.printStackTrace(); } }

在测试中,调用下面的predict方法进行分类判断。在计算前,再来回顾一下上面的公式,在程序中进行简化运算:

对于同一个预测样本,分母相同,所以我们可以只比较分子的大小。对分子部分进行进一步简化,对于连乘预算,我们可以对其进行对数操作,变成各部分相加:

这样对于概率的大小比较,就可以简化为比较 先验概率和各个似然概率分别取对数后相加的和。先验概率我们在之前的步骤中已经计算完成并保存,所以这里只计算各词汇在分类条件下的似然概率即可。predict方法的实现如下:

private static String predict(String sentence) { String[] features = sentence.split(" "); String prediction; //分别预测好评和差评 double good = likelihoodSum(labels[0], features) + Math.log(catagory.get(labels[3])); double bad = likelihoodSum(labels[1], features) + Math.log(catagory.get(labels[4])); return good >= bad?labels[0]:labels[1]; }

在其中调用likelihood方法计算似然概率的对数和:

//似然概率的计算 public static double likelihoodSum(String label, String[] features) { double p = 0.0; Double total = catagory.get(label) + 1;//分母平滑处理 for (String word : features) { Integer count = parameters.getOrDefault(label + "-" + word, 0) + 1;//分子平滑处理 //计算在该类别的情况下是该词的概率,用该词的词频除以类别的总词频 p += Math.log(count / total); } return p; }

在计算似然概率的方法中,如果出现在训练集中没有包括的词汇,那么会出现它的似然概率为0的情况,为了防止这种情况,对分子分母进行了分别加一的平滑操作。

最后在主函数中调用上面的步骤,最终如果计算出基于样本的好评概率大于等于差评概率,那么将它分类划入“好评”,反之划入“差评”类别,到此就完成了训练和测试的全过程:

public static void main(String[] args) throws IOException { train(); loadModel(); predictAll(); }

执行全部代码,结果如下,可以看到获取了93.35%的准确率。

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

对比最后输出的文档中的标签与预测结果,可以看到,预测结果的准确度还是非常高的。

5、总结

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

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