基於BP人工神經網絡的數字字符識別及MATLAB實現

應用背景:在模式識別中,有一種高實用性的分類方法,就是人工神經網絡,它被成功應用於智能機器人、自動控制、語音識別、預測估計、生物、醫學、經濟等領域,解決了許多其他分類方法難以解決的實際問題。這得益於神經網絡的模型比較多,可針對不同的問題使用相應的神經網絡模型,這裏使用BP神經網絡解決手寫的數字字符識別問題。

BP神經網絡基本原理概述:這種網絡模型利用誤差反向傳播訓練算法模型,能夠很好地解決多層網絡中隱含層神經元連接權值係數的學習問題,它的特點是信號前向傳播、誤差反向傳播,簡稱BP(Back  Propagation)神經網絡。BP學習算法的基本原理是梯度最快下降法,即通過調整權值使網絡總誤差最小,在信號前向傳播階段,輸入信號經輸入層處理再經隱含層處理最後傳向輸出層處理;在誤差反向傳播階段,將輸出層輸出的信號值與期望輸出信號值比較得到誤差,若誤差較大則把誤差信號傳回隱含層直至輸入層,在各層神經元中使用誤差信號修改權值係數,之後進入下一輪迭代,如此循環直至誤差最小,實際輸出信號值接近期望輸出信號值。下圖爲三層BP神經網絡模型:

                                                                                                          

它包括輸入層、1層隱含層、輸出層,是一種最簡單的BP神經網絡模型。用這個模型解決手寫的數字字符識別問題的MATLAB代碼如下:

