MATLAB--基于BP神经网络的手写数字识别
MATLAB–基于BP神經網絡的手寫數字識別
在干活的過程中整理下來的,希望對大家有幫助。
手寫數字識別技術作為圖像處理和模式識別中的研究熱點,在大規模數據統計(如行業年檢、人口普查等)、票據識別、財務報表、郵件分揀等方面有著廣泛的應用。目前手寫數字識別技術也有很多種實現方法,這里介紹與本章內容相關的一種基于BP神經網絡的手寫數字識別方法。該方法的基本思想來源于以下兩方面:一是手寫數字圖片中黑色像素點和白色像素點之間的空間編排關系構成了我們看到的數字,也就是說圖片像素點的空間排布和輸出的識別結果之間存在著非線性的映射關系。二是BP神經網絡剛好就能解決非線性映射的數學建模問題。如果對像素點空間排布與輸出數字之間的關系進行學習、訓練,建立有效的人工神經網絡,就可對再次給出的手寫數字圖片進行識別,輸出識別結果。
手寫數字的識別就是利用計算機自動識別人手寫在紙張上的阿拉伯數字,如果輸入以下手寫數字圖片,則計算機輸出對應識別結果為:0、1、2、3、4、5、6、7、8、9。
進行手寫數字識別時,先要對讀取圖片進行預處理,包括去噪、二值化等,再進行特征提取。特征提取的方法很多,這里采用一種簡單的特征提取方法,即統計每個小區域中圖像像素所占百分比作為特征數據。提取特征后再創建、訓練BP神經網絡模型,最后用測試數據進行測試。
要進行手寫數字識別這個實際問題,第一步就是建立手寫數字的模型。
1.手寫數字識別非線性數學的模型建立
BP神經網絡即誤差反向傳播神經網絡,可解決有教師訓練的非線性數學建模問題。模型的建立主要包括:BP神經網絡的創建、BP神經網絡的訓練以及BP神經網絡的測試三步。
創建BP神經網絡前首先要確定網絡的輸入、輸出。
(1)BP神經網絡的輸入、輸出
BP神經網絡的輸入數據是手寫數字樣本經過預處理和特征提取后的數據。而為了BP神經網絡的輸入,我們肯定要先讀入手寫數字的樣本,這里我們使用最通用的MNIST手寫數字庫,這個數據庫直接在百度上就能下載到,該數據庫包含0-9這10個數字的手寫體,放在10個文件夾里,文件夾的名稱對應存放的手寫數字圖片的數字,每個數字500張,每張圖片的像素統一為28×28。
下面介紹用MATLAB程序實現讀入手寫數字的樣本,這里注意,我將手寫數字的樣本放在和MATLAB 程序同根目錄的文件夾里,文件夾的名稱對應存放的手寫數字圖片的數字,也就是說當前文件夾如下圖所示。畫紅線的文件夾就是我們要讀入的手寫數字的樣本,以數字0為例,數據庫中圖片的名稱如下圖所示。
這樣就可以用在主程序中調用read_train子函數讀入手寫數字的樣本了。
這里需要說明的是,我的MATLAB程序來自于:
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/zxm_jimin/article/details/87937652
————————————————
版權聲明:本文為CSDN博主「zxm_」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zxm_jimin/article/details/87937652
這里主要介紹我在學習這段MALTLAB程序的時候,學到的內容。
main.m的MATLAB如下。
clc; clear all; close all; %% 讀取圖像 root='./data'; img=read_train(root); %% 提取特征 img_feature=feature_lattice(img); %% 構造標簽 class=10; numberpclass=500; ann_label=zeros(class,numberpclass*class); ann_data=img_feature; for i=1:classfor j=numberpclass*(i-1)+1:numberpclass*iann_label(i,j)=1;end end%% 選定訓練集和測試集 k=rand(1,numberpclass*class); [m,n]=sort(k); ntraindata=4500; ntestdata=500; train_data=ann_data(:,n(1:ntraindata)); test_data=ann_data(:,n(ntraindata+1:numberpclass*class)); train_label=ann_label(:,n(1:ntraindata)); test_label=ann_label(:,n(ntraindata+1:numberpclass*class)); %% BP神經網絡創建,訓練和測試 net=network_train(train_data,train_label); predict_label=network_test(test_data,net); %% 正確率計算 [u,v]=find(test_label==1); label=u'; error=label-predict_label; accuracy=size(find(error==0),2)/size(label,2)read_train子函數的MATLAB如下。
function [imglist] = read_train(root) % ni為讀取圖片張數,n為文件夾數目 %========讀取文件夾========% out_Files = dir(root);%展開 tempind=0; imglist=cell(0); n=length(out_Files); %========讀取文件========% for i = 1:nif strcmp(out_Files(i).name,'.')|| strcmp(out_Files(i).name,'..')elserootpath=strcat(root,'/',out_Files(i).name);in_filelist=dir(rootpath);ni=length(in_filelist);for j=1:niif strcmp(in_filelist(j).name,'.')|| strcmp(in_filelist(j).name,'..')|| strcmp(in_filelist(j).name,'Desktop_1.ini')|| strcmp(in_filelist(j).name,'Desktop_2.ini')elsetempind=tempind+1;imglist{tempind}=imread(strcat(rootpath,'/',in_filelist(j).name));endendend end end在這個子程序的4行dir函數可以獲得指定文件夾下的所有子文件夾和文件,并存放在文件結構體數組中。返回值out_Files是一個struct—結構體,我們可以在工作區查看它,如下圖。
在第10行函數strcmp()用于做字符串的比較,
如調用格式為:TF=strcmp(s1,s2);
則如果字符串s1和s2是一致的,則返回值TF=1,否則,TF=0。
在第12行函數strcat(),用于橫向連接字符串。如調用格式為:combinedStr= strcat(s1, s2, …, sN),就是將數組 s1,s2,…,sN 水平地連接成單個字符串,并保存于變量combinedStr中。在這里就是講文件夾的路徑和文件夾名橫向連接。
也就是說從10到13行,就是對于每一個文件夾中文件讀入in_filelist這個結構體。而在n_filelist這個結構體中,比如對于”9”這個文件夾,每個圖片的名稱就是9_1,9_2,等等,從下邊的一小塊截圖就可以看出來。
從15到21行,同樣用到了函數strcmp()和函數strcat(),然后調用imread,也就是根據每個文件的路徑及文件名,依次讀入到imglist這個cell-元胞數組中,從而完成5000張圖片的讀入。
在我們這個例子預處理主要是圖像的二值化,特征提取方法主要采用粗網格特征提取。粗網格特征提取方法是指將二值化后的圖像大小統一為50×50,再等分成5×5個網格,每個網格包含100像素,然后依次統計每個網格中黑色像素點的數量,從而得到一個1×25的特征向量。
也就是說5000張手寫數字圖片的特征向量即為BP神經網絡的輸入(一個5000×25的矩陣),而其對應的真實數字為BP神經網絡的輸出(一個5000×1的向量)。
圖像預處理及特征提取的MATLAB通過在主程序中調用feature_lattice子函數來實現,其MATLAB如下。
首先該子程序的第5行,在MATLAB中將圖像轉換為二值圖像,調用MATLAB中的im2bw函數。
對于灰度圖像,調用的格式如下。
bw=im2bw(I,level);
level空著的話,默認是0.5。level一般使用graythresh函數來計算,graythresh函數是MATLAB中自帶的,函數功能:使用最大類間方差法找到圖片的一個合適的閾值–level,
第6行,調用imresize將圖像大小統一為50×50。
接著,從8-13行,用嵌套的for循環語句,將圖像分成5×5個網格,也就是說每個網格是10×10個像素點,然后統計每個網格中不為0的像素點的數量。
15行100-left就是每個網格中為0的像素點(黑色)的數量
第16行通過一個轉置操作,保證每個圖像的特征是一個列向量。
這樣通過調用feature_lattice子函數,每一張圖片都有1×25的特征向量。
提取完特征后,將數據打上標簽,這段程序是主程序的10-18行。
因為數據一共10類,每類500張圖片,先初始化一個用于存放標簽的矩陣,這個矩陣大小就是10×(10×500)。
我用圖畫了一下這個存放標簽的矩陣是什么樣。
如果一個圖片的標簽是[1;0;0;0;0;0;0;0;0;0],那么這張圖片上的數字是1,如果標簽是[0;1;0;0;0;0;0;0;0;0], 那么這張圖片上的數字是2,以此類推。
因為我們數字圖片是根據文件名讀入的,這樣圖片上的數字、文件名和標簽就都對應上了。
最后隨機選取4500張圖片作為訓練樣本,500張圖片作為測試樣本。MATLAB是主程序的21-28行。提取的特征在ann_data中,也就是BP神經網絡的輸入,標簽在ann_label中,也就是BP神經網絡的輸入輸出。這樣,我們就將BP神經網絡的輸入、輸出準備好了。就可以開始創建BP神經網絡了。
(2)BP神經網絡的創建
BP神經網絡具有輸入層、隱含層(隱藏層)和輸出層的三層結構。其中,隱含層可以有一個或兩個及以上,這里采用具有一個隱含層的基本BP網絡模型,隱含層神經元個數選取25個,激勵函數選取默認的Sigmoid函數,學習速率設為0.1,網絡訓練函數選取默認的Trainlm,網絡目標誤差設為0.001。隨機抽取4500張圖片提取的特征矩陣作為訓練樣本的輸入,計算隱含層和輸出層輸出、誤差,更新網絡權值。當誤差達到設定目標時,網絡的學習過程就結束。在main.m中調用network_train子函數,其MATLAB程序如下。
function net = network_train(train_data,train_label ) % BP網絡訓練 % 初始化網絡結構 layer=30;%隱含層個數 net=newff(train_data,train_label,layer);%創建網絡 net.trainParam.epochs=10;%迭代次數 net.trainParam.lr=0.2;%學習率 net.trainParam.goal=0.001;%誤差參數 net.trainFcn='trainrp';%訓練方法 % 網絡訓練 net=train(net,train_data,train_label); end這樣我們得到了訓練好噠神經網絡net。
(3)神經網絡的測試
訓練好神經網絡之后,用隨機抽取的500張手寫數字圖片對網絡進行測試,輸入特征向量,計算隱含層和輸出層輸出,得到最后測試的數據。同時計算每個數字的正確率和全體的正確率。在主程序中調用network_test子函數,其MATLAB程序如下。
function out = network_test(test_data,net) % 輸入:測試數據的特征和真值。輸出:測試數據的label以及誤差圖 % BP網絡預測 an=sim(net,test_data); for i=1:length(test_data)out(i)=find(an(:,i)==max(an(:,i))); end end測試數據的標簽存在了predict_label中,可以在工作區雙擊predict_label,打開查看。如下所示。
正確率在命令行窗口可以看到。
另外,在網絡訓練的性能等可以點擊下圖中的按鈕進行查看。這部分在上一篇介紹了,這里就不贅述了。
手寫數字的數據集,data,我存放在百度網盤里了。
總結
以上是生活随笔為你收集整理的MATLAB--基于BP神经网络的手写数字识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 绿竹生物再冲刺港交所上市:暂未商业化,孔
- 下一篇: 福州新投格兰云天国际酒店开启试运营;爱彼