任务简介
给了70000个数字,60000个训练样本,10000个测试样本,完成对数字0~9的识别。使用matlab实现。
特征提取
- 使用田字划分分辨率来进行特征提取,代码:
function feature=Get_Feature(A,n,m)
%依照分辨率n*m,则矩阵A维数为m*n
A=im2bw(A,0.5);
a1=A(1:floor(m/2),1:floor(n/2));
a2=A(1:floor(m/2),floor(n/2)+1:n);
a3=A(floor(m/2)+1:m,1:floor(n/2));
a4=A(floor(m/2)+1:m,floor(n/2)+1:n);
f1=nnz(a1);
f2=nnz(a2);
f3=nnz(a3);
f4=nnz(a4);
feature=[f1 f2 f3 f4]';
此处注意分辨率的维数表示和矩阵是反的。
2. 把所有的像素点都作为一列向量特征
function feature=Get_Feature2(A,n,m)
%依照分辨率n*m,则矩阵A维数为m*n
A=im2bw(A,0.5);
array=A(:);
feature=array;
KNN法
- 采用田字特征提取
主函数:
clc
clear all
close all
%% 获取训练样本
Path = 'C:\杂七杂八杂货铺\模式识别\数字识别\手写体数字70000\';
path_train=strcat([Path,'训练图像\']);%训练样本文件夹的路径
file_struct=dir([path_train,'*.bmp']);%列出当前目录下符合'.bmp'的文件并放在文件结构体中
n_train=length(file_struct);%获取训练样本个数
for j=1:n_train
sample=imread([path_train,file_struct(j).name]);%打开第j个训练样本
X_train(:,j)=Get_Feature2(sample,28,28);%获取该样本特征,图片分辨率为20*20
class_train(j)=file_struct(j).name(1);%获取该训练样本的类别,为字符型
end
class_train=str2num(class_train(:))';%将字符型转化为数组
%% 获取测试样本
path_test=strcat([Path,'测试图像\']);%测试样本文件夹的路径
file_struct=dir([path_test,'*.bmp']);%列出当前目录下符合'.bmp'的文件并放在文件结构体中
n_test=length(file_struct);%获取测试样本个数
for j=1:n_test
sample=imread([path_test,file_struct(j).name]);%打开第j个训练样本
X_test(:,j)=Get_Feature2(sample,28,28);%获取该样本特征,图片分辨率为28*28
class_test(j)=file_struct(j).name(1);%获取该测试样本的类别
end
class_test=str2num(class_test(:))';%将字符型转化为数组
%% KNN法
for K=1:2:9
[topK,class_judge]=knn(X_train,X_test,class_train,class_test,K);
%校验错误率
error=class_judge-class_test;
ro(K)=(nnz(error)/n_test)*100;%计算错误率
disp(strcat('K=',num2str(K),'时,错误率为',num2str(ro(K)),'%'));
end
子函数:Get_Feature()和Get_Feature2()见上特征提取
knn:
function [topK,class_judge]=knn(X_train,X_test,class_train,class_test,K)
%X_train为训练样本,test为测试样本
%class_train为每个训练样本对应的类别,class_test为每个测试样本对应的类别
n_train=size(X_train,2);
n_test=size(X_test,2);
for i=1:n_test
X_test_mat=repmat(X_test(:,i),1,n_train);%将测试集扩展至训练集维度
Z=(X_test_mat-X_train).^2;
d=sum(Z,1);%计算空间距离
[list,temp_index]=sort(d);%对空间距离排序并取标号
topK=temp_index(1:K);%前K个近邻点的标号
for a=1:K
class_topK(a)=class_train(topK(a));%前K个近邻点的类别
end
array=tabulate(class_topK);%计算前K个近邻点各类别出现的频数等
[~,xuhao]=max(array(:,2));%找出最大频数和频数对应的序号
class_judge(i)=array(xuhao,1);%依照最大频数序号去找类别,确定该测试集的类别
end
end
在KNN法中,田字特征提取识别率(50%~60%)远低于所有特征的识别率(95%~96%),但是采集所有特征之后在进行KNN运算时,需要消耗大量的计算时间。
神经网络工具箱
clc
clear all
close all
%% 获取训练样本
Path = 'C:\杂七杂八杂货铺\模式识别\数字识别\手写体数字70000\';
path_train=strcat([Path,'训练图像\']);%训练样本文件夹的路径
file_struct=dir([path_train,'*.bmp']);%列出当前目录下符合'.bmp'的文件并放在文件结构体中
n_train=length(file_struct);%获取训练样本个数
for j=1:n_train
sample=imread([path_train,file_struct(j).name]);%打开第j个训练样本
X_train(:,j)=Get_Feature2(sample,28,28);%获取该样本特征,图片分辨率为20*20
class_train(j)=file_struct(j).name(1);%获取该训练样本的类别,为字符型
end
class_train=str2num(class_train(:))';%将字符型转化为数组
%% 获取测试样本
path_test=strcat([Path,'测试图像\']);%测试样本文件夹的路径
file_struct=dir([path_test,'*.bmp']);%列出当前目录下符合'.bmp'的文件并放在文件结构体中
n_test=length(file_struct);%获取测试样本个数
for j=1:n_test
sample=imread([path_test,file_struct(j).name]);%打开第j个训练样本
X_test(:,j)=Get_Feature2(sample,28,28);%获取该样本特征,图片分辨率为28*28
class_test(j)=file_struct(j).name(1);%获取该测试样本的类别
end
class_test=str2num(class_test(:))';%将字符型转化为数组
%% 将类别按照概率表示,训练样本类别变成10*60000
for i=1:n_train
switch class_train(:,i)
case 0
class(:,i)=[1 0 0 0 0 0 0 0 0 0]';
case 1
class(:,i)=[0 1 0 0 0 0 0 0 0 0]';
case 2
class(:,i)=[0 0 1 0 0 0 0 0 0 0]';
case 3
class(:,i)=[0 0 0 1 0 0 0 0 0 0]';
case 4
class(:,i)=[0 0 0 0 1 0 0 0 0 0]';
case 5
class(:,i)=[0 0 0 0 0 1 0 0 0 0]';
case 6
class(:,i)=[0 0 0 0 0 0 1 0 0 0]';
case 7
class(:,i)=[0 0 0 0 0 0 0 1 0 0]';
case 8
class(:,i)=[0 0 0 0 0 0 0 0 1 0]';
case 9
class(:,i)=[0 0 0 0 0 0 0 0 0 1]';
end
end
%% 测试
class_judge_temp=sim(net1,X_test);
for i=1:n_test
[~,index]=max(class_judge_temp(:,i));
class_judge(i)=index-1;
end
error=class_judge-class_test;
ro=(nnz(error)/n_test)*100;
disp(strcat('错误率为',num2str(ro),'%'));
在测试的代码前,需要手动点击神经网络的拟合工具箱,由于数字识别不涉及深度学习,所以使用工具箱完成操作(PS:好像工具箱可改的参数并不多,只能用一个隐含层,只能修改隐含层个数,好在默认值也能拟合的很好),这里设置了128个隐含层神经元,10个输出层神经元,准确率大概能达到94%左右,用时相对较短。