网上有很多对朴素贝叶斯算法的说明的文章,在对算法实现前,参考了一下几篇文章:

NLP系列(2)_用朴素贝叶斯进行文本分类(上)

NLP系列(3)_用朴素贝叶斯进行文本分类(下)

带你搞懂朴素贝叶斯分类算法

其中“带你搞懂朴素贝叶斯算法”在我看来比较容易理解,上面两篇比较详细,更深入。

算法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);
}

第三步计算特征词的条件概率

/**
* 多项式朴素贝叶斯类条件概率
* 类条件概率P(IK|c)=(类c下单词IK在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|)
* V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),
* |V|则表示训练样本包含多少种单词。 P(IK|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,
* 而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)
* @param category
* @param word
* @return
*/
public static BigDecimal categoryConditionalProbability(String category, String word){
BigDecimal wordCount = new BigDecimal(wordInCategoryCount(word, category) + 1);
BigDecimal categoryTrainFileWordCount = new BigDecimal(categoryWordCount(category) + getAllTrainCategoryWordCount());
return wordCount.divide(categoryTrainFileWordCount, 10, BigDecimal.ROUND_CEILING);
}

第四步计算给定文本的分类结果

/**
* 多项式朴素贝叶斯分类结果
* P(C_i|w_1,w_2...w_n) = P(w_1,w_2...w_n|C_i) * P(C_i) / P(w_1,w_2...w_n)
* = P(w_1|C_i) * P(w_2|C_i)...P(w_n|C_i) * P(C_i) / (P(w_1) * P(w_2) ...P(w_n))
* @param words
* @return
*/
public static Map<String, BigDecimal> classifyResult(Set<String> words){
Map<String, BigDecimal> resultMap = new HashMap<String, BigDecimal>();
//获取训练语料集所有的分类集合
Set<String> categorySet = allTrainFileSegsMap.keySet();
//循环计算每个类别的概率
for (String categorySetLabel : categorySet){
BigDecimal probability = new BigDecimal(1.0);
for (String word : words){
probability = probability.multiply(categoryConditionalProbability(categorySetLabel, word)).multiply(zoomFactor);
}
resultMap.put(categorySetLabel, probability.multiply(prioriProbability(categorySetLabel)));
}
return resultMap;
}

辅助函数

/**
* 对分类结果进行比较,得出概率最大的类
* @param classifyResult
* @return
*/
public static String getClassifyResultName(Map<String, BigDecimal> classifyResult){
String classifyName = "";
if (classifyResult.isEmpty()){
return classifyName;
}
BigDecimal result = new BigDecimal(0);
Set<String> classifyResultSet = classifyResult.keySet();
for (String classifyResultSetString : classifyResultSet){
if (classifyResult.get(classifyResultSetString).compareTo(result) >= 1){
result = classifyResult.get(classifyResultSetString);
classifyName = classifyResultSetString;
}
}
return classifyName;
} /**
* 统计给定类别下的单词总数(带词频计算)
* @param categoryLabel 指定类别参数
* @return
*/
public static Long categoryWordCount(String categoryLabel){
Long sum = 0L;
Map<String, Map<String, Integer>> categoryWordMap = allTrainFileSegsMap.get(categoryLabel);
if (categoryWordMap == null){
return sum;
}
Set<String> categoryWordMapKeySet = categoryWordMap.keySet();
for (String categoryLabelString : categoryWordMapKeySet){
Map<String, Integer> categoryWordMapDataMap = categoryWordMap.get(categoryLabelString);
List<Map.Entry<String, Integer>> dataWordMapList = new ArrayList<Map.Entry<String, Integer>>(categoryWordMapDataMap.entrySet());
for (int i=0; i<dataWordMapList.size(); i++){
sum += dataWordMapList.get(i).getValue();
}
}
return sum;
} /**
* 获取训练样本所有词的总数(词总数计算是带上词频的,也就是可以重复算数)
* @return
*/
public static Long getAllTrainCategoryWordsCount(){
Long sum = 0L;
//获取所有分类
Set<String> categoryLabels = allTrainFileSegsMap.keySet();
//循环相加每个类下的词总数
for (String categoryLabel : categoryLabels){
sum += categoryWordCount(categoryLabel);
}
return sum;
} /**
* 获取训练样本下各个类别不重复词的总词数,区别于getAllTrainCategoryWordsCount()方法,此处计算不计算词频
* 备注:此处并不是严格意义上的进行全量词表生成后的计算,也就是加入类别1有"中国=6"、类别2有"中国=2",总词数算中国两次,
* 也就是说,我们在计算的时候并没有生成全局词表(将所有词都作为出现一次)
* @return
*/
public static Long getAllTrainCategoryWordCount(){
Long sum = 0L;
//获取所有分类
Set<String> categoryLabels = allTrainFileSegsMap.keySet();
for (String cateGoryLabelsLabel : categoryLabels){
Map<String, Map<String, Integer>> categoryWordMap = allTrainFileSegsMap.get(cateGoryLabelsLabel);
List<Map.Entry<String, Map<String, Integer>>> categoryWordMapList = new ArrayList<Map.Entry<String, Map<String, Integer>>>(categoryWordMap.entrySet());
for (int i=0; i<categoryWordMapList.size(); i++){
sum += categoryWordMapList.get(i).getValue().size();
}
}
return sum;
} /**
* 计算测试数据的每个单词在每个类下出现的总数
* @param word
* @param categoryLabel
* @return
*/
public static Long wordInCategoryCount(String word, String categoryLabel){
Long sum = 0L;
Map<String, Map<String, Integer>> categoryWordMap = allTrainFileSegsMap.get(categoryLabel);
Set<String> categoryWordMapKeySet = categoryWordMap.keySet();
for (String categoryWordMapKeySetFile : categoryWordMapKeySet){
Map<String, Integer> categoryWordMapDataMap = categoryWordMap.get(categoryWordMapKeySetFile);
Integer value = categoryWordMapDataMap.get(word);
if (value!=null && value>0){
sum += value;
}
}
return sum;
} /**
* 获取所有分类类别
* @return
*/
public Set<String> getAllCategory(){
return allTrainFileSegsMap.keySet();
}

