机器学习入门算法及其java实现-朴素贝叶斯

贝叶斯决策论是在所有相关概率都已知的理想情形下,基于这些概率和误判损失来选择最优的类别标记。
假设有N中可能的类别标记,即 y={c1,c2,...,cN} , λij 是将一个真实标记为 cj 的样本误分类为 ci 的样本误分类为所产生的损失。基于后验概率 p(ci|x) 可获得将样本 x 分类为ci所产生的期望损失(expected loss),即在样本 x 上的“条件风险”(conditional risk)。

R(ci|x)=j=1Nλijp(cj|x)
我们的任务是寻找一个判定准则 h:xy 以最小总体风险。

R(h)=Ex[R(h(x)|x)]
对于每个样本 x ,若h能最小化条件风险 R(h(x)|x) ,则总体风险 R(h) 也将被最小化。这就产生了贝叶斯判定准则(Bayes decision rule):为最小化总体风险,只需在每个样本上选择那个能使条件风险 R(c|x) 最小的类别标记,即
h(x)=argmincyR(c|x)
此时, h 称为贝叶斯最佳分类器,与之对应的总体风险 R(h) 称为贝叶斯风险。 1R(h) 反映了分类器所能达到的最好性能,即通过机器学习所能产生的模型精度的理论上限。
例如,若目标是最小化分类错误率,则误判损失 λij 可写为
λij={01if i=jif otherwise
此时条件风险
R(c|x)=1p(c|x)
即对每个样本 xi 选择能使后验概率 P(c|x) 最大的类别标记。
然而后验概率 P(c|x) 。然而,在现实任务中这通常难以直接获得。从这个角度来看,机器学习所要实现的是基于有限的训练样本集尽可能准确的估计出后验概率 p(c|x) 。大体来说,主要有两种策略:给定 可通过直接建模 p(c|x) 来预测 c ,这样得到的是“判别式模型”;也可现对联合概率分布p(x,c),然后在由此获得 P(c|x) ,这样得到的是“生成式模型”。对于生成式模型,必然考虑:
P(c|x)=P(x,c)P(x)

基于贝叶斯定理, P(c|x) 可写为
P(c|x)=P(c)P(x|c)P(x)
其中 P(c) 是类“先验”概率; P(x|c) 是样本 x 相对于类标记c的类条件概率,或称为“似然”; P(x) 是用于归一化的“证据”因子。对给定样本 ,证据因子 P(x) 与类标记无关,因此估计 P(c|x) 的问题就转化为如何基于训练数据D来估计先验 P(c) 和似然 P(x|c)
类先验概率 P(c) 也表达了样本空间各类样本所占的比例,根据大数定律,当训练集包含充足的独立同分布样本时, P(c) 可通过各类样本出现的概率来进行估计。
对于条件概率 P(x|c) 由于它设计关于 x 所有属性的联合概率,直接根据样本出现的频率来估计将会遇到严重的困难。例如,假设样本的d个属性都是二值的,则样本空间将会有2d种可能的取值,在现实应用中,这个值往往远大于训练样本数m,也就是说,很多样本取值在训练集种根本没有出现,直接使用频率来估计 P(x|c) 显然不可行,因为“未被观测到”与“出现概率为零”通常是不同的。

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

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值