神經網絡原理及其c++實現


 

 

1引言

數字識別是模式識別領域 中的一個重要分支,數字識別一般通過特征匹配及特征判別的傳統方法進行處理。特征匹配通常適用於規范化的印刷體字符的識別,而 特征判別多用於手寫字符識別,這些方法還處於探索階段,識別率還比較低。隨着神經網絡技術的飛速發展,其本身具有的高度並行性、較強的自組織能力和容錯性、較好抑制噪聲干擾能力等特點,為快速准確地進行數字識別開辟了新的途徑。目前,對於指針式表而言,可以根據二值化后的指針指向來識別表盤的讀數,而對於某些特殊類型的表盤,由於沒有可判斷讀數的指針,只能通過表盤上的數字來讀取表盤數據,這無疑增大了識別的難度,這類表盤中數字識別就顯得格外重要。本文針對這種情況,在對待識別數字圖像進行預處理和特征提取的基礎上,利用粗糙集理論進行特征約簡,以減少神經網絡的規模和結構復雜度, 最后利用神經網絡進行儀表表盤的數字識別。

2數字識別的基本過程

本文數字圖像的識別過程[2]如圖1所示,主要包括獲取數字圖像、數字圖像預處理、特征提取、粗糙集特征約簡和神經網絡數字識別幾個階段:

clip_image003

圖1 數字識別過程

其中圖像預處理包括圖像灰度化,圖像二值化,自適應直方圖均衡,自適應中值濾波等。

clip_image005clip_image007

圖2 原始圖像和經過自適應直方圖均衡並且提取表盤圖像

自適應直方圖均衡解決了不同圖像光照不均等問題。但是該方法引入了類似椒噪聲,再用自適應中值濾波進行濾波,得到的圖像只剩下表盤區域。我們再用投影法便可得到每個數字所在的區域。我們把每個數字的小區域圖像等間隔的取點作為神經網絡的輸入樣本,訓練神經網絡,當樣本數量足夠多時,神經網絡訓練的參數也趨於穩定,再用測試樣本進行檢測我們訓練的結果。

clip_image009clip_image011

圖3 自適應中值濾波后的圖像和數字進行分割后的結果

3 bp神經網絡

Bp神經網絡結構有3層[4]:輸入層、隱含層、輸出層,如圖6所示。

clip_image013

圖4 三層BP網絡結構

3層BP神經網絡學習訓練過程主要由4部分組成:輸入模式順傳播(輸入模式由輸入層經隱含層向輸出層傳播計算)、輸出誤差逆傳播(輸出的誤差由輸出層經隱含層傳向輸入層)、循環記憶訓練(模式傳播與誤差逆傳播的計算過程反復交替循環進行)和學習結果判別(判定全局誤差是否趨向極值)。

下面具體介紹和分析用梯度下降法訓練BP神經網絡,在第1次輸入樣品(1=1,2,……,N)進行訓練時各個參數的表達及計算方法。

3.1確定參數

① 輸入向量為X=[x1,x2,…,xn]T(n—輸入層單元個數);

② 輸出向量Y=[y1,y2,…,yq]T(q—輸出層單元個數);

③ 希望輸出向量O=[o1,o2,…,oq]T;

④ 隱含層輸出向量B=[b1,b2,…,bp]T(p—隱含層單元個數);

⑤ 初始化輸入層至隱含層的連接權值

Wj=[wj1,wj2,…,wjt,…,wjn]T,j=1,2,…p;

初始化隱含層至輸出層的連接權值

Wk=[wk1,wk2,…,wkj,…,wkp]T,k=1,2,…q。
3.2輸入模式順序傳播。

這一過程主要是利用輸入模式求出它對應的實際輸出。

① 計算隱含層各神經元的激活值clip_image015
clip_image017(j=1,2,3…p) (1)

clip_image019為隱含層單元的閾值

clip_image021為輸出層至隱含層的連接權

② 激活函數用S型函數,即:

clip_image023 (2)

這里之所以選S型函數為BP神經網絡神經元的激活函數,是因為它是連續可微分的,而且更接近於生物神經元的信號輸出形式。

