深度學習神經網路純C語言基礎版【轉】
阿新 • • 發佈:2019-01-26
/* 深度學習神經網路V1.0 made by xyt 2015/7/23 使用語言:C 本程式構建多層矩陣形神經網路多輸入單輸出 學習策略:隨機梯度下降 啟用函式:sigmoid 使用前必須用srand((unsigned)time(NULL))取隨機對映初始值 */ #ifndef _DNN_H #define _DNN_H #include<stdio.h> #include<math.h> #include <stdlib.h> #include <time.h> #define DNN_VEC 8 //輸入訓練組組數 #define DNN_INUM 5 //輸入維度 double dnn_sig(double in){ //sigmoid函式,此處不可變 return 1.0/(1.0+exp(-1.0*in)); } struct dnn_cell{ //神經元結構體 double w[DNN_INUM]; double wb; double in[DNN_INUM]; double out; double error; double v; void SetCell_Default(){ //預設初始化,權值初始化很小 int i; for(i=0;i<DNN_INUM;i++){ w[i]=0.000001; } wb=0.000001; v=0.001; } void SetCell_InitWeight(double Initial){ //權值統一權值初始化 int i; for(i=0;i<DNN_INUM;i++){ w[i]=Initial; } wb=Initial; v=0.001; } void SetCell_InitAll(double Initial,double InV){ //權值統一初始化,學習速率初始化 int i; for(i=0;i<DNN_INUM;i++){ w[i]=Initial; } wb=Initial; v=InV; } void SetCell_Precise(double *InW,double InWb,double InV){ //權值精確初始化,學習速率初始化 int i; for(i=0;i<DNN_INUM;i++){ w[i]=InW[i]; } wb=InWb; v=InV; } void SetIn(double *SIn){ //設定神經元輸入 int i; for(i=0;i<DNN_INUM;i++){ in[i]=SIn[i]; } } double GetOut(){ //獲取、設定神經元輸出 int i; double sum=0; for(i=0;i<DNN_INUM;i++){ sum+=w[i]*in[i]; } sum+=wb; out=dnn_sig(sum); return out; } void UpdateWeight(){ //更新神經元權值 int i; for(i=0;i<DNN_INUM;i++){ w[i]-=v*error*out*(1-out)*in[i]; } wb=v*error*out*(1-out); } void SetError(double InErr){ //設定神經元誤差傳播值 error=InErr; } void SetSpeed(double InV){ //設定神經元學習速率 v=InV; } }; /* 獲得前向傳播得到的輸出值,第一個引數為神經元結構體陣列,第二個引數為神經網路 層數。具體排列為:前0~DNN_INUM神經元為第一層,後面每DNN_INUM個神經元為一層,依次 排列,直至最後一個輸出神經元為單獨一層,如果層數是4,DNN_INUM=5(5輸入)則神經元 數量應為(4-1)*5+1=16個。*in引數為輸入網路的具有DNN_INUM個數據的陣列 */ double DNN_Cal(dnn_cell *incell,int deep,double *in) { double out=0; int dd=0,i,j,k,count=0; double tmp[DNN_INUM]; for(i=0;i<DNN_INUM;i++) tmp[i]=in[i]; for(j=0;j<deep-1;j++) { for(i=j*DNN_INUM;i<(j*DNN_INUM+DNN_INUM);i++) { incell[i].SetIn(tmp); incell[i].GetOut(); count++; } k=0; for(i=j*DNN_INUM;i<(j*DNN_INUM+DNN_INUM);i++) {tmp[k]=incell[i].out; k++;} } incell[count].SetIn(tmp); out=incell[count].GetOut(); return out; } /* 對輸入矩陣訓練,最後得到更新的神經網路,要求每組資料量限定為DNN_INUM資料組數限定為DNN_VEC 輸入神經原組為按層排列,除了最後一層的節點數為一其他節點數都限定為輸入向量DNN_INUM deep為網路層數至少2層,算上最後輸出層,n為訓練次數,expect為期望,返回訓練後平均誤差 */ double DNN_Train(dnn_cell *cell,int deep,double InMat[DNN_VEC][DNN_INUM],double *expect,int n) { double out,devi,sum; double de[DNN_VEC]; int co=n,kp=-1; int i,j,k,tt,l; for(i=0;i<DNN_VEC;i++) de[i]=9.9; while(co--){ kp=(int)(rand()*(double)(DNN_VEC)/RAND_MAX); out=DNN_Cal(cell,deep,InMat[kp]); devi=out-expect[kp]; de[kp]=devi; //printf("%lf %lf %lf %d\n",fabs(de[0]),fabs(de[3]),fabs(de[7]),kp); tt=(deep-1)*DNN_INUM; cell[tt].error=devi; l=0; for(i=(deep-2)*DNN_INUM;i<tt;i++) {cell[i].error=cell[tt].error*cell[tt].out*(1-cell[tt].out)*cell[tt].w[l];l++;} for(j=deep-2;j>0;j--){ l=0; for(i=(j-1)*DNN_INUM;i<j*DNN_INUM;i++){ sum=0; for(k=j*DNN_INUM;k<(j+1)*DNN_INUM;k++){ sum+=cell[k].error*cell[k].out*(1-cell[k].out)*cell[k].w[l]; } cell[i].error=sum; l++; } } for(i=0;i<=(deep-1)*DNN_INUM;i++){ cell[i].UpdateWeight(); } //變學習速率,可以自行更改=============================== for(i=0;i<=(deep-1)*DNN_INUM;i++){ cell[i].SetSpeed(fabs(devi)); } //======================================================= } sum=0; for(i=0;i<DNN_VEC;i++) sum+=fabs(de[i]); return sum/DNN_VEC; } #endif