700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 基于matlab支持向量机SVM多分类手写体数字识别

基于matlab支持向量机SVM多分类手写体数字识别

时间:2021-08-16 19:12:40

相关推荐

基于matlab支持向量机SVM多分类手写体数字识别

此程序为本人模式识别大作业,参考了网上的代码,并进行了一定的修改,希望对大家有所帮助!

此代码主要参考了以下文章:

/Einperson/article/details/106769799?spm=1001..3001.5506

前面的大部分我都是以这篇文章为基础的,我在此写一些注释:

下载安装并配置LIBSVM工具箱、LIBSVM-FarutoUitimate工具箱,去B站找UP 中山大学王伟良 ,up有安装视频教程。up的视频里还有个SVM代码,挺详细的,真的很良心!!!

代码:

预处理函数设计

(1)先对手写体图像进行反色处理(即黑变白、白变黑),

(2)将此时的图像进行二值化处理(即将黑色变为1,白色变为0,也可能是相反的,这不重要,我偷个懒),

(3)是搜索整个图片中数字出现的位置(类似于图片裁剪,只留下手写字体的部分,可以大大降低图片数据量)

(4)将图片进行缩小,进一步减少数据量

%% sub function of pre-processing picfunction pic_preprocess = pic_preprocess(pic)% 图片预处理子函数%三原色图像反色处理pic = 255-pic;%设定阈值,将反色图像转成二值图像pic = im2bw(pic,0.4) ;%查找数字上所有像素点的行标y和列标x[y,x] = find(pic == 1);%截取包含完整数字的最小区域pic_preprocess = pic (min(y):max(y),min(x):max(x));%将截取的包含完整数字的最小区域图像转成20*20的标准化图像pic_preprocess = imresize(pic_preprocess, [20, 20]);

2.主函数编写

2.1.载入数据

(1)uigetfile函数可以弹出一个窗口用于选择训练样本,运行程序后,可自动出现

(2)后面内容代码注释解释的很清楚,我不再多讲

注:FileName{k}(n)函数可用于提取训练集图片名称上第n位符号,因为我所用到的训练图片格式img001.png这种,所以取其第6位,大家要按照自己实际的情况进行改动。

