zoukankan      html  css  js  c++  java
  • 机器学习之Bayes

    基本思想

    朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。算法的基础是概率问题,分类原理是通过某对象的先验概率,利用贝叶斯公式计算出其后验概率,即该对象属于某一类的概率,选择具有最大后验概率的类作为该对象所属的类。朴素贝叶斯假设是约束性很强的假设,假设特征条件独立,但朴素贝叶斯算法简单,快速,具有较小的出错率。

    算法流程

    假设某个体有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;
    }
    


    版权声明:

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/walccott/p/4957095.html
Copyright © 2011-2022 走看看