main函数测试

//main方法
public static void main(String[] args){
BayesNB.getFeatureClassForTrainText("/Users/zhouyh/work/yanfa/xunlianji/train/");
String s = "全国假日旅游部际协调会议的各成员单位和中央各有关部门围绕一个目标,积极配合,主动工作,抓得深入,抓得扎实。主要有以下几个特点:一是安全工作有部署有检查有跟踪。国务院安委会办公室节前深入部署全面检查,节中及时总结,下发关于黄金周后期安全工作的紧急通知;铁路、民航、交通等部门针对黄金周前后期旅客集中返程交通压力较大情况,及时调遣应急运力;质检总局进一步强化节日期间质量安全监管工作;旅游部门每日及时发布旅游信息通报,有效引导游客。二是各方面主动协调密切配合。各省区市加强了在安全事故问题上的协调与沟通,化解了一些跨省区矛盾和问题;铁道、民航部门准时准确报送信息;中宣部和中央文明办以黄金周旅游为载体," +
"部署精神文明建设和践行社会主义荣辱观的宣传活动;中国气象局及时将黄金周每日气象分析送交各有关部门;公安部专门部署警力,为协调游客流动大的城市及景区做了大量工作;旅游部门密切配合有关部门做好各类事故处理和投诉调解工作。三是政府各部门的社会服务意识大为增强。外交部及其驻外领事馆及时提供境外安全信息为旅游者服务;中央电视台、地方电视台和各大媒体及各地方媒体提供的旅游信息十分丰富;气象信息服务充分具体;中消协提出多项旅游警示。各部门的密切配合和主动服务配合,确保了本次黄金周的顺利平稳运行。";
Set<String> words = IKWordSegmentation.segString(s).keySet(); Map<String, BigDecimal> resultMap = BayesNB.classifyResult(words);
String category = BayesNB.getClassifyResultName(resultMap);
System.out.println(category);
}

经过上述步骤即可实现简单的多项式模型算法,有部分代码参考了网上的算法代码。