③ 計算隱含層j單元的輸出值:

clip_image025 (3)

閾值clip_image019[1]在學習過程中和權值一樣不斷被修改,閾值的作用反應在函數的輸出曲線上。

clip_image027

圖7 閾值的作用

④ 計算輸出層第k個單元的激活值clip_image029

clip_image031 (4)

clip_image033為隱含層至輸出層的權值

clip_image035輸出層單元閾值

⑤ 計算輸出層第k個單元的實際輸出值clip_image037

clip_image039 (t=1,2,3…q) (5)

clip_image041為S型激活函數。

3.3輸出誤差的傳播。

在上一步的模式順傳播計算中得到網絡的實際輸出值,當這些實際的輸出值與希望的輸出值不一樣時或者說誤差大於所限定的數值時,就要對網絡進行校正。
①輸出層的校正誤差為:

clip_image043 (k=1,2,3…q)

②隱含層各單元的校正誤差為:

clip_image045 (6)

③對於輸出層至隱含層連接權和輸出層閾值的校正量為:

clip_image047 (7)

α為學習系數,α>0。

clip_image049為隱含層j單元的輸出。

clip_image051為輸出層的校正誤差。

④隱含層至輸入層的校正量為:

clip_image053 (8)
clip_image055為隱含層j單元的校正誤差。

對於BP神經網絡輸入的每一組訓練模式,一般都要經過數百次甚至上萬次的循環記憶訓練,才能使網絡記住這一模式。這種循環記憶訓練實際上就是反復重復上面介紹的輸入模式。
判別的目的主要是檢查輸出誤差是否已經小到可以允許的程度。學習或者說訓練的過程是網絡全局誤差趨向於極小值的過程。


3.4各層神經元的選取

輸入層神經元的個數由輸入向量的維數確定,例如當我們每個數字圖像提取64個點時,那么輸入的神經元個數n就是64,輸出層的個數由數字分類個數決定,我們對數字1可以很容易的檢測出來剩下的0、2-9個數字共有9個數,所以分9類,故輸出神經元個數m為9,隱含層神經元個數由下式確定[5]:

clip_image057clip_image059 (9)

故可以取8到18的任意數,隱含層神經元的個數會影響計算量以及計算精度。

4.實驗

我們令學習率為0.8,迭代次數上限1000000次,精度0.01,取測試樣本輸入訓練好的神經網絡,寫好代碼:

#include"bpnet.h"

#define n 32 //輸入層神經元個數

#define mid_num 16 //隱含層神經元個數

#define out_num 9 //輸出層神經元個數

#define T 32 //樣本個數

#define in_num 2 //樣本個數

double v[mid_num][out_num]; //輸出層的權矩陣

double sita_h[mid_num]; //隱藏層閾值

double sita_o[out_num]; //輸出層閾值

double w[n][mid_num]; //輸出(隱藏)層的權矩陣

double delta_o[out_num]; //輸出層各聯結權的修改量組成的向量

double delta_h[mid_num]; //隱藏層各聯結權的修改量組成的向量

double hide_s[mid_num]; //隱藏層的激活值

double hide_o[mid_num]; //隱藏層的輸出值

double output_s[out_num]; //輸出層的激活值

double output_o[out_num]; //輸出層的輸出值

double input[T][n]; //輸入層的輸入向量

double output[T][out_num]; //期望的輸出值

double E; //誤差

double sigma=0.01; //精度控制參數

double alpha=0.8; //學習率

int M=1000000; //循環最大次數

//****初始化函數****//

void initialize()

{

int i,j;

for(i = 0; i < mid_num; i++)

{

hide_s[i] = 0;

hide_o[i] = 0;

delta_h[i] = 0;

sita_h[i] = rand() / ( RAND_MAX + 1.0 );

}

for(i = 0; i < out_num; i++)

{

sita_o[i] = rand() / ( RAND_MAX + 1.0 );

output_s[i] = 0;

output_o[i] = 0;

delta_o[i] = 0;

}

for(i = 0; i < mid_num; i++)

for(j = 0; j < out_num; j++)

v[i][j] = rand() / ( RAND_MAX + 1.0 );

for(i = 0; i < n; i++)

for(j = 0; j < mid_num; j++)

w[i][j] = rand() / ( RAND_MAX + 1.0 );

}

