java 朴素贝叶斯_朴素贝叶斯算法分析及java 实现

@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.数学语言描述

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

3.1贝叶斯定理:

6ed2f0c97ec0f09f5b4ba26c5894a653.gif

3.2 推导

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

1、设

gif.latex?x=%5C%7Ba_1,a_2,...,a_m%5C%7D为一个待分类项,而每个a为x的一个特征属性。

2、有类别集合

gif.latex?C=%5C%7By_1,y_2,...,y_n%5C%7D

3、计算

gif.latex?P(y_1%7Cx),P(y_2%7Cx),...,P(y_n%7Cx)

4、如果

gif.latex?P(y_k%7Cx)=max%5C%7BP(y_1%7Cx),P(y_2%7Cx),...,P(y_n%7Cx)%5C%7D,则

gif.latex?x%20%5Cin%20y_k

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

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

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

gif.latex?P(a_1%7Cy_1),P(a_2%7Cy_1),...,P(a_m%7Cy_1);P(a_1%7Cy_2),P(a_2%7Cy_2),...,P(a_m%7Cy_2);...;P(a_1%7Cy_n),P(a_2%7Cy_n),...,P(a_m%7Cy_n)

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

gif.latex?P(y_i%7Cx)=%5Cfrac%7BP(x%7Cy_i)P(y_i)%7D%7BP(x)%7D

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

gif.latex?P(x%7Cy_i)P(y_i)=P(a_1%7Cy_i)P(a_2%7Cy_i)...P(a_m%7Cy_i)P(y_i)=P(y_i)%5Cprod%5Em_%7Bj=1%7DP(a_j%7Cy_i)

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上下载:

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

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

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 lisatt = new LinkedList(); // 存储属性的名称:outlook,temperature,humidity,windy

public static LinkedList> lisvals = new LinkedList>(); //outlook:sunny,overcast,rainy 存储每个属性的取值,属性的特征

public static LinkedList listdata = new LinkedList();; // 原始数据

public static final String patternString = "@attribute(.*)[{](.*?)[}]";

//存储分类,比如,是,否。再比如:检测SNS社区中不真实账号,是真实用户还是僵尸用户

public static LinkedList sort=new LinkedList();

//计算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 map=new HashMap();

//先计算判定结果的概率,保存为文件

for(int i=0;i

//第一个for对取出sort,第二个for对data中的sort进行计数

//避免零频问题,对各项计数加1

Integer sum=1;

String sortname=sort.get(i);

Double probability=0.0;

for(int j=0;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

String attname=lisatt.get(i);

List lisval=lisvals.get(i);

//对属性的特征进行循环

for(int j=0;j

String attval=lisval.get(j);

//先取出sort(yes 还是no情况)

for(int n=0;n

//避免零频问题,对各项计数加1

Integer sum=1;

String sortname=sort.get(n);

Double probability=0.0;

//取出数据集进行for

for(int k=0;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

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 al = new ArrayList(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,朴素贝叶斯)