朴素贝叶斯算法java实现(多项式模型)的更多相关文章

  1. 利用朴素贝叶斯算法进行分类-Java代码实现

    http://www.crocro.cn/post/286.html 利用朴素贝叶斯算法进行分类-Java代码实现  鳄鱼  3个月前 (12-14)  分类:机器学习  阅读(44)  评论(0) ...

  2. 朴素贝叶斯算法原理及Spark MLlib实例(Scala/Java/Python)

    朴素贝叶斯 算法介绍: 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法. 朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,在没有其它可用信息下,我 ...

  3. 朴素贝叶斯算法的python实现

    朴素贝叶斯 算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 朴素贝叶斯比如我们想判断一个邮件是不是垃圾邮件,那么 ...

  4. 【十大算法实现之naive bayes】朴素贝叶斯算法之文本分类算法的理解与实现

    关于bayes的基础知识,请参考: 基于朴素贝叶斯分类器的文本聚类算法 (上) http://www.cnblogs.com/phinecos/archive/2008/10/21/1315948.h ...

  5. Python机器学习笔记:朴素贝叶斯算法

    朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法.对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同.比如决策树,KNN,逻辑回归,支持向 ...

  6. 朴素贝叶斯算法的python实现方法

    朴素贝叶斯算法的python实现方法 本文实例讲述了朴素贝叶斯算法的python实现方法.分享给大家供大家参考.具体实现方法如下: 朴素贝叶斯算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类 ...

  7. 朴素贝叶斯算法下的情感分析——C#编程实现

    这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...

  8. 【数据挖掘】朴素贝叶斯算法计算ROC曲线的面积

    题记:          近来关于数据挖掘学习过程中,学习到朴素贝叶斯运算ROC曲线.也是本节实验课题,roc曲线的计算原理以及如果统计TP.FP.TN.FN.TPR.FPR.ROC面积等等.往往运用 ...

  9. C#编程实现朴素贝叶斯算法下的情感分析

    C#编程实现 这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Lang ...

随机推荐

  1. 命令模式(c++实现)

    命令模式 目录 命令模式 模式定义 模式动机 UML类图 源码实现 优点 缺点 模式定义 命令模式(Facade),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请 ...

  2. 二进制图片blob数据转canvas

    javascript是有操作二进制文件的方法的,在这里就不详述了. 而AJAX的核心XMLHttpRequest也可以获取服务端给的二进制Blob. 可以参考: XMLHttpRequest Leve ...

  3. 【JUnit测试】总结

    什么是Junit? Junit是xUnit的一个子集,在c++,paython,java语言中测试框架的名字都不相同 xUnit是一套基于测试驱动开发的测试框架 其中的断言机制:将程序预期的结果与程序 ...

  4. Monster Audio 使用教程(四)Wifi 远程遥控

    Android端下载二维码:(链接指向的是apk包地址,所以微信可能打不开,请用自带浏览器扫描二维码)  IOS下载二维码: 安装好上面的app,确保你的移动端设备和你电脑连接的是同一个路由器(也就是 ...

  5. 【新生学习】第一周:深度学习及pytorch基础

    DEADLINE: 2020-07-25 22:00 写在最前面: 本课程的主要思路还是要求大家大量练习 pytorch 代码,在写代码的过程中掌握深度学习的各类算法,希望大家能够坚持练习,相信经度过 ...

  6. 一个edit的学习笔记

    https://blog.csdn.net/woshizoe/article/details/51555396

  7. 使用AB对Nginx压测和并发预估

    简介 ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问.它的测试目标是基于URL的. # 1.ab每次只能测试一个URL,适合做重复压力测试 # 2.参数很多,可以支持添加c ...

  8. 萌新学渗透系列之Hack The Box_Lame

    我将我的walkthrough过程用视频解说的形式记载 视频地址https://www.bilibili.com/video/BV1Mv411z75c 一是因为看我视频的后来者应该都是刚入门的新手,视 ...

  9. Day02_IP地址详解&进制转换&DOS基本命令与批处理

    学于千峰教育开源课程 感谢 千峰教育官网 b站在线视频 IP地址详解 一.简单局域网的构成 局域网:一般称为内网 简单局域网的构成:交换机.网线.PC(其他IT终端) 交换机:用来组建内网的局域网的设 ...

  10. gerrit安装指南

    Gerrit的基本介绍 Gerrit 是一个Git服务器,它基于 git 版本控制系统,使用网页界面来进行审阅工作.Gerrit 旨在提供一个轻量级框架,用于在代码入库之前对每个提交进行审阅,更改将上 ...