%% 载入训练数据%利用uigetfile函数交互式选取训练样本 ...是换行再度[FileName,PathName,FilterIndex]=uigetfile(...{'*.png';'*.bmp'},'请导入训练图片','*.png','MultiSelect','on');if ~FilterIndex %如果用户取消,则返回上一步return;endnum_train=length(FileName); % Filename是一个字符串数组 图片的个数TrainData=zeros(num_train,20*20); %生成训练样本,样本维度为20*20,由pic_preprocess函数决定TrainLabel=zeros(num_train,1); %生成训练样本标签for k=1:num_trainpic=imread([PathName,FileName{k}]);%逐个读入图片%pic是1200*900*3的数组,其中1200*900是图片的原始分辨率,3是三原色pic=pic_preprocess(pic);%将一幅图转为20*20个二进制数TrainData(k,:)=double(pic(:)');%单引号是将pic转一维数组,存放在TrainData的第K行if str2double(FileName{k}(5))~=0%如img010(即数字“9”的文件名)TrainLabel(k)=str2double(FileName{k}(5))*10+str2double(FileName{k}(6))-1; else%其他文件,如img001是数字“0”的文件名TrainLabel(k)=str2double(FileName{k}(6))-1; %文件名中第6个字符是该图片的数字endend

2.2. 建立支持向量机!!!

之前参考的代码用到了gaSVMcgForClass函数,但是这个函数需要设置GA相关参数,本人小白一个,搞不懂这些东西就放弃了这个函数。

也有代码用到了svmtrain函数,由于本人的matlab为b,已经将此函数删除建议我用fitsvm。之后我又去查找fitsvm,之后发现它只能实现二分类,多分类问题只能通过建立多个两两二分类(建立二分之m方个,m为类别数)。对于手写体数字识别问题,就要50个实在是太麻烦了。

之后我又找到了fitcecoc函数,此函数可以用来实现SVM多分类问题,真的超级nice!找到关于这个函数的例子还是通过mathwork搜索得来的,其中举得例子就是分类iris鸢尾花、ionosphere电离层数据,这里我直接照搬了他们的代码,,,本人小白,真的不太会这里,不知道怎么改可以,只是发现它可以运行成功,并且分类效果不错就直接使用了

(1)templateSVM函数可以建立一个SVM模板函数,其参数值为默认值,试了下其默认核函数应该为线性核函数,想要具体了解可mathwork自行搜索。

(2)fitcecoc函数(训练集,训练标签,'Learners',t,'ClassNames',{这里填你要分类的那几种标签名,按顺序噢});关于fitcecoc函数可自行查阅mathwork进行学习。

通过查找资料发现这里训练的是ECOC模型,具体我也不懂,感兴趣的朋友可以自行学习。

(3)使用crossval函数可以实现10折交叉验证(10折交叉验证:将数据集分成平均分成互斥的十份,轮流将其中9份做训练1份做验证,10次的结果的均值作为对算法精度的估计,一般还需要进行多次10折交叉验证求均值),以测试算法准确性。

SVM——n倍交叉验证:

/weixin_46345400/article/details/124358046?spm=1001..3001.5506

(4)通过kfoldLoss函数得到估计广义分类误差,误差越小说明分类器的泛化(泛化是指训练好的模型在前所未见的数据上的性能好坏)效果越好。

深入理解泛化:

/sc2079/article/details/103090727?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%B3%9B%E5%8C%96&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-103090727.142^v10^pc_search_result_control_group,157^v8^control&spm=1018.2226.3001.4187

%% 建立支持向量机t = templateSVM('Standardize',1,'KernelFunction','linear'); %创建SVM模板t;%templateSVM是fitcecoc函数中的SVM模板;%standardize:数据标准化,可用help查看templateSVM其他参数%训练该模型Mdl = fitcecoc(TrainData,TrainLabel,'Learners',t,'ClassNames',{'0','1','2','3','4','5','6','7','8','9'}); %验证该模型CVMdl = crossval(Mdl); %将模型进行交叉验证,平衡模型欠拟合和过拟合%显示结果oosLoss = kfoldLoss(CVMdl) %10折交叉验证得到的泛化误差 oosloss = 0.0750

2.3.载入测试样本

%% 载入测试样本[FileName,PathName,FilterIndex]=uigetfile( ...{'*.png';'*.bmp'},'请导入测试图片','*.png','MultiSelect','on');if ~FilterIndex %如果用户取消,则返回上一步return;endnum_test=length(FileName); %Filename是一个字符串数组TestData=zeros(num_test,20*20); %生成测试样本矩阵,维度为400TestLabel=zeros(num_test,1);%生成测试样本标签矩阵for k=1:num_testpic=imread([PathName,FileName{k}]); %逐个读图pic=pic_preprocess(pic); %将一幅图转为20*20个二进制数TestData(k,:)=double(pic(:)'); %单引号是将pic转一维数组,存放在TrainData的第K行if str2double(FileName{k}(5))~=0%如img010(即数字“9”的文件名)TestLabel(k)=str2double(FileName{k}(5))*10+str2double(FileName{k}(6))-1;elseTestLabel(k)=str2double(FileName{k}(6))-1; %文件名中第6个字符是该图片的数字endend

2.4.提取Test测试集中图片名称(这一步是为了后面显示判断错误的图片名称,不需要可以删掉)

%% 对Test图片名称提取fileFolder=fullfile('C:\Users\Test'); %引号内是需要遍历的路径,填绝对路径,然后保存在fileFolderdirOutput=dir(fullfile(fileFolder,'*.png'));%引号内是文件的后缀,写'.png'则读取后缀为'.png'的文件fileNames={dirOutput.name}; %将所有文件名,以矩阵形式按行排列,保存到fileNames中

2.5.对测试样本进行分类

predict函数的使用可以参考mathwork上官方解释,这里就不赘述了。

preTestLabel是通过SVM模型产生的预测标签,为cell型,如果要判断正确率就要与double型TestLabel进行比较,但是cell型不能直接与double型作比较,这里就是使用了preTestLabel=str2num(cell2mat(preTestLabel));来转换。

%% 对测试样本进行分类preTestLabel = predict(Mdl,TestData);preTestLabel=str2num(cell2mat(preTestLabel)); %将cell型preTestLabel转为double型,以供后面与测试样本标签进行比较right =0;%正确数量k=0; %错误数量for i=1:numel(TestLabel) if TestLabel(i)==preTestLabel(i) %统计正确数量right =right+1;elsek=k+1;error_name(k)=fileNames(i);%记录错误文件名endendtest_number=numel(TestLabel) rightaccuracy =right/numel(TestLabel) %测试样本正确率%accuracy = 0.9333error_name

结果:

对于SVM模型的建立那里本人还不是很明白应该怎么做,如果有比较了解的朋友欢迎评论区里讲解一下,非常感谢!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。