1. 先引入一个简单的例子


一、病人分类的例子

让我从一个例子开始讲起,你会看到贝叶斯分类器很好懂,一点都不难。

某个医院早上收了六个门诊病人,如下表。

  症状  职业   疾病
  打喷嚏 护士   感冒
  打喷嚏 农夫   过敏
  头痛  建筑工人 脑震荡
  头痛  建筑工人 感冒
  打喷嚏 教师   感冒
  头痛  教师   脑震荡

现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?

根据贝叶斯定理:

 P(A|B) = P(B|A) P(A) / P(B)

可得

P(感冒|打喷嚏x建筑工人)

    = P(打喷嚏x建筑工人|感冒) x P(感冒)
    / P(打喷嚏x建筑工人)
假定"打喷嚏"和"建筑工人"这两个特征是独立的,因此,上面的等式就变成了
   P(感冒|打喷嚏x建筑工人)
    = P(打喷嚏|感冒) x P(建筑工人|感冒) x P(感冒)
    / P(打喷嚏) x P(建筑工人)
这是可以计算的。
  P(感冒|打喷嚏x建筑工人)
    = 0.66 x 0.33 x 0.5 / 0.5 x 0.33
    = 0.66

因此,这个打喷嚏的建筑工人,有66%的概率是得了感冒。同理,可以计算这个病人患上过敏或脑震荡的概率。比较这几个概率,就可以知道他最可能得什么病。

这就是贝叶斯分类器的基本方法:在统计资料的基础上,依据某些特征,计算各个类别的概率,从而实现分类。

二、朴素贝叶斯分类器的公式

假设某个体有n项特征(Feature),分别为F1、F2、...、Fn。现有m个类别(Category),分别为C1、C2、...、Cm。贝叶斯分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值:

 P(C|F1F2...Fn)
  = P(F1F2...Fn|C)P(C) / P(F1F2...Fn)

由于 P(F1F2...Fn) 对于所有的类别都是相同的,可以省略,问题就变成了求

 P(F1F2...Fn|C)P(C)

的最大值。

朴素贝叶斯分类器则是更进一步,假设所有特征都彼此独立,因此

 P(F1F2...Fn|C)P(C)
  = P(F1|C)P(F2|C) ... P(Fn|C)P(C)

上式等号右边的每一项,都可以从统计资料中得到,由此就可以计算出每个类别对应的概率,从而找出最大概率的那个类。

虽然"所有特征彼此独立"这个假设,在现实中不太可能成立,但是它可以大大简化计算,而且有研究表明对分类结果的准确性影响不大。

下面再通过两个例子,来看如何使用朴素贝叶斯分类器。


2. 举例说明(采用打球的例子)
通过上面的例子我们知道,朴素贝叶斯训练阶段要做的事情就是求: P(F1|C)P(F2|C)
... P(Fn|C)P(C)

2.1 下面以打球的例子分析:

datafile/naivebayes/train/in/weather.nominal.arff
#存放做决策的属性,一般是或否
@decision
yes,no
@attribute outlook {sunny, overcast, rainy}
@attribute temperature {hot, mild, cool}
@attribute humidity {high, normal}
@attribute windy {TRUE, FALSE}
@data
sunny,hot,high,FALSE,no
sunny,hot,high,TRUE,no
overcast,hot,high,FALSE,yes
rainy,mild,high,FALSE,yes
rainy,cool,normal,FALSE,yes
rainy,cool,normal,TRUE,no
overcast,cool,normal,TRUE,yes
sunny,mild,high,FALSE,no
sunny,cool,normal,FALSE,yes
rainy,mild,normal,FALSE,yes
sunny,mild,normal,TRUE,yes
overcast,mild,high,TRUE,yes
overcast,hot,normal,FALSE,yes
rainy,mild,high,TRUE,no

2.2训练阶段要做的事情就是求出以下各个值的概率:(先放结果再分析)

datafile/naivebayes/train/out/trainresult.arff

