模式识别-基于Java的手写数字识别分类

这个算法是基朴素贝叶斯分类算法做的, 首先我们了解一下什么是贝叶斯;

贝叶斯公式:

我们设事件A发生的概率为P(A),事件Bi发生的概率为P(Bi),事件A发生的条件下事件Bi发生的概率被记为P(Bi|A),

但往往求P(Bi|A)时有一定的难度,因此有了贝叶斯公式之后可以将P(Bi|A)做一个转化,这样就方便了很多。

比如一个学校中总人数为1000人,男生的人数占总人数的60%,女生的人数占总人数的40%,男生们都会打蓝篮球,女生中有30%会打篮球,看到了学校有一个人在打篮球,问他是男生的概率?

我们可以设事件A为:是男生,事件B为:打篮球

朴素贝叶斯分类算法是贝叶斯分类算法中最基本也是最常用的算法之一,它的基本分类思想也很简单,就是对于一个待被分类的项X,分别利用贝叶斯公式求出在X发生的条件下,分别求出各个类别发生的概率,那个类别发生的概率最大,就把X归到哪一类去。

下面详细讲解下朴素贝叶斯分类算法的详细流程:

1,我们设X={P1,P2,P3......Pn}为一个待被分类的分类项,P1,P2..Pn 为X的特征

2, 类别的集合(分类项)C={ y1, y2, y3... ,yn }。

3,分别计算在X发生的条件下各个类别发生的概率P(y1 | X), P(y2 | X), P(y3 | X), P(yn | X)

4,   然后求出X发生的条件下 概率最大打类别P(ym| X)=MAX{P(y1 | X), P(y2 | X), P(y3 | X), P(yn | X)} 

就把X归并到ym 类。

但重点是第三步往往不好直接求解,所以我们就要借助贝叶斯公式求解,我们现在具体问题具体分析,在实战中具体看看第三步是怎么实现的。

我们现在有400张类似于这样的0-9数字手写图片,每张图片28*28像素(我的代码里面把它缩放成14*14),0-9个40张,我们打算用300张作为训练集,100张作为测试集,首先我们要把图片读进来,然后灰度化,和二值化。其实Java有一套自己处理图片的强大的库,我这里用的是openvc处理的不过都一样,我们先把openvc的jar包导进去。

1,我们计算测试集的先验概率:  Mi表示(0-9)分组,M表示总共图片的个数300  每个分组都是30张所以每个分组的概率是相等的都是1/10;

2,我们计算在在分组Yi发生的条件下X发生的概率P(X | Yi), 就要计算P(X | Yi),我们先得计算分组Yi发生的条件下X的每个特征发生的概率,Pj(Yi)表示X在Y类下,X的第j个特征为1的情况下的概率:

              

3,最后我们利用贝叶斯公式求后验概率:

 

	for(int i=0;i<10;i++){
	   File file=new File("D:\\image\\"+i);     //图片存放的根目录
	   String[] str=file.list();
	   for(int j=0;j<40;j++){
	      String imgname="D:\\image\\"+i+"\\"+str[j];  //0-9分组的图片存放的目录
	      image=Imgcodecs.imread(imgname);             // 读取图片
	      Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);//灰度化
	      Imgproc.threshold(gray,binary,0,255,Imgproc.THRESH_BINARY); //二值化

注意:image ,gray, binary都是mat类型,这样图片就转成了0和255的像素,我们现在把存存到二维数组中去,

 	for(int a=0;a<28;a++){
	   for(int b=0;b<28;b++){	
	      value1[a][b]= (int) binary.get(a,b)[0];   //把存二值化的值存到中间数组中去
	      if(value1[a][b]==255){
		  value[a/2][b/2]++;        //转换成14*14 的
	       }
	   }	 
	}
        for(int m=0;m<14;m++){
	    for(int n=0;n<14;n++){
	       if(j<30){
	         train[i][j][m][n]=value[m][n]/4; 
	         }  //300张训练集,i代表分类【0-9】,j代表每个分组图片的个数【0-30】 
	      else {
	            test[i][j-30][m][n]=value[m][n]/4;		
		}
	   }
	} 

      

数组没转换之前我们如果打印二维数组value1[a][b]/255输出这样的效果,存二维数组这里我们用了中间数组的转换,把它转化成value[14][14]的数组,当然你也可以转成【4】【4】或者不转都行,最后转成的数组大小不同,结果也不同。最后在把他们放到训练集合和测试集中去。

	for(int i=0;i<10;i++){
	   for(int n=0;n<14;n++){
	      for(int m=0;m<14;m++){
		for(int j=0;j<30;j++){
		      fin[i][0][m][n]+=train[i][j][m][n];
		   }
		     fin[i][0][m][n]=(fin[i][0][m][n]+1)/32;  
	        }
	    }
        }

我们把每个分类的30张图片各个特征的概率加在一起,fin[i][0][m][n]+1/32的原因是为了不让概率p为0。

double max=0,temp=1,sum=0,p=0;
int flag=0;
for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
	max=0;
	for(int k=0;k<10;k++){
	    temp=1;
	    p=0;
	    for(int m=0;m<14;m++){
		for(int n=0;n<14;n++){
		    if(test[i][j][m][n]==0){
			p=1-fin[k][0][m][n];
		    }
		    else{
			p=fin[k][0][m][n];
			}
	            temp=temp*p;
		   }
	    }
	   if(max<temp){
	max=temp;
	flag=k;
	}
	}
	if(i==flag)sum++;
   }
}

然后让测试集合的100张图片,每个图片和10个类别的利用贝叶斯公式算出的概率作比较,那个最大把他划分到那个类别当中,然后载于原来已经知道的类别做比较,如果相同就识别正确,最后得知识别率为83%。

需要下载数据集和代码的 

连接为https://download.csdn.net/download/qq_34402394/11992903   csdn下载最少也要5c币 ,没有c币的私聊我

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值