int trial()

{

int i,j,t,N;

double error;

ofstream fout( "result.txt" );

if( !fout )

cout << " can't create bp.txt\n " ;

/*cout << "請輸入學習率:alpha=";

cin >> alpha;

cout << endl << "請輸入誤差控制精度:sigma=";

cin >> sigma;

cout << endl << "請輸入循環的最大次數:M=";

cin >> M;*/

ifstream fin( "sample.txt" );

if( !fin )

cout << " can't open sample.txt\n";

for(i = 0; i < T; i++)

{

cout <<endl<< i<<" 個輸入\n"<<endl;

for(int p=0;p<32;p++)

{

fin >> input[i][p];

printf("%d",int(input[i][p]));

}

}

for(i = 0; i < T; i++)

{

cout <<endl<< i<<" 個輸出\n"<<endl;

for(int p=0;p<9;p++)

{

fin >> output[i][p];

printf("%d",int(output[i][p]));

}

}

fin.close();

E = sigma + 1;

N = 0;

initialize();

while( E > sigma && N < M)

{

N++;

for(t = 0; t < T; t++)

{

for(i = 0; i < mid_num; i++)

{

hide_s[i] = 0;

for(j = 0; j < n; j++)

hide_s[i] += w[j][i] * input[t][j];

hide_s[i] -= sita_h[i]; //計算隱含層各神經元的激活值hide_s

hide_o[i] = 1.0 / ( 1.0 + exp(-hide_s[i]) ); //隱含層神經元的輸出值

}

for(i = 0; i < out_num; i++)

{

output_s[i] = 0;

for(j = 0; j < mid_num; j++)

output_s[i] += v[j][i] * hide_o[j];

output_s[i] -= sita_o[i]; //計算輸出層各神經元的激活值output_s

output_o[i] = 1.0 / ( 1.0 + exp(-output_s[i]) ); //輸出層神經元的輸出值

}

for(i = 0; i < out_num; i++)

{

delta_o[i] = output_o[i] * ( 1 - output_o[i] ) * ( output[t][i] - output_o[i] );

//輸出層的校正誤差delta_o=(o-y)y(1-y)

sita_o[i] -= alpha * delta_o[i]; //輸出層閾值校正量

}

for(i = 0; i < mid_num; i++)

{

double Z = 0;

for(j = 0; j < out_num; j++)

Z += v[i][j] * delta_o[j];

delta_h[i] = Z * hide_o[i] * ( 1 - hide_o[i] ); //隱含層的校正誤差

sita_h[i] -= alpha * delta_h[i]; //隱含層閾值校正量

}

for(i = 0; i < mid_num; i++)

{

for(j = 0; j < out_num; j++)

{

v[i][j] += alpha * hide_o[i] * delta_o[j]; //輸出層至隱含層權值校正

}

}

for(i = 0; i < n; i++)

for(j = 0; j < mid_num; j++)

{

w[i][j] += alpha * input[t][i] * delta_h[j]; //隱含層至輸入層權值的校正

}

}

E = 0;

for(t = 0; t < T; t++)

{

for(i = 0; i < mid_num; i++)

{

hide_s[i] = 0;

for(j = 0; j < n; j++)

hide_s[i] += w[j][i] * input[t][j];

hide_s[i] -= sita_h[i]; //計算隱含層各神經元的激活值hide_s

hide_o[i] = 1.0 / ( 1.0 + exp(-hide_s[i]) ); //隱含層神經元的輸出值

}

for(i = 0; i < out_num; i++)

{

output_s[i] = 0;

for(j = 0; j < mid_num; j++)

output_s[i] += v[j][i] * hide_o[j];

output_s[i] -= sita_o[i]; //計算輸出層各神經元的激活值output_s

output_o[i] = 1.0 / ( 1.0 + exp(-output_s[i]) ); //輸出層神經元的輸出值

}

error = 0;

for(i = 0;i < out_num; i++)

error += ( output_o[i] - output[t][i] ) * ( output_o[i] - output[t][i] );

E += error / 2; //誤差計算

}

}

fout << "網絡學習" << N << "次結束,誤差為:" << E << ",各層的權值如下:" << endl;

fout << endl << "輸入層到隱藏層權值:" << endl;

for(i = 0; i < n; i++)

{

//fout << "w[" << i << "]";

for(j = 0; j < mid_num; j++)

{

fout << w[i][j] <<'\t';

}

fout << endl ;

}

fout << endl <<"隱藏層到輸出層權值:" << endl;

for(i = 0; i < mid_num; i++)

{

//fout << "v[" << i << "]";

for(j = 0; j < out_num; j++)

{

fout << v[i][j] <<'\t';

}

fout << endl ;

}

fout << endl << "對應着樣本實際輸出為:"<< endl;

for(t = 0; t < T; t++)

{

//fout << input[t][0] << '\t' << input[t][1] << '\t';

for(i = 0; i < mid_num; i++)

{

hide_s[i] = 0;

for(j = 0; j < n; j++)

hide_s[i] += w[j][i] * input[t][j];

hide_s[i] -= sita_h[i];

hide_o[i] = 1.0 / ( 1.0 + exp(-hide_s[i]) );

}

for(i = 0; i < out_num; i++)

{

output_s[i] = 0;

for(j = 0; j < mid_num; j++)

output_s[i] += v[j][i] * hide_o[j];

output_s[i] -= sita_o[i];

output_o[i] = 1.0 / ( 1.0 + exp(-output_s[i]) );

fout << output_o[i] << '\t';

}

fout << endl;

}

fout.close();

printf("done!!!");

return 0;

}