%三層BP神經網絡應用於字符識別
clc;  
clear all;  
close all;  
Files= dir('C:\Program Files\MATLAB\R2013a\bin\work\CNN數字字符識別1\data');  
LengthFiles= length(Files);  
%========讀取存在data文件夾下0-10個文件的全部圖片========%  
for i = 3:LengthFiles;     
    if strcmp(Files(i).name,'.')||strcmp(Files(i).name,'..')  
    else  
       rootpath=strcat('C:\Program Files\MATLAB\R2013a\bin\work\CNN數字字符識別1\data','\',Files(i).name);
       filelist=dir(rootpath);  
       [filenum,temp]=size(filelist);  
       count=0;  
       imglist=cell(0);  
       for j=1:filenum      
           if strcmp(filelist(j).name,'.')|| strcmp(filelist(j).name,'..')||strcmp(filelist(j).name,'Desktop_1.ini')||strcmp(filelist(j).name,'Desktop_2.ini')         
           else  
              count=count+1;  
            imglist{count}=imread(strcat(rootpath,'/',filelist(j).name));  
           end  
       end
       number{i-2}=imglist;
    end   
end  
charvec1=zeros(35,5000);  
%========對讀取的圖片預處理(二值化-裁剪-特徵提取)========%  
 for i=1:10  
     for j=1:500  
        I1=number{1,i}{1,j}; %第i個文件夾的第j張圖 
        img_bw = im2bw(I1,graythresh(I1));  %灰度圖轉二值圖
        bw_7050=imresize(img_bw,[70,50]);
        %提取特徵統計每個小區域中圖像象素所佔百分比作爲特徵數據
        for cnt=1:7
            for cnt2=1:5
              Atemp=sum(bw_7050(((cnt*10-9):(cnt*10)),((cnt2*10-9):(cnt2*10))));%10*10box對矩陣所有元素求和,共100個像素
              lett((cnt-1)*5+cnt2)=sum(Atemp);%按行求和
            end
        end
        lett=((100-lett)/100);
        lett=lett';
        charvec1(:,(i-1)*500+j)=lett;  
     end  
 end  
 %每個樣本對應的類標籤向量
label=[zeros(1,500),zeros(1,500)+1,...  
   zeros(1,500)+2,zeros(1,500)+3,zeros(1,500)+4,zeros(1,500)+5,zeros(1,500)+6,zeros(1,500)+7,zeros(1,500)+8,zeros(1,500)+9];  
charvec1(36,:)=label;  
%輸入輸出數據  
input=charvec1(1:35,:);  
output1=charvec1(36,:); %目標輸出類標籤    
%把輸出從1維變成10維  
for i=1:5000  
    switch output1(i)  
        case 0  
            output(:,i)=[1 0 0 0 0 0 0 0 0 0]';  
        case 1  
            output(:,i)=[0 1 0 0 0 0 0 0 0 0]';  
        case 2  
            output(:,i)=[0 0 1 0 0 0 0 0 0 0]';  
        case 3  
            output(:,i)=[0 0 0 1 0 0 0 0 0 0]';  
        case 4  
            output(:,i)=[0 0 0 0 1 0 0 0 0 0]';  
        case 5  
            output(:,i)=[0 0 0 0 0 1 0 0 0 0]';  
        case 6  
            output(:,i)=[0 0 0 0 0 0 1 0 0 0]';  
        case 7  
            output(:,i)=[0 0 0 0 0 0 0 1 0 0]';  
        case 8  
            output(:,i)=[0 0 0 0 0 0 0 0 1 0]';  
        case 9  
            output(:,i)=[0 0 0 0 0 0 0 0 0 1]';  
    end  
end    
 %=========BP神經網絡創建,訓練和測試========%   
%% 網絡結構初始化  
innum=35;  %輸入層的輸入維數
midnum=80;  %中間隱含層的維數
outnum=10;  %輸出層的輸出維數 
%提取450個樣本爲訓練樣本
input_train=input(:,1:450); 
T=output(:,1:450); 
%權值初始化  
Wij=rands(midnum,innum);%輸入到隱含層的權重向量  
b1=rands(midnum,1);  %偏值或閾值
Wki=rands(outnum,midnum);%隱含層到輸出層的權重向量  
b2=rands(outnum,1); %偏值或閾值 
Ir=0.05;err_goal=0.001;  %Ir爲學習速率,err_goal爲期望誤差最小值
max_epoch=1000;a=0.9;  %訓練的最大次數,a爲慣性系數  
Oi=0;Ok=0;  %初始化隱含層的輸出值爲0;初始化輸出層的輸出值爲0
[M,N]=size(input_train);
Wij0=zeros(midnum,M);Wki0=zeros(outnum,midnum);
%第一階段,模型訓練期:根據加權係數Wij,Wki,對給定的樣本計算輸出
for epoch=1:max_epoch
    %計算隱含層各神經元節點輸出
    for i=1:N
        NETi(:,i)=Wij*input_train(:,i)+b1; 
    end
    for j=1:N
        for i=1:midnum
                 Oi(i,j)=1/(1+exp(double(-NETi(i,j))));%激勵函數
        end
    end 
    %計算輸出層各神經元節點輸出
    for i=1:N
         NETk(:,i)=Wki*Oi(:,i)+b2;
    end
    for i=1:N
        for k=1:outnum
                 Ok(k,i)=1/(1+exp(double(-NETk(k,i))));%激勵函數
        end
    end
    %計算誤差函數:方差    
    E=( (T-Ok)' * (T-Ok) );
    err=abs(E)>err_goal;
    if sum(sum(err))==0
       break;
    end
    %調整輸出層加權係數,引入慣性項即最近一次歷史權值,也就是上一次迭代的權值
    delta_k=Ok.*(1-Ok).*(T-Ok);
    W=Wki;
    Wki=Wki + Ir*delta_k*Oi' + a*(Wki-Wki0);
    Wki0=W;
    %調整隱含層加權係數,引入慣性項
    delta_i=Oi.*(1-Oi).*(delta_k' * Wki)';
    W=Wij;
    Wij=Wij+Ir*delta_i* input_train'+ a*(Wij-Wij0);
    Wij0=W;
end
epoch   %顯示訓練次數
%第二階段,測試期:根據訓練好的加權係數Wij,Wki,對給定的輸入計算輸出
input_test=input(:,451);%給定輸入
X1=input_test;
output_test=output(:,451);
[M,N]=size(X1);
Oi=0;Ok=0;
%計算隱含層各神經元節點輸出
for i=1:N
	 NETi1(:,i)=Wij*X1(:,i)+b1; 
end
for j=1:N
        for i=1:midnum           
            Oi(i,j)=1/(1+exp(double(-NETi1(i,j))));%激勵函數
        end
end
%計算輸出層各神經元節點輸出
for i=1:N
    NETk1(:,i)=Wki*Oi(:,i)+b2;  
end
for i=1:N
        for k=1:outnum
            Ok(k,i)=1/(1+exp(double(-NETk1(k,i))));%激勵函數
        end
end
output_test'    %顯示網絡輸出層的期望輸出
Ok'   %顯示網絡輸出層的實際輸出

程序中使用450張寫了數字“0”的圖片作爲訓練樣本以及1張寫了數字“0”的圖片作爲測試樣本,運行結果如下圖


從運行結果看,模型訓練了2次就成功,識別率高,爲0.99。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章