简单BP神经网络分类手写数字识别0-9
前言:本人旨在交流代碼,細節和原理不清楚的可以留言,以后做完了再整理,現在先放一部分,可以直接使用
1.代碼可以直接在c上運行,輸入為5*5矩陣,比如數字0:
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
因為訓練集合太小,決定用matlab生成大量訓練樣本,放在后文中。
2.c語言實現代碼:(BP推導很簡單,不會的自己可以留言,代碼中有詳細注釋)
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h>#define COUNT 50//樣本數量 #define IN_NUM 25//輸入層神經元數量 #define OUT_NUM 10//輸出層神經元數量 #define numHidden 30//隱含層神經元數量double weight_hidden[IN_NUM][numHidden];//輸入層到隱含層的權值 double bias_hidden[numHidden];//隱含層的閾值 double weight_output[numHidden][OUT_NUM];//隱含層到輸出層的權值 double bias_output[OUT_NUM];//輸出層的閾值 double learnRate = 0.4;//學習數率 double accuracy = 0.001;//最大容許誤差0.000001 int maxloopCount = 1000000;//最大學習數率 double fnet(double net)//Sigmoid {return 1 / (1 + exp(-net)); } double dfnet(double net)//Sigmoid導函數 y = s*(s-1) {return net * (1 - net); } int InitBP()//得到-1到1隨機數 {int i, j;srand((unsigned)time(NULL));for (i = 0; i < IN_NUM; i++)for (j = 0; j < numHidden; j++){weight_hidden[i][j] = rand() / (double)(RAND_MAX)-0.5;bias_hidden[j] = rand() / (double)(RAND_MAX)-0.5;}for (i = 0; i < numHidden; i++)for (j = 0; j < OUT_NUM; j++){weight_output[i][j] = rand() / (double)(RAND_MAX)-0.5;bias_output[j] = rand() / (double)(RAND_MAX)-0.5;}return 1; } int TrainBP(float x[COUNT][IN_NUM], float y[COUNT][OUT_NUM]) {double delta_hidden[numHidden], delta_output[OUT_NUM];//中間計算量double output_hidden[numHidden], output_output[OUT_NUM];//隱含層輸出 輸出層輸出double temp;//中間累加值double loss;int i, j, k, n;for (n = 0; n < maxloopCount; n++){loss = 0;for (i = 0; i < COUNT; i++)//逐個數據進行計算,整個數據計算一遍后n+1{/*前相傳播*///計算隱含層輸出for (k = 0; k < numHidden; k++){temp = 0;for (j = 0; j < IN_NUM; j++)temp += x[i][j] * weight_hidden[j][k];output_hidden[k] = fnet(temp + bias_hidden[k]);}//計算輸出層輸出for (k = 0; k < OUT_NUM; k++){temp = 0;for (j = 0; j < numHidden; j++)temp += output_hidden[j] * weight_output[j][k];output_output[k] = fnet(temp + bias_output[k]);}//計算誤差for (j = 0; j < OUT_NUM; j++)loss += 0.5*(y[i][j] - output_output[j])*(y[i][j] - output_output[j]);/*方向傳播階段*///更新輸出層的權值for (j = 0; j < OUT_NUM; j++)delta_output[j] = (y[i][j] - output_output[j])*dfnet(output_output[j]);for (j = 0; j < numHidden; j++)for (k = 0; k < OUT_NUM; k++){weight_output[j][k] += learnRate * delta_output[k] * output_hidden[j];}//更新輸出層的偏重for (k = 0; k < OUT_NUM; k++)bias_output[k] += learnRate * delta_output[k];//更新隱含層權重for (j = 0; j < numHidden; j++){temp = 0;for (k = 0; k < OUT_NUM; k++)temp += weight_output[j][k] * delta_output[k];delta_hidden[j] = temp * dfnet(output_hidden[j]);}for (j = 0; j<IN_NUM; j++)for (k = 0; k < numHidden; k++)weight_hidden[j][k] += learnRate*delta_hidden[k] * x[i][j];//跟新隱含層偏置for (k = 0; k < numHidden; k++)bias_hidden[k] += learnRate*delta_hidden[k];}if (n % 10 == 0)printf("誤差:%f\n", loss);if (loss <= accuracy)break;//達到訓練標準,訓練提前結束}printf("總的訓練次數:%d\n", n);printf("bp網絡訓練結束!\n");return 1; } int TestBP() {float Input[IN_NUM];//定義輸入向量double output_hidden[numHidden];//隱含層輸出double output_output[OUT_NUM];//輸出層輸出double mid= 0;int c;while (1){printf("請輸入一個數:\n");int i, j;//輸入層for (i = 0; i < IN_NUM; i++){scanf_s("%f", &Input[i]);}//隱含層double temp;for (i = 0; i < numHidden; i++)//輸入層神經元與隱含層神經元的連接計算{temp = 0;//中間變量,用于存儲隱含層隱含層神經元輸出for (j = 0; j < IN_NUM; j++)temp += Input[j] * weight_hidden[j][i];output_hidden[i] = fnet(temp + bias_hidden[i]);}//輸出層for (i = 0; i < OUT_NUM; i++){temp = 0;for (j = 0; j < numHidden; j++)temp += output_hidden[j] * weight_output[j][i];output_output[i] = fnet(temp + bias_output[i]);}//輸出輸出層每一個神經元結果printf("結果為: ");for (i = 0; i < OUT_NUM; i++)printf("%f ", output_output[i]);for (i = 0; i < OUT_NUM; i++){if (mid < output_output[i]){mid = output_output[i];c = i; }}printf("你輸入的數為%d\n", c);printf("\n");}return 1; }int main() {//輸入規則:3不允許連排,且輸入偏右//x為輸入向量,y為輸出向量float x[COUNT][IN_NUM] = {// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25//------------------------------------0 start----------------------------------------------------//{ 1, 1, 1, 1, 1,1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },// 1 2 3 4 5{ 1, 1, 1, 1, 0,1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 },// 1 2 3 4 5{0, 1, 1, 1, 1,0, 1, 0, 0, 1,0, 1, 0, 0, 1,0, 1, 0, 0, 1,0, 1, 1, 1, 1},// 1 2 3 4 5{1, 1, 1, 1, 0,1, 0, 0, 1, 0,1, 1, 1, 1, 0,0, 0, 0, 0, 0,0, 0, 0, 0, 0},// 1 2 3 4 5{1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1,0, 0, 0, 0, 0,0, 0, 0, 0, 0}, //------------------------------------0 end------------------------------------------------------------// //------------------------------------1 start----------------------------------------------------//// 1 2 3 4 5 {1, 0, 0, 0, 0,1, 0, 0, 0, 0,1, 0, 0, 0, 0,1, 0, 0, 0, 0,1, 0, 0, 0, 0},// 1 2 3 4 5{0, 1, 0, 0, 0,0, 1, 0, 0, 0,0, 1, 0, 0, 0,0, 1, 0, 0, 0,0, 1, 0, 0, 0},// 1 2 3 4 5{0, 0, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0},// 1 2 3 4 5{0, 0, 0, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0},// 1 2 3 4 5{0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1}, //------------------------------------1 end------------------------------------------------------------// //------------------------------------2 start----------------------------------------------------// // 1 2 3 4 5 {1, 1, 1, 1, 1,0, 0, 0, 0, 1,1, 1, 1, 1, 1,1, 0, 0, 0, 0,1, 1, 1, 1, 1},// 1 2 3 4 5{0, 0, 0, 0, 0,1, 1, 1, 1, 1,1, 1, 1, 1, 1,1, 0, 0, 0, 0,1, 1, 1, 1, 1},// 1 2 3 4 5{0, 1, 1, 1, 0,0, 0, 0, 1, 0,0, 1, 1, 1, 0,0, 1, 0, 0, 0,0, 1, 1, 1, 0},// 1 2 3 4 5{1, 1, 1, 1, 0,0, 0, 0, 1, 0,1, 1, 1, 1, 0,1, 0, 0, 0, 0,1, 1, 1, 1, 0},// 1 2 3 4 5{0, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 1, 1, 1, 1,0, 1, 0, 0, 0,0, 1, 1, 1, 1}, //------------------------------------2 end------------------------------------------------------------// //------------------------------------3 start----------------------------------------------------// // 1 2 3 4 5 {1, 1, 1, 1, 1,0, 0, 0, 0, 1,1, 1, 1, 1, 1,0, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{1, 1, 1, 1, 0,0, 0, 0, 1, 0,1, 1, 1, 1, 0,0, 0, 0, 1, 0,1, 1, 1, 1, 0},// 1 2 3 4 5{1, 1, 1, 0, 0,0, 0, 1, 0, 0,1, 1, 1, 0, 0,0, 0, 1, 0, 0,1, 1, 1, 0, 0},// 1 2 3 4 5{1, 1, 1, 1, 1,1, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{0, 0, 1, 1, 1,0, 0, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 1, 1, 1,0, 0, 0, 0, 0}, //------------------------------------3 end------------------------------------------------------------// //------------------------------------4 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 0, 0, 0,1, 1, 0, 0, 0,1, 1, 0, 0, 0,1, 1, 1, 1, 1,0, 1, 0, 0, 0},// 1 2 3 4 5{1, 0, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 1, 1,0, 0, 1, 0, 0,0, 0, 1, 0, 0},// 1 2 3 4 5{1, 0, 0, 1, 0,1, 0, 0, 1, 0,1, 1, 1, 1, 1,0, 0, 0, 1, 0,0, 0, 0, 1, 0},// 1 2 3 4 5{1, 0, 0, 0, 1,1, 0, 0, 0, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1,0, 0, 0, 0, 1},// 1 2 3 4 5{1, 0, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 1, 1,0, 0, 1, 0, 0,0, 0, 1, 0, 0}, //------------------------------------4 end------------------------------------------------------------// //------------------------------------5 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 1, 1, 1,1, 0, 0, 0, 0,1, 1, 1, 1, 1,0, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{1, 1, 1, 1, 0,1, 0, 0, 0, 0,1, 1, 1, 1, 0,0, 0, 0, 1, 0,1, 1, 1, 1, 0},// 1 2 3 4 5{1, 1, 1, 0, 0,1, 0, 0, 0, 0,1, 1, 1, 0, 0,1, 1, 1, 0, 0,0, 0, 0, 0, 0},// 1 2 3 4 5{1, 1, 1, 0, 0,1, 0, 0, 0, 0,1, 1, 1, 0, 0,0, 0, 1, 0, 0,1, 1, 1, 0, 0},// 1 2 3 4 5{0, 1, 1, 1, 0,0, 1, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,0, 1, 1, 1, 0}, //------------------------------------5 end------------------------------------------------------------// //------------------------------------6 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 1, 1, 1,1, 0, 0, 0, 0,1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{1, 0, 0, 0, 0,1, 0, 0, 0, 0,1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{1, 1, 1, 0, 0,1, 0, 0, 0, 0,1, 1, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 0, 0},// 1 2 3 4 5{0, 0, 1, 1, 1,0, 0, 1, 0, 0,0, 0, 1, 1, 1,0, 0, 1, 1, 1,0, 0, 0, 0, 0},// 1 2 3 4 5{0, 1, 0, 0, 0,0, 1, 0, 0, 0,0, 1, 1, 1, 1,0, 1, 0, 0, 1,0, 1, 1, 1, 1}, //------------------------------------6 end------------------------------------------------------------// //------------------------------------7 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1},// 1 2 3 4 5{0, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 0},// 1 2 3 4 5{0, 0, 0, 0, 0,0, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1},// 1 2 3 4 5{0, 0, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0},// 1 2 3 4 5{0, 0, 0, 0, 0,0, 0, 0, 0, 0,1, 1, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0}, //------------------------------------7 end------------------------------------------------------------// //------------------------------------8 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1},// 1 2 3 4 5{1, 1, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 0, 0},// 1 2 3 4 5{0, 0, 1, 1, 1,0, 0, 1, 0, 1,0, 0, 1, 1, 1,0, 0, 1, 0, 1,0, 0, 1, 1, 1},// 1 2 3 4 5{0, 1, 1, 1, 0,0, 1, 0, 1, 0,0, 1, 1, 1, 0,0, 1, 1, 1, 0,0, 0, 0, 0, 0},// 1 2 3 4 5{0, 1, 1, 1, 1,0, 1, 0, 0, 1,0, 1, 1, 1, 1,0, 1, 0, 0, 1,0, 1, 1, 1, 1}, //------------------------------------8 end------------------------------------------------------------// //------------------------------------9 start----------------------------------------------------//// 1 2 3 4 5 {1, 1, 1, 1, 1,1, 0, 0, 0, 1,1, 1, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1},// 1 2 3 4 5{1, 1, 1, 0, 0,1, 0, 1, 0, 0,1, 1, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0},// 1 2 3 4 5{0, 0, 1, 1, 1,0, 0, 1, 0, 1,0, 0, 1, 1, 1,0, 0, 0, 0, 1,0, 0, 0, 0, 1},// 1 2 3 4 5{0, 0, 0, 0, 0,1, 1, 1, 1, 0,1, 0, 0, 1, 0,1, 1, 1, 1, 0,0, 0, 0, 1, 0},// 1 2 3 4 5{0, 1, 1, 1, 0,0, 1, 0, 1, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,0, 0, 0, 1, 0}, //------------------------------------9 end------------------------------------------------------------//};float y[COUNT][OUT_NUM] = {{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },//0{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },//1{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },//2{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },//3{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },//4{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },//5{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },//6{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },//7{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },//8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },//9};InitBP();//初始化BP網絡TrainBP(x, y);//訓練BPTestBP();//測試BPreturn 1; }c語言程序運行結果:
很明顯,對于輸入的矩陣完美判別(受到訓練集合大小和圖像像素的影響,對于不規則輸入有很大誤差)
3.訓練集合太小,所以我又研究了下matlab手寫輸入畫板,在matlab下新建圖形界面,傳送門:http://blog.sina.com.cn/s/blog_86a4e34a0102vxra.html,參考了這個代碼。matlab手寫畫板.m文件幾個重要函數在傳送門直接可以用,使用效果如下:
這是打開的matlab手寫輸入板,自己寫的1,保存為bmp圖像,保存按鈕的代碼如下:(傳送門沒有)
% --- 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) h=getframe(handles.axes1); imwrite(h.cdata,'output.bmp','bmp'); cla(handles.axes1);4.對于保存的圖像生成二進制,matlab代碼如下: clc; clear; filename = 'output.bmp'; %讀出源文件 imfinfo(filename) % 查看圖像文件信息 imgRgb = imread(filename); % 讀入一幅彩色圖像 imshow(imgRgb); % 顯示彩色圖像 imgGray = rgb2gray(imgRgb); % 轉為灰度圖像 figure % 打開一個新的窗口顯示灰度圖像 imshow(imgGray); % 顯示轉化后的灰度圖像 % imwrite(imgGray, 'gray.jpg'); % 將灰度圖像保存到圖像文件 thresh = graythresh(imgGray); %自動確定二值化閾值 I = im2bw(imgGray,thresh); %對圖像二值化 ci=imresize(I,[16,16]); %把ai轉成256x256的大小 ti =~ci;%對圖像取反 figure imshow(ti)%畫取反后的圖 figure imshow(ci)%畫壓縮后的二進制 figure imshow(I); %畫二進制圖結果如下:左到右依次為原圖、灰度圖、壓縮后的二進制圖,原本二進制圖,我們需要的數據就存儲在二進制圖的數組里面16*16大小,可以弄大一點,這樣對于輸入的判斷會更準。
本文缺陷:1.c語言中讀入訓練集合和測試集合應改為文件流操作,這樣對于大量數據文件的訓練和測試會很方便,matlab 生成圖像文件和二進制文件可以直接改為文件操作,時間有限感興趣的可以基于我的demo改,希望能共同學習共同進步!!!
結束語:c語言實現只是我測試的一個東西,我的目的是用ASIC集成電路實現,下一步將在fpga使用verilog語言實現這個手寫輸入識別!敬請關注!
文中多有瑕疵和漏洞,歡迎指教!
總結
以上是生活随笔為你收集整理的简单BP神经网络分类手写数字识别0-9的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Report (enovia) 开发实践
- 下一篇: 1044 火星数字