int test()

{

int i,j,t,N;

double error;

ofstream fout( "result.txt" );

if( !fout )

cout << " can't create bp.txt\n " ;

ifstream fin( "trial.txt" );

if( !fin )

cout << " can't open sample.txt\n";

for(i = 0; i < n; i++)

{

cout <<endl<<"w"<< i<<endl;

for(int p=0;p<mid_num;p++)

{

fin >> w[i][p];

printf(" %f ",w[i][p]);

}

}

for(i = 0; i < mid_num; i++)

{

cout <<endl<<"v"<< i<<endl;

for(int p=0;p<out_num;p++)

{

fin >> v[i][p];

printf(" %f ",v[i][p]);

}

}

for(i = 0; i < in_num; i++)

{

cout <<endl<< i<<" 個輸入\n"<<endl;

for(int p=0;p<n;p++)

{

fin >> input[i][p];

printf("%d",int(input[i][p]));

}

}

fin.close();

fout << endl << "對應着樣本實際輸出為:"<< endl;

for(t = 0; t < in_num; t++)

{

//fout << input[t][0] << '\t' << input[t][1] << '\t';

for(i = 0; i < mid_num; i++)

{

hide_s[i] = 0;

for(j = 0; j < n; j++)

hide_s[i] += w[j][i] * input[t][j];

hide_s[i] -= sita_h[i];

hide_o[i] = 1.0 / ( 1.0 + exp(-hide_s[i]) );

}

for(i = 0; i < out_num; i++)

{

output_s[i] = 0;

for(j = 0; j < mid_num; j++)

output_s[i] += v[j][i] * hide_o[j];

output_s[i] -= sita_o[i];

output_o[i] = 1.0 / ( 1.0 + exp(-output_s[i]) );

fout << output_o[i] << '\t';

}

fout << endl;

}

fout.close();

printf("done!!!");

return 0;:

}

  

clip_image061clip_image063clip_image065clip_image067

clip_image069clip_image071clip_image073

clip_image075clip_image077

神經網絡測試時,trial.txt文件前面是訓練好的神經網絡的參數:

0.377247 0.858411 -0.634805 0.507595 0.691088 0.519536 0.105074 0.960348 0.935243 -3.046 0.357988 0.491087

