@decision P(yes) {0.6428571428571429}@decision P(no) {0.35714285714285715}@dataP(outlook=sunny|yes),0.2222222222222222P(outlook=sunny|no),0.6P(outlook=overcast|yes),0.4444444444444444P(outlook=overcast|no),0.0P(outlook=rainy|yes),0.3333333333333333P(outlook=rainy|no),0.4P(temperature=hot|yes),0.2222222222222222P(temperature=hot|no),0.4P(temperature=mild|yes),0.4444444444444444P(temperature=mild|no),0.4P(temperature=cool|yes),0.3333333333333333P(temperature=cool|no),0.2P(humidity=high|yes),0.3333333333333333P(humidity=high|no),0.8P(humidity=normal|yes),0.6666666666666666P(humidity=normal|no),0.2P(windy=TRUE|yes),0.3333333333333333P(windy=TRUE|no),0.6P(windy=FALSE|yes),0.6666666666666666P(windy=FALSE|no),0.4
2.3
上面的各个概率计算过程如下:
P(yes)=9/14 (在训练集中,yes出现9次,总数是14 )P(no)=5/14P(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.059overcast,mild,high,TRUE 判断的结果是:yes --参考数值是:0.028overcast,hot,normal,FALSE 判断的结果是:yes --参考数值是:0.052rainy,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 stubTrain 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(); } }}
当你能飞的时候就不要放弃飞