1. 程式人生 > 其它 >【手寫數字識別】基於matlab GUI BP神經網路手寫數字識別【含Matlab原始碼 1118期】

【手寫數字識別】基於matlab GUI BP神經網路手寫數字識別【含Matlab原始碼 1118期】

一、簡介

1 概述
BP(Back Propagation)神經網路是1986年由Rumelhart和McCelland為首的科研小組提出,參見他們發表在Nature上的論文 Learning representations by back-propagating errors 。

BP神經網路是一種按誤差逆傳播演算法訓練的多層前饋網路,是目前應用最廣泛的神經網路模型之一。BP網路能學習和存貯大量的 輸入-輸出模式對映關係,而無需事前揭示描述這種對映關係的數學方程。它的學習規則是使用最速下降法,通過反向傳播來不斷 調整網路的權值和閾值,使網路的誤差平方和最小。

2 BP演算法的基本思想
上一次我們說到,多層感知器在如何獲取隱層的權值的問題上遇到了瓶頸。既然我們無法直接得到隱層的權值,能否先通過輸出層得到輸出結果和期望輸出的誤差來間接調整隱層的權值呢?BP演算法就是採用這樣的思想設計出來的演算法,它的基本思想是,學習過程由訊號的正向傳播與誤差的反向傳播兩個過程組成。
正向傳播時,輸入樣本從輸入層傳入,經各隱層逐層處理後,傳向輸出層。若輸出層的實際輸出與期望的輸出(教師訊號)不符,則轉入誤差的反向傳播階段。
反向傳播時,將輸出以某種形式通過隱層向輸入層逐層反傳,並將誤差分攤給各層的所有單元,從而獲得各層單元的誤差訊號,此誤差訊號即作為修正各單元權值的依據。
這兩個過程的具體流程會在後文介紹。

BP演算法的訊號流向圖如下圖所示

3 BP網路特性分析——BP三要素
我們分析一個ANN時,通常都是從它的三要素入手,即
1)網路拓撲結構;
2)傳遞函式;
3)學習演算法。

每一個要素的特性加起來就決定了這個ANN的功能特性。所以,我們也從這三要素入手對BP網路的研究。
3.1 BP網路的拓撲結構
上一次已經說了,BP網路實際上就是多層感知器,因此它的拓撲結構和多層感知器的拓撲結構相同。由於單隱層(三層)感知器已經能夠解決簡單的非線性問題,因此應用最為普遍。三層感知器的拓撲結構如下圖所示。
一個最簡單的三層BP:

3.2 BP網路的傳遞函式
BP網路採用的傳遞函式是非線性變換函式——Sigmoid函式(又稱S函式)。其特點是函式本身及其導數都是連續的,因而在處理上十分方便。為什麼要選擇這個函式,等下在介紹BP網路的學習演算法的時候會進行進一步的介紹。
單極性S型函式曲線如下圖所示。

雙極性S型函式曲線如下圖所示。

3.3 BP網路的學習演算法
BP網路的學習演算法就是BP演算法,又叫 δ 演算法(在ANN的學習過程中我們會發現不少具有多個名稱的術語), 以三層感知器為例,當網路輸出與期望輸出不等時,存在輸出誤差 E ,定義如下




下面我們會介紹BP網路的學習訓練的具體過程。

4 BP網路的訓練分解
訓練一個BP神經網路,實際上就是調整網路的權重和偏置這兩個引數,BP神經網路的訓練過程分兩部分:

前向傳輸,逐層波浪式的傳遞輸出值;
逆向反饋,反向逐層調整權重和偏置;
我們先來看前向傳輸。
前向傳輸(Feed-Forward前向反饋)
在訓練網路之前,我們需要隨機初始化權重和偏置,對每一個權重取[ − 1 , 1 ] [-1,1][−1,1]的一個隨機實數,每一個偏置取[ 0 , 1 ] [0,1][0,1]的一個隨機實數,之後就開始進行前向傳輸。