0.375012 0.828832 0.951367 0.432279 0.275154 2.63869 0.291745 0.739141 0.564582 -5.70708 0.76442 0.838058

0.400641 0.527232 1.45037 0.058791 1.01707 1.55471 0.0531387 0.53709 0.206088 3.01423 0.630553 0.671074

0.200186 0.850179 -1.31559 0.0763892 0.743755 5.06973 0.948105 0.289171 0.337871 -5.99671 0.732254 0.835663

0.708048 0.605176 0.881955 0.279621 0.141891 -5.15581 0.0731357 0.806125 0.853079 5.32735 0.11355 0.556637

0.017665 0.142064 0.0192649 0.759464 0.706458 1.01862 0.0816154 0.443103 0.213161 5.95356 0.2939 0.453217

0.242033 0.602425 -5.78124 0.599064 0.187205 -2.20553 0.959521 0.706918 0.94056 -1.40149 0.351149 0.197002

1.00086 0.455077 1.79714 0.0997744 0.631607 1.84406 0.43637 0.93598 0.0495626 -1.30654 0.297147 0.231462

0.776241 0.43548 3.0892 0.587198 0.633927 -0.517372 0.457637 0.605914 0.648855 1.7846 0.835886 0.633717

0.730424 0.605941 -6.01408 0.247359 0.763198 5.53306 0.918252 0.25396 0.203278 -3.64636 0.705638 0.61288

0.353938 0.490971 -5.15456 0.74475 0.613168 1.87483 0.694388 0.807908 0.147756 -1.99769 0.874812 0.92539

0.619933 0.738314 -6.46902 0.587859 0.995886 0.457699 0.567457 0.314481 0.18674 -1.79019 0.877299 0.851464

0.753193 0.175494 4.77418 0.0747461 0.105844 -2.62336 0.814459 0.555395 0.462717 -0.846603 0.310971 0.479186

0.510134 0.176028 1.07502 0.688057 0.339516 -0.399121 0.956348 0.88411 0.738688 2.2697 0.949 0.138311

0.0717262 0.79374 -4.47487 0.686007 0.957391 -7.2034 0.878786 0.658836 0.323527 -1.55444 0.518652 0.248108

0.290131 0.896138 0.649528 0.630392 0.110866 -4.30107 0.370895 0.496849 0.790859 8.92541 0.38592 0.683163

0.540558 0.641344 -3.19087 0.0886569 0.737851 -0.577588 0.627259 0.872157 0.504676 -5.11777 0.514084 0.415044

0.788252 0.555508 2.66023 0.973441 0.626731 -0.574999 0.385226 0.135119 0.743803 2.17861 0.620822 0.040573

0.335512 0.0534692 1.51597 0.134474 0.853338 0.721896 0.595418 0.726102 0.854994 5.29114 0.133573 0.712013

0.618638 0.206371 1.96753 0.0878029 0.625576 -1.3427 0.314514 0.369832 0.663497 2.95017 0.810152 0.518827

0.62022 0.835713 1.71622 0.13708 0.660553 0.679894 0.254888 0.14714 0.868766 -0.664971 0.435085 0.599524

0.307424 0.549136 -0.154131 0.301203 0.11472 3.00481 0.132712 0.288762 0.790066 0.127832 0.788714 0.746273

0.618885 0.356983 1.19457 0.261181 0.873147 0.575007 0.245541 0.544089 0.984175 3.2499 0.0871343 0.528641

0.430027 0.100405 0.352517 0.871845 0.253838 -1.23204 0.123602 0.93716 0.0912947 2.14616 0.0649301 0.337019

0.91647 0.38311 6.68484 0.88988 0.835064 -2.39749 0.836507 0.696528 0.397337 0.227614 0.00881625 0.52464

0.957914 0.422008 3.00306 0.621519 0.277795 -5.21993 0.949012 0.44137 0.901673 2.82637 0.945287 0.622713

0.789526 0.58565 -3.6062 0.208824 0.403906 2.7528 0.418193 0.0882874 0.671148 -2.46241 0.0721788 0.820473

0.667946 0.686849 -2.17367 0.497317 0.690848 1.01549 0.685628 0.732831 0.77806 3.40165 0.876567 0.653006

