贝叶斯决策论是在所有相关概率都已知的理想情形下,基于这些概率和误判损失来选择最优的类别标记。
假设有N中可能的类别标记,即
y={c1,c2,...,cN}
,
λij
是将一个真实标记为
cj
的样本误分类为
ci
的样本误分类为所产生的损失。基于后验概率
p(ci|x)
可获得将样本
x
分类为
例如,若目标是最小化分类错误率,则误判损失 λij 可写为
然而后验概率 P(c|x) 。然而,在现实任务中这通常难以直接获得。从这个角度来看,机器学习所要实现的是基于有限的训练样本集尽可能准确的估计出后验概率 p(c|x) 。大体来说,主要有两种策略:给定 可通过直接建模 p(c|x) 来预测 c ,这样得到的是“判别式模型”;也可现对联合概率分布
基于贝叶斯定理, P(c|x) 可写为
类先验概率 P(c) 也表达了样本空间各类样本所占的比例,根据大数定律,当训练集包含充足的独立同分布样本时, P(c) 可通过各类样本出现的概率来进行估计。
对于条件概率 P(x|c) 由于它设计关于 x 所有属性的联合概率,直接根据样本出现的频率来估计将会遇到严重的困难。例如,假设样本的d个属性都是二值的,则样本空间将会有
package naiveBayes;
import java.io.IOException;
public class NaiveBayesmain {
public static void main(String[] args) throws IOException {
InputStringData ori=new InputStringData();
String[][] data=ori.loadData("watermelon.txt");
//输入原始数据,本例子采用《机器学习》——周志华watermentlon2.0数据
String[] feature=data[0];
for(int i=0;i<feature.length;i++){
}
String[][]attribute=new String[data.length-1][data[0].length-1];
for(int i=0;i<data.length-1;i++){
attribute[i]=data[i+1];
for(int j=0;j<attribute[0].length;j++){
}
}
//将源数据第一行变量名输入feature,剩下的属性值输入attribute
System.out.println("p(x|c):");
NaiveBayes myBayesdis=new NaiveBayes(attribute,feature);
Bayestools mytools=new Bayestools(feature);
String[]testvalue=mytools.getvalue(attribute, feature[1]);
double[][][]BayesDis=myBayesdis.Bayes();
for(int i=0;i<BayesDis.length;i++){
String[] temp=mytools.getvalue(attribute,feature[i+1]);
for(int j=0;j<temp.length;j++){
for(int k=0;k<BayesDis[i][j].length;k++){
System.out.print(mytools.getvalue(attribute, feature[i+1])[j]+"|"+mytools.getvalue(attribute, feature[0])[k]+":"+BayesDis[i][j][k]+" ");
}
System.out.println("");
}
System.out.println("");
}
//计算P(xi|c)的值
System.out.println("");
System.out.println("p(c):");
double[] c=mytools.getRatio(attribute, feature[0], mytools.getvalue(attribute,feature[0]));
for(int i=0;i<c.length;i++){
System.out.print(mytools.getvalue(attribute, feature[0])[i]+":"+c[i]);
}
//计算P(c)的值
}
package naiveBayes;
public class NaiveBayes {
private String[][]attribute;
private String[]feature;
public NaiveBayes(String[][] a,String [] b){
attribute=a;
feature=b;
}
public double [][][]Bayes(){
Bayestools mytool=new Bayestools(feature);
int max1=-1;
String[] t=mytool.getvalue(attribute,feature[0]);
for(int i=1;i<feature.length;i++){
String[] tt=mytool.getvalue(attribute, feature[i]);
if(tt.length>max1){
max1=tt.length;
}
}
double[][][]Bayes=new double[feature.length-1][max1][t.length];
//生成一个三维数组
for(int i=0;i<Bayes.length;i++){
Bayes[i]=mytool.conprob(attribute, feature[i+1], feature[0]);
}
return Bayes;
}
//计算p(xi|c)
}
package naiveBayes;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class InputStringData {
int countRow=0,countCol=0;
public String[][] loadData(String trainfile)throws IOException{
ArrayList<String>features = new ArrayList<String>();
File file = new File("C:\\Users\\CJH\\Desktop\\R程序运行",trainfile);
Scanner input1 = new Scanner(file);
while(input1.hasNext()){
String line = input1.nextLine();
Scanner input2 = new Scanner(line);
while(input2.hasNext()){
features.add(input2.next());
countCol++;
}
countRow++;input2.close();
}
countCol=countCol/countRow;
input1.close();
String [][]x = new String[countRow][countCol];
int index=0;
for(int i=0;i<countRow;i++){
for(int j=0;j<countCol;j++){
x[i][j]=features.get(index);
index++;
}
}
return x;
}
}
//输入原始数据
package naiveBayes;
import java.security.KeyStore.Entry.Attribute;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Bayestools {
private String[] feature;
public Bayestools(String[]a){
feature=a;
}
public String[]getvalue(String[][]t,String n){
int index=-1;
for(int i=0;i<feature.length;i++){
if (feature[i].equals(n)){
index=i;
break;
}
}
if (index==-1){
System.out.print("error");
}
Set<String> temp=new HashSet<String>();
for (int i=0;i<t.length;i++){
temp.add(t[i][index]);
}
Iterator<String> set=temp.iterator();
String[]value=new String[temp.size()];
for(int i=0;i<value.length;i++){
value[i]=set.next();
}
return value;
}
//取出某一类所有子集的值
public double[][]conprob(String[][] t,String a,String b){
//t字符型数据框,a表示选中属性,b表示条件属性
int index1=-1;
int index2=-1;
Arith ari=new Arith();
for(int i=0;i<feature.length;i++){
if (feature[i].equals(a)){
index1=i;
break;
}
}
for(int i=0;i<feature.length;i++){
if (feature[i].equals(b)){
index2=i;
break;
}
}
Bayestools temptool=new Bayestools(feature);
String[] target=temptool.getvalue(t, a);
String[] con=temptool.getvalue(t,b);
double[][]conprob=new double[target.length][con.length];
double[]judgenum=new double[con.length];
for(int i=0;i<judgenum.length;i++){
for(int j=0;j<t.length;j++){
if(t[j][index2].equals(con[i])){
judgenum[i]++;
}
}
}
for(int i=0;i<target.length;i++){
for(int j=0;j<con.length;j++){
for(int t1=0;t1<t.length;t1++){
if(t[t1][index1].equals(target[i])&&t[t1][index2].equals(con[j])){
conprob[i][j]++;
}
}
conprob[i][j]=ari.div(conprob[i][j]+1,judgenum[j]+(double)target.length,4);
}
}
return conprob;
}
//计算条件概率P(a|b)
public double[]getRatio(String[][]b,String t,String[] n){
int index=-1;
for(int i=0;i<feature.length;i++){
if(feature[i].equals(t)){
index=i;
break;
}
}
double[] count=new double[n.length];
for(int i=0;i<n.length;i++){
for(int j=0;j<b.length;j++){
if(b[j][index].equals(n[i])){
count[i]++;
}
}
}
Arith ari=new Arith();
double[]getRatio=new double[n.length];
for(int i=0;i<n.length;i++){
getRatio[i]=ari.div(count[i],(double)b.length,4);
}
return getRatio;
}
//计算某一属性所有子集的比例
}
//此包为计算NaiveBayes中使用的一些计算方法
package naiveBayes;
import java.math.BigDecimal;
public class Arith{
private static final int DEF_DIV_SCALE=10;
public double add(double v1,double v2){
BigDecimal b1=new BigDecimal(Double.toString(v1));
BigDecimal b2=new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
public double sub(double v1,double v2){
BigDecimal b1=new BigDecimal(Double.toString(v1));
BigDecimal b2=new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
public double mul(double v1,double v2){
BigDecimal b1=new BigDecimal(Double.toString(v1));
BigDecimal b2=new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
public double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
public double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1=new BigDecimal(Double.toString(v1));
BigDecimal b2=new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
public double mul(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1=new BigDecimal(Double.toString(v1));
BigDecimal b2=new BigDecimal(Double.toString(v2));
if(v1!=0&&v2!=0){
BigDecimal b3=new BigDecimal(Double.toString(1));
BigDecimal b4=new BigDecimal(b3.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue());
return b1.divide(b4,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
else{
return 0;
}
}
public double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b=new BigDecimal(Double.toString(v));
BigDecimal one=new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
实验结果及实例分析:
p(x|c):
浅白|好瓜:0.1818 浅白|坏瓜:0.4167
青绿|好瓜:0.3636 青绿|坏瓜:0.3333
乌黑|好瓜:0.4545 乌黑|坏瓜:0.25
硬挺|好瓜:0.0909 硬挺|坏瓜:0.25
蜷缩|好瓜:0.5455 蜷缩|坏瓜:0.3333
稍蜷|好瓜:0.3636 稍蜷|坏瓜:0.4167
沉闷|好瓜:0.2727 沉闷|坏瓜:0.3333
清脆|好瓜:0.0909 清脆|坏瓜:0.25
浊响|好瓜:0.6364 浊响|坏瓜:0.4167
稍糊|好瓜:0.1818 稍糊|坏瓜:0.4167
模糊|好瓜:0.0909 模糊|坏瓜:0.3333
清晰|好瓜:0.7273 清晰|坏瓜:0.25
稍凹|好瓜:0.3636 稍凹|坏瓜:0.3333
凹陷|好瓜:0.5455 凹陷|坏瓜:0.25
平坦|好瓜:0.0909 平坦|坏瓜:0.4167
软粘|好瓜:0.3 软粘|坏瓜:0.3636
硬滑|好瓜:0.7 硬滑|坏瓜:0.6364
p(c):
好瓜:0.4706坏瓜:0.5294