神經網路的訓練是由多趟迭代完成的,每一趟迭代都使用訓練集的所有記錄,而每一次訓練網路只使用一條記錄,抽象的描述如下:

while 終止條件未滿足:
    for record:dataset:
        trainModel(record)



4.1 逆向反饋(Backpropagation)


4.2 訓練終止條件
每一輪訓練都使用資料集的所有記錄,但什麼時候停止,停止條件有下面兩種:
設定最大迭代次數,比如使用資料集迭代100次後停止訓練
計算訓練集在網路上的預測準確率,達到一定門限值後停止訓練

5 BP網路執行的具體流程
5.1 網路結構
輸入層有n nn個神經元,隱含層有p pp個神經元,輸出層有q qq個神經元。
5.2 變數定義








第九步:判斷模型合理性
判斷網路誤差是否滿足要求。
當誤差達到預設精度或者學習次數大於設計的最大次數,則結束演算法。
否則,選取下一個學習樣本以及對應的輸出期望,返回第三部,進入下一輪學習。

6 BP網路的設計
在進行BP網路的設計是,一般應從網路的層數、每層中的神經元個數和啟用函式、初始值以及學習速率等幾個方面來進行考慮,下面是一些選取的原則。
6.1 網路的層數
理論已經證明,具有偏差和至少一個S型隱層加上一個線性輸出層的網路,能夠逼近任何有理函式,增加層數可以進一步降低誤差,提高精度,但同時也是網路 複雜化。另外不能用僅具有非線性啟用函式的單層網路來解決問題,因為能用單層網路解決的問題,用自適應線性網路也一定能解決,而且自適應線性網路的 運算速度更快,而對於只能用非線性函式解決的問題,單層精度又不夠高,也只有增加層數才能達到期望的結果。
6.2 隱層神經元的個數
網路訓練精度的提高,可以通過採用一個隱含層,而增加其神經元個數的方法來獲得,這在結構實現上要比增加網路層數簡單得多。一般而言,我們用精度和 訓練網路的時間來恆量一個神經網路設計的好壞:
(1)神經元數太少時,網路不能很好的學習,訓練迭代的次數也比較多,訓練精度也不高。
(2)神經元數太多時,網路的功能越強大,精確度也更高,訓練迭代的次數也大,可能會出現過擬合(over fitting)現象。
由此,我們得到神經網路隱層神經元個數的選取原則是:在能夠解決問題的前提下,再加上一兩個神經元,以加快誤差下降速度即可。

6.3 初始權值的選取
一般初始權值是取值在(−1,1)之間的隨機數。另外威得羅等人在分析了兩層網路是如何對一個函式進行訓練後,提出選擇初始權值量級為s√r的策略, 其中r為輸入個數,s為第一層神經元個數。

6.4 學習速率
學習速率一般選取為0.01−0.8,大的學習速率可能導致系統的不穩定,但小的學習速率導致收斂太慢,需要較長的訓練時間。對於較複雜的網路, 在誤差曲面的不同位置可能需要不同的學習速率,為了減少尋找學習速率的訓練次數及時間,比較合適的方法是採用變化的自適應學習速率,使網路在 不同的階段設定不同大小的學習速率。

6.5 期望誤差的選取
在設計網路的過程中,期望誤差值也應當通過對比訓練後確定一個合適的值,這個合適的值是相對於所需要的隱層節點數來確定的。一般情況下,可以同時對兩個不同 的期望誤差值的網路進行訓練,最後通過綜合因素來確定其中一個網路。

7 BP網路的侷限性
BP網路具有以下的幾個問題:

(1)需要較長的訓練時間:這主要是由於學習速率太小所造成的,可採用變化的或自適應的學習速率來加以改進。
(2)完全不能訓練:這主要表現在網路的麻痺上,通常為了避免這種情況的產生,一是選取較小的初始權值,而是採用較小的學習速率。
(3)區域性最小值:這裡採用的梯度下降法可能收斂到區域性最小值,採用多層網路或較多的神經元,有可能得到更好的結果。