0.713841 0.105793 2.03294 0.993234 0.0860135 3.14267 0.145836 0.989826 0.632768 -3.62082 0.932041 0.383594

0.694326 0.209136 0.148397 0.206527 0.519482 3.66009 0.105346 0.902985 0.442806 -4.25958 0.778145 0.164006

0.974441 0.778894 6.48005 0.261923 0.458774 -0.833779 0.755149 0.114259 0.405322 -3.91584 0.991908 0.0494735

0.257562 0.202866 2.07583 0.17988 0.629609 -0.679001 0.939315 0.200052 0.781164 1.22227 0.659771 0.921545

0.422288 -2.50635 -1.46338 -1.6023 -1.84221 -0.344169 -0.307905 -1.62429 -3.31261

0.196554 -1.94979 -0.994689 -1.23098 -2.14057 -0.365164 -0.080708 -1.40259 -3.4215

-8.9893 9.34044 -10.3186 9.27844 -1.89813 -9.48953 7.49168 -10.1012 12.5381

1.183 -2.39131 -0.47187 -1.04568 -1.07435 -0.238901 -0.0490415 -1.64092 -3.48751

0.280129 -1.77857 -1.43888 -1.23298 -2.11657 -0.215215 -0.81794 -2.21149 -3.01541

-16.4326 -8.78439 -8.49366 8.21918 4.66897 8.06705 -12.8712 15.9745 19.8687

0.453258 -2.16244 -0.50957 -0.867093 -2.09136 -0.284455 -0.487313 -1.49971 -3.33198

0.556833 -2.26427 -1.31253 -1.38828 -1.79405 -0.0785346 -0.361075 -1.23356 -3.1663

0.327637 -2.45429 -0.806304 -1.11871 -2.15539 -0.186563 -0.372242 -2.07658 -2.96845

-8.28416 18.0912 14.9721 -16.9528 16.9704 -23.0413 -8.14845 4.80364 6.79369

0.837821 -1.80192 -0.883725 -1.42135 -2.03776 -0.0541501 -0.400628 -2.07058 -3.41988

0.715436 -2.20815 -1.18571 -1.01918 -1.52575 -0.177048 -0.146913 -1.73517 -3.79789

例如:

clip_image079

輸入向量:

0

1 0 0 0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 0

1

1 1 1 0 1 0 1 1 0 1 0 0 1 1 0 0 1 1 1 0 1 1 1 1 0 1 1 0 1 0 1 1

2

1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 1 0 1 0 1 1 1 0 0 0 0 1 1 0 0 1

3

1 1 0 0 0 0 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 1 0 0

對應着樣本實際輸出為:

0

4.60587e-006 0.999625 0.0122094 8.20651e-009 0.154652 1.09484e-015 0.0240042 9.64179e-010 2.47071e-005

1

1.8857e-009 1.02738e-008 1.29456e-012 0.997627 9.50407e-007 0.0181077 0.000289101 4.42784e-005 0.880562

2

1.52949e-005 1.79338e-012 3.39587e-008 0.0418522 5.61276e-006 0.991913 2.94107e-007 0.327807 2.77761e-005

3

3.69813e-013 0.293486 2.50337e-006 3.09886e-005 0.947757 3.49155e-012 7.02339e-008 0.00738104 0.999895

clip_image081

5結論

實驗表明盤數字識別,結果是令人鼓舞的。利用神經網絡的自適應學習能力,可以從數字圖像中發掘有用信息,從而找到影響分類的非線性映射關系,為快速、准確地進行數字識別提供了一種新的途徑。但是,由於在神經網絡的應用研究中,研究對象不同、研究對象的復雜程度不同以及一些固有特性的差異,神經網絡模型的結構也不同,不同的網絡結構對網絡的訓練和識別效果都會產生影響。除此之外,網絡初始權值的選取以及訓練程度等對網絡也都有影響。對於數字圖像本身,預處理的算法、特征向量的提取方法等因素對數字識別率的影響也很大。這些問題仍舊需要進一步研究和提高。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM