基本思想
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。算法的基础是概率问题,分类原理是通过某对象的先验概率,利用贝叶斯公式计算出其后验概率,即该对象属于某一类的概率,选择具有最大后验概率的类作为该对象所属的类。朴素贝叶斯假设是约束性很强的假设,假设特征条件独立,但朴素贝叶斯算法简单,快速,具有较小的出错率。
算法流程
假设某个体有n项特征(Feature),分别为F1、F2、…、Fn。现有m个类别(Category),分别为C1、C2、…、Cm。贝叶斯分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值:
P(C|F1F2…Fn)
= P(F1F2…Fn|C)P(C) / P(F1F2…Fn)
由于 P(F1F2…Fn) 对于所有的类别都是相同的,可以省略,问题就变成了求
P(F1F2…Fn|C)P(C)
的最大值。
朴素贝叶斯分类器则是更进一步,假设所有特征都彼此独立,因此
P(F1F2…Fn|C)P(C)
= P(F1|C)P(F2|C) … P(Fn|C)P(C)
贝叶斯定理之所以有用,是因为我们在生活中经常遇到这种情况:我们可以很容易直接得出P(A|B),P(B|A)则很难直接得出,但我们更关心P(B|A),贝叶斯定理就为我们打通从P(A|B)获得P(B|A)的道路。
总结
Bayes模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,这给Bayes模型的正确分类带来了一定影响。在属性个数比较多或者属性之间相关性较大时,Bayes模型的分类效率比不上决策树模型。而在属性相关性较小时,Bayes模型的性能良好。
Bayes分类算法实现数字识别
/****************************************************************** * 函数名称:BayesErzhishuju() * 函数类型:int * 函数功能:基于二值数据的Bayes分类器 ,返回手写数字的类别 ******************************************************************/ int Classification::BayesErzhishuju() { double Pw[10];//先验概率P(wj)=Nj/N double P[10][25];//Pj(wi)wi:wi类,j:第j个特征 double PXw[10];//类条件概率P(X|wj) double PwX[10];//后验概率P(wj|X) int i,j; //求先验概率 int n[10];//各类样品数 int N=0;//样品总数 for(i=0;i<10;i++) { //各数字类别样品数 n[i]=pattern[i].number; N+=n[i];//样品总数 } for(i=0;i<10;i++) Pw[i]=(double)n[i]/(double)N;//先验概率 //求类条件概率 for(i=0;i<10;i++) { for(j=0;j<25;j++) { int numof1=0;//二值数据中1的个数 for(int k=0;k<pattern[i].number;k++) numof1+=pattern[i].feature[k][j]>0.1?1:0; P[i][j]=(double)(numof1+1)/(double)(n[i]+2); } } for(i=0;i<10;i++) { double p=1; for(int j=0;j<25;j++) { p*=(testsample[j]>0.1)?P[i][j]:1-P[i][j]; } PXw[i]=p; } //求后验概率 double PX=0.0,maxP=0.0; int number; for(i=0;i<10;i++) { PX+=Pw[i]*PXw[i]; } for(i=0;i<10;i++) { PwX[i]=Pw[i]*PXw[i]/PX; if(PwX[i]>maxP) { maxP=PwX[i]; number=i; } } return number; } /****************************************************************** * 函数名称:BayesLeasterror() * 函数类型:int * 函数功能:最小错误概率的Bayes分类器 ,返回手写数字的类别 ******************************************************************/ int Classification::BayesLeasterror() { double X[25];//待测样品 double Xmeans[25];//样品的均值 double S[25][25];//协方差矩阵 double S_[25][25];//S的逆矩阵 double Pw;//先验概率 double hx[10];//判别函数 int i,j,k,n; for(n=0;n<10;n++)//循环类别0~9 { int num=pattern[n].number;//样品个数 //求样品平均值 for(i=0;i<25;i++) Xmeans[i]=0.0; for(k=0;k<num;k++) { for(i=0;i<25;i++) Xmeans[i]+=pattern[n].feature[k][i]>0.10?1.0:0.0; } for(i=0;i<25;i++) Xmeans[i]/=(double)num; //求协方差矩阵 double mode[200][25]; for(i=0;i<num;i++) for(j=0;j<25;j++) mode[i][j]=pattern[n].feature[i][j]>0.10?1.0:0.0; for(i=0;i<25;i++) for(j=0;j<25;j++) { double s=0.0; for(k=0;k<num;k++) s=s+(mode[k][i]-Xmeans[i])*(mode[k][j]-Xmeans[j]); s=s/(double)(num-1); S[i][j]=s; } //求先验概率 int total=0; for(i=0;i<10;i++) total+=pattern[i].number; Pw=(double)num/(double)total; //求S的逆矩阵 for(i=0;i<25;i++) for(j=0;j<25;j++) S_[i][j]=S[i][j]; double(*p)[25]=S_; brinv(*p,25);//S的逆矩阵 //求S的行列式 double (*pp)[25]=S; double DetS; DetS=bsdet(*pp,25);//S的行列式 //求判别函数 for(i=0;i<25;i++) X[i]=testsample[i]>0.10?1.0:0.0; for(i=0;i<25;i++) X[i]-=Xmeans[i]; double t[25]; for(i=0;i<25;i++) t[i]=0; brmul(X,S_,25,t); double t1=brmul(t,X,25); double t2=log(Pw); double t3=log(DetS+1); hx[n]=-t1/2+t2-t3/2; } double maxval=hx[0]; int number=0; //判别函数的最大值 for(n=1;n<10;n++) { if(hx[n]>maxval) { maxval=hx[n]; number=n; } } return number; } /****************************************************************** * 函数名称:BayesLeastRisk(double loss[10][10]) * 函数类型:double* * 参数说明:double loss[10][10]:损失 * 函数功能:最小风险的Bayes分类器 ,返回各类的风险值 ******************************************************************/ double* Classification::BayesLeastRisk(double loss[10][10]) { double X[25];//待测样品 double Xmeans[25];//样品的均值 double S[25][25];//协方差矩阵S double S_[25][25];//S的逆矩阵 double P[10];//后验概率 double Pw;//先验概率 double hx[10];//判别函数 int i,j,k,n; for(n=0;n<10;n++)// { int num=pattern[n].number;//样品个数 //求样品均值 for(i=0;i<25;i++) Xmeans[i]=0.0; for(k=0;k<num;k++) { for(i=0;i<25;i++) Xmeans[i]+=pattern[n].feature[k][i]>0.2?1.0:0.0; } for(i=0;i<25;i++) Xmeans[i]/=(double)num; //求协方差矩阵 double mode[200][25]; for(i=0;i<num;i++) for(j=0;j<25;j++) mode[i][j]=pattern[n].feature[i][j]>0.2?1.0:0.0; for(i=0;i<25;i++) for(j=0;j<25;j++) { double s=0.0; for(k=0;k<num;k++) s=s+(mode[k][i]-Xmeans[i])*(mode[k][j]-Xmeans[j]); s=s/(double)(num-1); S[i][j]=s; } //求先验概率 int total=0;//样品总数 for(i=0;i<10;i++) total+=pattern[i].number; Pw=(double)num/(double)total; //求S的逆矩阵 for(i=0;i<25;i++) for(j=0;j<25;j++) S_[i][j]=S[i][j]; double(*p)[25]=S_; brinv(*p,25);//S的逆矩阵 //求S的行列式 double (*pp)[25]=S; double DetS; DetS=bsdet(*pp,25);//S的行列式 //求判别函数 for(i=0;i<25;i++) X[i]=testsample[i]>0.2?1.0:0.0; for(i=0;i<25;i++) X[i]-=Xmeans[i]; double t[25]; for(i=0;i<25;i++) t[i]=0; brmul(X,S_,25,t); double t1=brmul(t,X,25); double t2=log(Pw); double t3=log(DetS+1); P[n]=-t1/2+t2-t3/2; } for(n=0;n<10;n++) { double t=0.0; for(i=0;i<10;i++) t+=loss[n][i]*P[i]; hx[n]=t; } return (double*)hx; }
版权声明: