贝叶斯定理:
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();
}
}