IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]机器学习--朴素贝叶斯的分析与实现

    csharp25发表于 2016-06-03 12:39:50
    love 0

    贝叶斯定理:
    p(a|b) = p(b|a)*p(a)/p(b)
    假设:时间a,b相互独立。


    由于朴素贝叶斯基于贝叶斯定理,因此,在应用贝叶斯分类器时,所选的特征也应当是不相关的。


    例:
    训练数据: 四维向量数组,共15个元素。
    inputs ={
        new int[] { 0, 1, 1, 0 }, //  c=0 
        new int[] { 0, 1, 0, 0 }, //  c=0
        new int[] { 0, 0, 1, 0 }, //  c=0
        new int[] { 0, 1, 1, 0 }, //  c=0
        new int[] { 0, 1, 0, 0 }, //  c=0
        new int[] { 1, 0, 0, 0 }, //  c=1
        new int[] { 1, 0, 0, 0 }, //  c=1
        new int[] { 1, 0, 0, 1 }, //  c=1
        new int[] { 0, 0, 0, 1 }, //  c=1
        new int[] { 0, 0, 0, 1 }, //  c=1
        new int[] { 1, 1, 1, 1 }, //  c=2
        new int[] { 1, 0, 1, 1 }, //  c=2
        new int[] { 1, 1, 0, 1 }, //  c=2
        new int[] { 0, 1, 1, 1 }, //  c=2
        new int[] { 1, 1, 1, 1 }, //  c=2
    };
    



    前5个分类为0,中间五个分类为1,后五个分类为2。


    现在需要预测向量v{0,1,1,0}的分类。
    即分别求:
    p(c=0, inputs[0]=0, inputs[1]=1, inputs[2]=1, inputs[3]=0)的概率
    p(c=1, inputs[0]=0, inputs[1]=1, inputs[2]=1, inputs[3]=0)的概率
    p(c=2, inputs[0]=0, inputs[1]=1, inputs[2]=1, inputs[3]=0)的概率


    ,然后选出最大值。


    根据贝叶斯定理,并假设4个维度的特征不相关:
    p(c=0,v={0,1,1,0}) = p(input[0]=0,c=0)*p(input[1]=1,c=0)*p(input[2]=1,c=0)*p(input[3]=0,c=0)*p(c=0)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)
    p(c=1,v={0,1,1,0}) = p(input[0]=0,c=1)*p(input[1]=1,c=1)*p(input[2]=1,c=1)*p(input[3]=0,c=1)*p(c=1)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)
    p(c=2,v={0,1,1,0}) = p(input[0]=0,c=2)*p(input[1]=1,c=2)*p(input[2]=1,c=2)*p(input[3]=0,c=2)*p(c=2)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)


    ,对于本例,p(c=0) == p(c=1) == p(c=2),因此可将p(c={0|1|2})/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)视为常数。


    设,

    C = {p(c=0)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)}



    p(c=0,v={0,1,1,0}) = p(input[0]=0,c=0)*p(input[1]=1,c=0)*p(input[2]=1,c=0)*p(input[3]=0,c=0)*C
    p(c=1,v={0,1,1,0}) = p(input[0]=0,c=1)*p(input[1]=1,c=1)*p(input[2]=1,c=1)*p(input[3]=0,c=1)*C
    p(c=2,v={0,1,1,0}) = p(input[0]=0,c=2)*p(input[1]=1,c=2)*p(input[2]=1,c=2)*p(input[3]=0,c=2)*C
    



    求出以上3个概率后,取最大值即得到了分类。


    本例实现代码:


    void Main()
    {
    	
    //p(a|b) = p(b|a)*p(a)/p(b)
    
    
    //to calculate : p(c={0,1,2}, input = [0,1,1,0]):
    //p(c=0,input={0,1,1,0}) = p(input[0]=0,c=0)*p(input[1]=1,c=0)*p(input[2]=1,c=0)*p(input[3]=0,c=0)*p(c=0)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)
    //p(c=1,input={0,1,1,0}) = p(input[0]=0,c=1)*p(input[1]=1,c=1)*p(input[2]=1,c=1)*p(input[3]=0,c=1)*p(c=1)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)
    //p(c=2,input={0,1,1,0}) = p(input[0]=0,c=2)*p(input[1]=1,c=2)*p(input[2]=1,c=2)*p(input[3]=0,c=2)*p(c=2)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)
    
    
    //since p(c=0) == p(c=1) == p(c=2), set C = {p(c=0)/p(input[0]=0)*p(input[1]=1)*p(input[2]=1)*p(input[3]=0)}
    
    
    //p(c=0,input={0,1,1,0}) = p(input[0]=0,c=0)*p(input[1]=1,c=0)*p(input[2]=1,c=0)*p(input[3]=0,c=0)*C
    //p(c=1,input={0,1,1,0}) = p(input[0]=0,c=1)*p(input[1]=1,c=1)*p(input[2]=1,c=1)*p(input[3]=0,c=1)*C
    //p(c=2,input={0,1,1,0}) = p(input[0]=0,c=2)*p(input[1]=1,c=2)*p(input[2]=1,c=2)*p(input[3]=0,c=2)*C
    
    
    	var f0=0;
    	var f1=1;
    	var f2=1;
    	var f3=0;
    	
    	var p_input_equals_0_1_2_3 = 8*8*7*7/15*15*15*15.0;
    	var p_c_0_1_2 = 1/3;
    	var C = p_c_0_1_2 / p_input_equals_0_1_2_3;
    	
    	var p_c_0 = P_c_0(Feature(inputs,0), f0) * P_c_0(Feature(inputs,1),f1)* P_c_0(Feature(inputs,2),f2)* P_c_0(Feature(inputs,3),f3) * C;
    	//Console.WriteLine(p0);
    	var p_c_1 = P_c_1(Feature(inputs,0), f0) * P_c_1(Feature(inputs,1),f1)* P_c_1(Feature(inputs,2),f2)* P_c_1(Feature(inputs,3),f3) * C;
    	var p_c_2 = P_c_2(Feature(inputs,0), f0) * P_c_2(Feature(inputs,1),f1)* P_c_2(Feature(inputs,2),f2)* P_c_2(Feature(inputs,3),f3) * C;
    
    
    	var max = Math.Max(Math.Max(p_c_0,p_c_1),p_c_2);
    	if(max == p_c_0){
    		Console.WriteLine("category is 0");
    	}
    	else if(max == p_c_1){
    		Console.WriteLine("category is 1");
    	}
    	else{
    		Console.WriteLine("category is 2");
    	}
    }
    
    
    static int[][] inputs ={
        new int[] { 0, 1, 1, 0 }, //  c=0 
        new int[] { 0, 1, 0, 0 }, //  c=0
        new int[] { 0, 0, 1, 0 }, //  c=0
        new int[] { 0, 1, 1, 0 }, //  c=0
        new int[] { 0, 1, 0, 0 }, //  c=0
        new int[] { 1, 0, 0, 0 }, //  c=1
        new int[] { 1, 0, 0, 0 }, //  c=1
        new int[] { 1, 0, 0, 1 }, //  c=1
        new int[] { 0, 0, 0, 1 }, //  c=1
        new int[] { 0, 0, 0, 1 }, //  c=1
        new int[] { 1, 1, 1, 1 }, //  c=2
        new int[] { 1, 0, 1, 1 }, //  c=2
        new int[] { 1, 1, 0, 1 }, //  c=2
        new int[] { 0, 1, 1, 1 }, //  c=2
        new int[] { 1, 1, 1, 1 }, //  c=2
    };
    
    
    public static double P_c_0(int[] feature,int v){
    	var r = feature.Take(5).Count(x=>x == v)/5.0 /*from 1-5 , category is 0*/;
    	//Console.WriteLine(r);
    	return r;
    }
    public static double P_c_1(int[] feature,int v){
    	var r = feature.Skip(5).Take(5).Count(x=>x == v)/5.0 /*from 6-10 , category is 1*/;
    	//Console.WriteLine(r);
    	return r;
    }
    public static double P_c_2(int[] feature,int v){
    	var r = feature.Skip(10).Take(5).Count(x=>x == v)/5.0 /*from 11-15 , category is 2*/;
    	//Console.WriteLine(r);
    	return r;
    }
    
    
    
    
    public static int[] Feature(int[][] inputs, int c){
    	var result = new int[inputs.Length];
    	for(var i =0 ;i < inputs.Length; i++){
    		result[i] = inputs[i][c];
    	}
    	return result;
    }
    // Define other methods and classes here






    注,以上代码只用于对本例的朴素贝叶斯分类过程的分析,很多条件是hardcode的。




    以下是使用accord-framework实现的贝叶斯分类:


    public class BayesianDemo
        {
            public static void Execute()
            {
                int[][] inputs =
                {
                    //input                     output
                    new int[] { 0, 1, 1, 0 }, //  0 
                    new int[] { 0, 1, 0, 0 }, //  0
                    new int[] { 0, 0, 1, 0 }, //  0
                    new int[] { 0, 1, 1, 0 }, //  0
                    new int[] { 0, 1, 0, 0 }, //  0
                    new int[] { 1, 0, 0, 0 }, //  1
                    new int[] { 1, 0, 0, 0 }, //  1
                    new int[] { 1, 0, 0, 1 }, //  1
                    new int[] { 0, 0, 0, 1 }, //  1
                    new int[] { 0, 0, 0, 1 }, //  1
                    new int[] { 1, 1, 1, 1 }, //  2
                    new int[] { 1, 0, 1, 1 }, //  2
                    new int[] { 1, 1, 0, 1 }, //  2
                    new int[] { 0, 1, 1, 1 }, //  2
                    new int[] { 1, 1, 1, 1 }, //  2
                };
    
    
                int[] outputs = // those are the class labels
                {
                    0, 0, 0, 0, 0,
                    1, 1, 1, 1, 1,
                    2, 2, 2, 2, 2,
                };
                 
                // Create a discrete naive Bayes model for 3 classes and 4 binary inputs
                var bayes = new NaiveBayes(classes: 3, symbols: new int[] { 2, 2, 2, 2 });
    
    
                // Teach the model. The error should be zero:
                double error = bayes.Estimate(inputs, outputs);
    
    
                int answer = bayes.Compute(new int[] { 0, 1, 1, 0 });
    
    
                Console.WriteLine("category is : {0}",answer);
            }
        }
    
    
    class Program
        {
            static void Main(string[] args)
            {
                BayesianDemo.Execute();
                Console.ReadLine();
            }
        }




沪ICP备19023445号-2号
友情链接