8 BP網路的改進
P演算法改進的主要目標是加快訓練速度,避免陷入區域性極小值等,常見的改進方法有帶動量因子演算法、自適應學習速率、變化的學習速率以及作用函式後縮法等。 動量因子法的基本思想是在反向傳播的基礎上,在每一個權值的變化上加上一項正比於前次權值變化的值,並根據反向傳播法來產生新的權值變化。而自適應學習 速率的方法則是針對一些特定的問題的。改變學習速率的方法的原則是,若連續幾次迭代中,若目標函式對某個權倒數的符號相同,則這個權的學習速率增加, 反之若符號相反則減小它的學習速率。而作用函式後縮法則是將作用函式進行平移,即加上一個常數。

二、原始碼

function varargout = findimg(varargin)
% FINDIMG MATLAB code for findimg.fig
%      FINDIMG, by itself, creates a new FINDIMG or raises the existing
%      singleton*.
%
%      H = FINDIMG returns the handle to a new FINDIMG or the handle to
%      the existing singleton*.
%
%      FINDIMG('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in FINDIMG.M with the given input arguments.
%
%      FINDIMG('Property','Value',...) creates a new FINDIMG or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before findimg_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to findimg_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help findimg

% Last Modified by GUIDE v2.5 23-Apr-2021 16:06:05

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @findimg_OpeningFcn, ...
                   'gui_OutputFcn',  @findimg_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before findimg is made visible.
function findimg_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to findimg (see VARARGIN)

% Choose default command line output for findimg
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes findimg wait for user response (see UIRESUME)
% uiwait(handles.figure1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%定義全域性變數
global ButtonDown pos1;
ButtonDown = [];
pos1 = [];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% --- Outputs from this function are returned to the command line.
function varargout = findimg_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;
axis([0 250 0 250]);

% --- Executes during object creation, after setting all properties.
function axes1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to axes1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: place code in OpeningFcn to populate axes1
%取消顯示axes的座標軸
set((hObject),'xTick',[]);
set((hObject),'yTick',[]);

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[f,p]=uiputfile({'*.jpg'},'儲存檔案');  %儲存所畫的圖
str=strcat(p,f);
pix=getframe(handles.axes1);
imwrite(pix.cdata,str,'jpg')


% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cla(handles.axes1);   %清楚axes中所畫的影象

% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
pix=getframe(handles.axes1);
imwrite(pix.cdata,'imgtest.jpg');
newimage = imread('imgtest.jpg');           %儲存新畫的數字

newimgResult = identify(newimage) ;                  %通過識別函式進行比較
Result = BpRecognize(newimgResult);
msgbox(num2str(Result),'識別結果','help');



% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
BpTrain();
msgbox('Finish Train','提示','modal');




% --- Executes on mouse press over figure background, over a disabled or
% --- inactive control, or over an axes background.
function figure1_WindowButtonDownFcn(hObject, eventdata, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%滑鼠按下事件
global ButtonDown pos1;  
if(strcmp(get(gcf,'SelectionType'),'normal'))%判斷滑鼠按下的型別,normal為左鍵  
    ButtonDown=1;  
    pos1=get(handles.axes1,'CurrentPoint');%獲取座標軸上滑鼠的位置  
end  
function [] = BpTrain()
%UNTITLED5 Summary of this function goes here
%   Detailed explanation goes here

clear all;
clc

ctime = datestr(now, 30);%取系統時間
tseed = str2num(ctime((end - 5) : end)) ;%將時間字元轉換為數字
rand('seed', tseed) ;%設定種子,若不設定種子則可取到偽隨機數

load Data2;  %資料有10類資料,每類20行25列,有4列是標籤。共200*29 
c = 0;
data = [];
for i = 1:10
    for j = 1:20
        c = c + 1;
        data(c,:) = pattern(i).feature(j,:);
    end
end
 
%=============訓練資料=============
Data = data(1:20, 1:25);
Data = [ Data ; data(21:40, 1:25)];
Data = [ Data ; data(41:60, 1:25)];   
Data = [ Data ; data(61:80, 1:25)];
Data = [ Data ; data(81:100, 1:25)];
Data = [ Data ; data(101:120, 1:25)];
Data = [ Data ; data(121:140, 1:25)];
Data = [ Data ; data(141:160, 1:25)];
Data = [ Data ; data(161:180, 1:25)];
Data = [ Data ; data(181:200, 1:25)];

%0標籤
Data(1:20, 26)   = 0;
Data(1:20, 27)   = 0;
Data(1:20, 28)   = 0;
Data(1:20, 29)   = 0;
%1標籤
Data(21:40, 26)   = 0;
Data(21:40, 27)   = 0;
Data(21:40, 28)   = 0;
Data(21:40, 29)   = 1;

Data(41:60, 26)   = 0;
Data(41:60, 27)   = 0;
Data(41:60, 28)   = 1;
Data(41:60, 29)   = 0;

Data(61:80, 26)   = 0;
Data(61:80, 27)   = 0;
Data(61:80, 28)   = 1;
Data(61:80, 29)   = 1;

Data(81:100, 26)   = 0;
Data(81:100, 27)   = 1;
Data(81:100, 28)   = 0;
Data(81:100, 29)   = 0;

Data(101:120, 26)   = 0;
Data(101:120, 27)   = 1;
Data(101:120, 28)   = 0;
Data(101:120, 29)   = 1;

Data(121:140, 26)   = 0;
Data(121:140, 27)   = 1;
Data(121:140, 28)   = 1;
Data(121:140, 29)   = 0;

Data(141:160, 26)   = 0;
Data(141:160, 27)   = 1;
Data(141:160, 28)   = 1;
Data(141:160, 29)   = 1;

Data(161:180, 26)   = 1;
Data(161:180, 27)   = 0;
Data(161:180, 28)   = 0;
Data(161:180, 29)   = 0;

Data(181:200, 26)   = 1;
Data(181:200, 27)   = 0;
Data(181:200, 28)   = 0;
Data(181:200, 29)   = 1;

DN = size(Data, 1);

%輸入層結點數
S1N = 25;

%第二層結點數
S2N = 50;

%輸出層結點數
S3N = 4;

%學習率
sk = 0.5;


%隨機初始化各層的W和B
W2 = -1 + 2 .* rand(S2N, S1N);
B2 = -1 + 2 .* rand(S2N, 1);

W3 = -1 + 2 .* rand(S3N, S2N);
B3 = -1 + 2 .* rand(S3N, 1);

%資料樣本下標
di = 1; 


for i=1:50000
    
    
    %第三層輸出
    n3 = W3 * a2 + B3;
    a3 = Logsig(n3);   %第三層傳輸函式為logsig
    
    %計算輸出層誤差
    e  = t - a3;
    err = (e') * e;
    
    Fd3 = diag((1 - a3) .* a3);
    S3 = -2 * Fd3 * e;
    
    Fd2 = diag((1 - a2) .* a2);
    S2 = Fd2 * (W3') * S3;
    
    W3 = W3 - sk*S3*(a2'); %梯度下降步長
    B3 = B3 - sk*S3;
    
    W2 = W2 - sk*S2*(a1');
    B2 = B2 - sk*S2;
end
msgbox(num2str(err),'輸出層誤差','help');
save('W2.mat','W2');
save('W3.mat','W3');
save('B2.mat','B2');
save('B3.mat','B3');


end



三、執行結果










四、備註

版本:2014a

完整程式碼或代寫加QQ1564658423