标签:
void cnnbp(CNN* cnn,float* outputData) // 网络的后向传播 { int i,j,c,r; // 将误差保存到网络中 for(i=0;i<cnn->O5->outputNum;i++) cnn->e[i]=cnn->O5->y[i]-outputData[i]; /*从后向前反向计算*/ // 输出层O5 for(i=0;i<cnn->O5->outputNum;i++) cnn->O5->d[i]=cnn->e[i]*sigma_derivation(cnn->O5->y[i]); // S4层,传递到S4层的误差 // 这里没有激活函数 nSize outSize={cnn->S4->inputWidth/cnn->S4->mapSize,cnn->S4->inputHeight/cnn->S4->mapSize}; for(i=0;i<cnn->S4->outChannels;i++) for(r=0;r<outSize.r;r++) for(c=0;c<outSize.c;c++) for(j=0;j<cnn->O5->outputNum;j++){ int wInt=i*outSize.c*outSize.r+r*outSize.c+c; cnn->S4->d[i][r][c]=cnn->S4->d[i][r][c]+cnn->O5->d[j]*cnn->O5->wData[j][wInt]; } // C3层 // 由S4层传递的各反向误差,这里只是在S4的梯度上扩充一倍 int mapdata=cnn->S4->mapSize; nSize S4dSize={cnn->S4->inputWidth/cnn->S4->mapSize,cnn->S4->inputHeight/cnn->S4->mapSize}; // 这里的Pooling是求平均,所以反向传递到下一神经元的误差梯度没有变化 for(i=0;i<cnn->C3->outChannels;i++){ float** C3e=UpSample(cnn->S4->d[i],S4dSize,cnn->S4->mapSize,cnn->S4->mapSize); for(r=0;r<cnn->S4->inputHeight;r++) for(c=0;c<cnn->S4->inputWidth;c++) cnn->C3->d[i][r][c]=C3e[r][c]*sigma_derivation(cnn->C3->y[i][r][c])/(float)(cnn->S4->mapSize*cnn->S4->mapSize); for(r=0;r<cnn->S4->inputHeight;r++) free(C3e[r]); free(C3e); } // S2层,S2层没有激活函数,这里只有卷积层有激活函数部分 // 由卷积层传递给采样层的误差梯度,这里卷积层共有6*12个卷积模板 outSize.c=cnn->C3->inputWidth; outSize.r=cnn->C3->inputHeight; nSize inSize={cnn->S4->inputWidth,cnn->S4->inputHeight}; nSize mapSize={cnn->C3->mapSize,cnn->C3->mapSize}; for(i=0;i<cnn->S2->outChannels;i++){ for(j=0;j<cnn->C3->outChannels;j++){ float** corr=correlation(cnn->C3->mapData[i][j],mapSize,cnn->C3->d[j],inSize,full); addmat(cnn->S2->d[i],cnn->S2->d[i],outSize,corr,outSize); for(r=0;r<outSize.r;r++) free(corr[r]); free(corr); } /* for(r=0;r<cnn->C3->inputHeight;r++) for(c=0;c<cnn->C3->inputWidth;c++) // 这里本来用于采样的激活 */ } // C1层,卷积层 mapdata=cnn->S2->mapSize; nSize S2dSize={cnn->S2->inputWidth/cnn->S2->mapSize,cnn->S2->inputHeight/cnn->S2->mapSize}; // 这里的Pooling是求平均,所以反向传递到下一神经元的误差梯度没有变化 for(i=0;i<cnn->C1->outChannels;i++){ float** C1e=UpSample(cnn->S2->d[i],S2dSize,cnn->S2->mapSize,cnn->S2->mapSize); for(r=0;r<cnn->S2->inputHeight;r++) for(c=0;c<cnn->S2->inputWidth;c++) cnn->C1->d[i][r][c]=C1e[r][c]*sigma_derivation(cnn->C1->y[i][r][c])/(float)(cnn->S2->mapSize*cnn->S2->mapSize); for(r=0;r<cnn->S2->inputHeight;r++) free(C1e[r]); free(C1e); } }
编写C语言版本的卷积神经网络CNN之三:CNN的误差反向传播过程
标签:
原文地址:http://blog.csdn.net/tostq/article/details/51788093