标签:
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