朴素贝叶斯算法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);
}
第三步计算特征词的条件概率
/**
* 多项式朴素贝叶斯类条件概率
* 类条件概率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实现(多项式模型)的更多相关文章
- 利用朴素贝叶斯算法进行分类-Java代码实现
http://www.crocro.cn/post/286.html 利用朴素贝叶斯算法进行分类-Java代码实现 鳄鱼 3个月前 (12-14) 分类:机器学习 阅读(44) 评论(0) ...
- 朴素贝叶斯算法原理及Spark MLlib实例(Scala/Java/Python)
朴素贝叶斯 算法介绍: 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法. 朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,在没有其它可用信息下,我 ...
- 朴素贝叶斯算法的python实现
朴素贝叶斯 算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 朴素贝叶斯比如我们想判断一个邮件是不是垃圾邮件,那么 ...
- 【十大算法实现之naive bayes】朴素贝叶斯算法之文本分类算法的理解与实现
关于bayes的基础知识,请参考: 基于朴素贝叶斯分类器的文本聚类算法 (上) http://www.cnblogs.com/phinecos/archive/2008/10/21/1315948.h ...
- Python机器学习笔记:朴素贝叶斯算法
朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法.对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同.比如决策树,KNN,逻辑回归,支持向 ...
- 朴素贝叶斯算法的python实现方法
朴素贝叶斯算法的python实现方法 本文实例讲述了朴素贝叶斯算法的python实现方法.分享给大家供大家参考.具体实现方法如下: 朴素贝叶斯算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类 ...
- 朴素贝叶斯算法下的情感分析——C#编程实现
这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...
- 【数据挖掘】朴素贝叶斯算法计算ROC曲线的面积
题记: 近来关于数据挖掘学习过程中,学习到朴素贝叶斯运算ROC曲线.也是本节实验课题,roc曲线的计算原理以及如果统计TP.FP.TN.FN.TPR.FPR.ROC面积等等.往往运用 ...
- C#编程实现朴素贝叶斯算法下的情感分析
C#编程实现 这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Lang ...
随机推荐
- Mariadb之主从复制的读写分离
首先我们来回顾下代理的概念,所谓代理就是指的是一端面向客户端,另外一端面向服务端,代理客户端访问服务端,我们把这种代理叫正向代理:代理服务端响应客户端我们叫做反向代理,这个我们在之前nginx系列博客 ...
- 从连接器组件看Tomcat的线程模型——连接器简介
Connector组件介绍 Connector(连接器)组件是Tomcat最核心的两个组件之一,主要的职责是负责接收客户端连接和客户端请求的处理加工.每个Connector都将指定一个端口进行监听,分 ...
- 如何在项目中封装api
一般在项目中,会有很多的api请求,无论在vue,angular,还是react中都应该把接口封装起来,方便后期的维护. 1.新建一个api文件 我们可以在项目的分目录下创建一个api文件夹,在这里面 ...
- Python Ethical Hacking - Packet Sniffer(1)
PACKET_SNIFFER Capture data flowing through an interface. Filter this data. Display Interesting info ...
- linux : 新服务器部署项目要做的事
环境:阿里云服务器两台,一台web,一台db,系统centos7. 用户用外网访问web server ,web server 再去访问db server. 1 阿里云控制台进入系统2 SSH进入系统 ...
- 不是吧,阿sir,2020年程序员要不好过?
自从网传程序员到了35岁之后必须要转行,现在又有人传言:“疫情之下,程序员今年要过苦日子了,降薪裁员是大趋势.” 不是,我就不明白了,你们怎么就看不得程序员好呢?天天巴望着程序员降薪.转行.裁员… ...
- python 简单粗暴的生产的验证码
import os import pygame import random from pygame.locals import * count = 0; 生成验证码的函姝 def get_code() ...
- kotlin中使用Handler
kotlin中使用Handler jumpToPayHandler = Handler { var questionformModel = QuetionFormModel(2, spinner.te ...
- cookie 和session的简单比较
1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session ...
- IO—》打印流&commons-IO
打印流 打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式. 打印流根据流的分类: 字节打印流 PrintStream 字符打印流 PrintWriter 方法: void print( ...