• 机器学习之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;
    }
    


    版权声明:

  • 相关阅读:
    Jmeter配置slave
    Jmeter集合ant进行操作
    PageObject设计模式进行自动化用例的设计方法
    同学,迭代器生成器了解一下
    面向对象的一些方法与属性
    断言与异常
    wtforms-表单生成及验证
    DBUtils--数据库连接池
    Flask请求流程超清大图
    PEP8规范
  • 原文地址:https://www.cnblogs.com/walccott/p/4957095.html
Copyright © 2020-2023  润新知