@decision P(yes) {0.6428571428571429}
@decision P(no) {0.35714285714285715}
@data
P(outlook=sunny|yes),0.2222222222222222
P(outlook=sunny|no),0.6
P(outlook=overcast|yes),0.4444444444444444
P(outlook=overcast|no),0.0
P(outlook=rainy|yes),0.3333333333333333
P(outlook=rainy|no),0.4
P(temperature=hot|yes),0.2222222222222222
P(temperature=hot|no),0.4
P(temperature=mild|yes),0.4444444444444444
P(temperature=mild|no),0.4
P(temperature=cool|yes),0.3333333333333333
P(temperature=cool|no),0.2
P(humidity=high|yes),0.3333333333333333
P(humidity=high|no),0.8
P(humidity=normal|yes),0.6666666666666666
P(humidity=normal|no),0.2
P(windy=TRUE|yes),0.3333333333333333
P(windy=TRUE|no),0.6
P(windy=FALSE|yes),0.6666666666666666
P(windy=FALSE|no),0.4

2.3

上面的各个概率计算过程如下:
P(yes)=9/14 (在训练集中,yes出现9次,总数是14 )
P(no)=5/14
P(outlook=sunny|yes)=2/9(同时为sunny和yes的记录出现了2次,而yes总数出现了9次)
P(outlook=sunny|no)=3/5 (同时为sunny和no的记录出现了3次,no出现了5次)

其它的计算一样,这里不例举了。

2.4  测试:

求 (sunny,hot,high,FALSE) 属于yes还是no呢?

为了显示好看,把(sunny,hot,high,FALSE) 用1来表示

计算方法如下:

属于yes的概率(其它这里严格意义的概率,因为没有除以分母)

P(1|yes)= P(yes)*P(sunny|yes)*P(hot|yes)*P(high|yes)*P(FALSE|yes)=0.6428571428571429*0.2222222222222222*0.2222222222222222*0.3333333333333333*0.6666666666666666=0.007(约等)
P(1|no)=0.027
显然它属于no的概率大一点,判定它为no.

2.5 零频问题

以上计算没有考虑零频问题,实际的计算中应该避免零频问题,即在每个项计数时加1。

3.数学语言描述

关于数学公式的描述,这位大牛写得非常详细,建议大家看一看。

http://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html

3.1贝叶斯定理:

3.2 推导

朴素贝叶斯分类的正式定义如下:

1、设为一个待分类项,而每个a为x的一个特征属性。

2、有类别集合

3、计算

4、如果,则

那么现在的关键就是如何计算第3步中的各个条件概率。我们可以这么做:

1、找到一个已知分类的待分类项集合,这个集合叫做训练样本集。

2、统计得到在各类别下各个特征属性的条件概率估计。即

3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:

因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:

5.测试结果

下面结果对各项统计加1,为了避免零频问题。

sunny,hot,high,FALSE   判断的结果是:no	      --参考数值是:0.059
overcast,mild,high,TRUE 判断的结果是:yes --参考数值是:0.028
overcast,hot,normal,FALSE 判断的结果是:yes --参考数值是:0.052
rainy,mild,high,TRUE 判断的结果是:no --参考数值是:0.059

在实际中应随机抽取80%数据作为样本集,20%作为测试集,本例没考虑这点。

4.JAVA实现

详细源码请到我的Github上下载:

https://github.com/Bellonor/myHadoopProject/tree/master/com.homework/src/sequence/machinelearning/naivebayes/sequence/machinelearning/naivebayes/bayesdemo

时间匆忙,写例子为讲解。代码中各种漏洞请各位指出。谢谢!

以下仅给出训练部分的代码:

package sequence.machinelearning.naivebayes.bayesdemo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.LinkedList;
/**
* 案例:http://www.cnblogs.com/zhangchaoyang/articles/2586402.html
* @author Jamas
* 也参考了这篇文章:http://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html
*/
public class Train { public static LinkedList<String> lisatt = new LinkedList<String>(); // 存储属性的名称:outlook,temperature,humidity,windy
public static LinkedList<ArrayList<String>> lisvals = new LinkedList<ArrayList<String>>(); //outlook:sunny,overcast,rainy 存储每个属性的取值,属性的特征
public static LinkedList<String[]> listdata = new LinkedList<String[]>();; // 原始数据 public static final String patternString = "@attribute(.*)[{](.*?)[}]";
//存储分类,比如,是,否。再比如:检测SNS社区中不真实账号,是真实用户还是僵尸用户
public static LinkedList<String> sort=new LinkedList<String>(); //计算P(F1|C)P(F2|C)...P(Fn|C)P(C),并保存为文本文件
/**
* 为了避免零频问题,对每个计数加1,只要数量足够大,加1是可以忽略的
* @throws IOException
*/
public void CountProbility() throws IOException{ String src="datafile/naivebayes/train/out/trainresult.arff";
delfile(src);
File file=new File(src);
if(file.exists())
file.createNewFile();
FileOutputStream out=new FileOutputStream(file,true);
Map<String,Integer> map=new HashMap<String,Integer>();
//先计算判定结果的概率,保存为文件
for(int i=0;i<sort.size();i++){
//第一个for对取出sort,第二个for对data中的sort进行计数
//避免零频问题,对各项计数加1
Integer sum=1;
String sortname=sort.get(i);
Double probability=0.0; for(int j=0;j<listdata.size();j++){
String[] line=listdata.get(j);
if(line[line.length-1].equals(sortname)){
sum=sum+1;
}
}
map.put(sortname, sum);
probability=Double.valueOf(sum)/Double.valueOf(listdata.size());
//写入文件
StringBuffer sb=new StringBuffer();
sb.append("@decision P("+sortname+") {"+probability.toString()+"}\n");//如果不加"/n"则不能实现换行。
System.out.print(sb.toString()); out.write(sb.toString().getBytes("utf-8"));
}
out.write("@data\n".getBytes("utf-8"));
System.out.print("@data\n");
//先计算判定结果的概率,保存为文件
//out.close(); //到最后写完的时候再关闭
//分别统计P(F1|C)P(F2|C)...P(Fn|C)的个数,参考:http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html
//对属性进行循环
for(int i=0;i<lisatt.size();i++){ String attname=lisatt.get(i);
List<String> lisval=lisvals.get(i);
//对属性的特征进行循环
for(int j=0;j<lisval.size();j++){
String attval=lisval.get(j);
//先取出sort(yes 还是no情况)
for(int n=0;n<sort.size();n++){
//避免零频问题,对各项计数加1
Integer sum=1;
String sortname=sort.get(n);
Double probability=0.0; //取出数据集进行for
for(int k=0;k<listdata.size();k++){
String[] line=listdata.get(k);
if(line[line.length-1].equals(sortname)&&line[i].equals(attval)){
sum=sum+1;
}
} probability=Double.valueOf(sum)/Double.valueOf(map.get(sortname));
//写入文件
StringBuffer sb=new StringBuffer();
sb.append("P("+attname+"="+attval+"|"+sortname+"),"+probability+"\n");//如果不加"/n"则不能实现换行。
System.out.print(sb.toString());
out.write(sb.toString().getBytes("utf-8"));
} }
}
out.close();
} //读取arff文件,给attribute、attributevalue、data赋值
public void readARFF(File file) {
try {
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line;
Pattern pattern = Pattern.compile(patternString);
while ((line = br.readLine()) != null) {
if (line.startsWith("@decision")) {
line = br.readLine();
if(line=="")
continue;
String[] type = line.split(",");
for(int i=0;i<type.length;i++){
sort.add(type[i].trim());
}
}
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
lisatt.add(matcher.group(1).trim());
String[] values = matcher.group(2).split(",");
ArrayList<String> al = new ArrayList<String>(values.length);
for (String value : values) {
al.add(value.trim());
}
lisvals.add(al);
} else if (line.startsWith("@data")) {
while ((line = br.readLine()) != null) {
if(line=="")
continue;
String[] row = line.split(",");
listdata.add(row);
}
} else {
continue;
}
}
br.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Train train=new Train();
train.readARFF(new File("datafile/naivebayes/train/in/weather.nominal.arff"));
train.CountProbility(); }
public void delfile(String filepath){
File file=new File(filepath);
if(file.exists())
{
//file.createNewFile();
file.delete();
} }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

朴素贝叶斯算法分析及java 实现的更多相关文章

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

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

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

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

  3. 朴素贝叶斯算法java实现(多项式模型)

    网上有很多对朴素贝叶斯算法的说明的文章,在对算法实现前,参考了一下几篇文章: NLP系列(2)_用朴素贝叶斯进行文本分类(上) NLP系列(3)_用朴素贝叶斯进行文本分类(下) 带你搞懂朴素贝叶斯分类 ...

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

    朴素贝叶斯(Naive Bayesian)是一种基于贝叶斯定理和特征条件独立假设的分类方法,它是基于概率论的一种有监督学习方法,被广泛应用于自然语言处理,并在机器学习领域中占据了非常重要的地位.在之前 ...

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

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

  6. 朴素贝叶斯算法源码分析及代码实战【python sklearn/spark ML】

    一.简介 贝叶斯定理是关于随机事件A和事件B的条件概率的一个定理.通常在事件A发生的前提下事件B发生的概率,与在事件B发生的前提下事件A发生的概率是不一致的.然而,这两者之间有确定的关系,贝叶斯定理就 ...

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

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

  8. 朴素贝叶斯(NB)复习总结

    摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 贝叶斯分类算法是统计学的一种分类方法,其分类原理就是利用贝叶斯公式根据某 ...

  9. scikit-learn 朴素贝叶斯类库使用小结

    之前在朴素贝叶斯算法原理小结这篇文章中,对朴素贝叶斯分类算法的原理做了一个总结.这里我们就从实战的角度来看朴素贝叶斯类库.重点讲述scikit-learn 朴素贝叶斯类库的使用要点和参数选择. 1. ...

随机推荐

  1. Thread.currentThread().getContextClassLoader() and Class.getClassLoader()

    Thread.currentThread().getContextClassLoader() and Class.getClassLoader()   一.同一工程中: String path = T ...

  2. [原创]java WEB学习笔记30:Cookie Demo 之显示最近浏览的记录

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. Spark Structured Streaming框架(5)之进程管理

    Structured Streaming提供一些API来管理Streaming对象.用户可以通过这些API来手动管理已经启动的Streaming,保证在系统中的Streaming有序执行. 1. St ...

  4. 【DP】最长不下降子序列问题(二分)

    Description 给你一个长度为n的整数序列,按从左往右的顺序选择尽量多的数字并且满足这些数字不下降. Thinking 朴素dp算法:F[i]表示到第i位为止的最长不下降子序列长度 F[i]= ...

  5. [算法]Rotate Array

    You may have been using Java for a while. Do you think a simple Java array question can be a challen ...

  6. Spring Cloud之Hystrix服务保护框架

    服务保护利器 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的 ...

  7. Mac安装使用kettle

    kettle是一个ETL工具 下载安装 https://jaist.dl.sourceforge.net/project/pentaho/Data Integration/ 选择版本后下载,并解压,如 ...

  8. 有關WCF一個自認爲比較經典的博客

    无废话WCF入门教程四[WCF的配置文件] (http://www.cnblogs.com/iamlilinfeng/archive/2012/10/02/2710224.html) -------- ...

  9. Git之Eclipse提交项目到Github并实现多人协作

    一.Eclipece提交项目到Github 见  eclipse提交项目到github 二.利用github组织实现多人协作 1.新建组织: New organization

  10. windows下用vs2010编译ffmpeg

    转载自;http://q1q2q3q4q5q6ln.blog.163.com/blog/static/500794332014666536283/ (注意:请务必先阅读:七,后记补充:) ffmpeg ...