朴素贝叶斯算法java实现(多项式模型)
网上有很多对朴素贝叶斯算法的说明的文章,在对算法实现前,参考了一下几篇文章:
其中“带你搞懂朴素贝叶斯算法”在我看来比较容易理解,上面两篇比较详细,更深入。
算法java实现
第一步对训练集进行预处理,分词并计算词频,得到存储训练集的特征集合
/** * 所有训练集分词特征集合 * 第一个String代表分类标签,也就是存储该类别训练集的文件名 * 第二个String代表某条训练集的路径,这里存储的是该条语料的绝对路径 * Map<String, Integer>存储的是该条训练集的特征词和词频 * */ private static Map<String, Map<String, Map<String, Integer>>> allTrainFileSegsMap = new HashMap<String, Map<String, Map<String, Integer>>>(); /** * 放大因子 * 在计算中,因各个词的先验概率都比较小,我们乘以固定的值放大,便于计算 */ private static BigDecimal zoomFactor = new BigDecimal(10); /** * 对传入的训练集进行分词,获取训练集分词后的词和词频集合 * @param trainFilePath 训练集路径 */ public static void getFeatureClassForTrainText(String trainFilePath){ //通过将训练集路径字符串转变成抽象路径,创建一个File对象 File trainFileDirs = new File(trainFilePath); //获取该路径下的所有分类路径 File[] trainFileDirList = trainFileDirs.listFiles(); if (trainFileDirList == null){ System.out.println("训练数据集不存在"); } for (File trainFileDir : trainFileDirList){ //读取该分类下的所有训练文件 List<String> fileList = null; try { fileList = FileOptionUtil.readDirs(trainFileDir.getAbsolutePath()); if (fileList.size() != 0){ //遍历训练集目录数据,进行分词和类别标签处理 for(String filePath : fileList){ System.out.println("开始对此训练集进行分词处理:" + filePath); //分词处理,获取每条训练集文本的词和词频 //若知道文件编码的话,不要用下述的判断编码格式了,效率太低 // Map<String, Integer> contentSegs = IKWordSegmentation.segString(FileOptionUtil.readFile(filePath, FileOptionUtil.getCodeString(filePath))); Map<String, Integer> contentSegs = IKWordSegmentation.segString(FileOptionUtil.readFile(filePath, "gbk")); if (allTrainFileSegsMap.containsKey(trainFileDir.getName())){ Map<String, Map<String, Integer>> allSegsMap = allTrainFileSegsMap.get(trainFileDir.getName()); allSegsMap.put(filePath, contentSegs); allTrainFileSegsMap.put(trainFileDir.getName(), allSegsMap); } else { Map<String, Map<String, Integer>> allSegsMap = new HashMap<String, Map<String, Integer>>(); allSegsMap.put(filePath, contentSegs); allTrainFileSegsMap.put(trainFileDir.getName(), allSegsMap); } } } else { System.out.println("该分类下没有待训练语料"); } } catch (IOException e) { e.printStackTrace(); } } }
第二步计算类别的先验概率
/** * 计算类别C的先验概率 * 先验概率P(c)= 类c下单词总数/整个训练样本的单词总数 * @param category * @return 类C的先验概率 */ public static BigDecimal prioriProbability(String category){ BigDecimal categoryWordsCount = new BigDecimal(categoryWordCount(category)); BigDecimal allTrainFileWordCount = new BigDecimal(getAllTrainCategoryWordsCount()); return categoryWordsCount.divide(allTrainFileWordCount, 10, BigDecimal.ROUND_CEILING); }