深度學習之卷積神經網路程式設計實現(二)
阿新 • • 發佈:2019-01-07
void conv_bprop(Layer *layer, Layer *prev_layer, bool *pconnection) { int index = 0; int size = prev_layer->map_w * prev_layer->map_h; // delta for (int i = 0; i < prev_layer->map_count; i++) { memset(prev_layer->map_common, 0, size*sizeof(double)); for (int j = 0; j < layer->map_count; j++) { index = i*layer->map_count + j; if (pconnection != NULL && !pconnection[index]) { continue; } for (int n = 0; n < layer->map_h; n++) { for (int m = 0; m < layer->map_w; m++) { double error = layer->map[j].error[n*layer->map_w + m]; for (int ky = 0; ky < layer->kernel_h; ky++) { for (int kx = 0; kx < layer->kernel_w; kx++) { prev_layer->map_common[(n + ky)*prev_layer->map_w + m + kx] += error * layer->kernel[index].W[ky*layer->kernel_w + kx]; } } } } } for (int k = 0; k < size; k++) { prev_layer->map[i].error[k] = prev_layer->map_common[k] * activation_func::dtan_h(prev_layer->map[i].data[k]); } } // dW for (int i = 0; i < prev_layer->map_count; i++) { for (int j = 0; j < layer->map_count; j++) { index = i*layer->map_count + j; if (pconnection != NULL && !pconnection[index]) { continue; } convn_valid( prev_layer->map[i].data, prev_layer->map_w, prev_layer->map_h, layer->map[j].error, layer->map_w, layer->map_h, layer->kernel[index].dW, layer->kernel_w, layer->kernel_h); } } // db size = layer->map_w * layer->map_h; for (int i = 0; i < layer->map_count; i++) { double sum = 0.0; for (int k = 0; k < size; k++) { sum += layer->map[i].error[k]; } layer->map[i].db += sum; } } void avg_pooling_bprop(Layer *layer, Layer *prev_layer) { const double scale_factor = 0.25; int size = prev_layer->map_w * prev_layer->map_h; for (int i = 0; i < layer->map_count; i++) { kronecker(layer->map[i].error, layer->map_w, layer->map_h, prev_layer->map_common, prev_layer->map_w); // delta for (int k = 0; k < size; k++) { double delta = layer->kernel[i].W[0] * prev_layer->map_common[k]; prev_layer->map[i].error[k] = delta * scale_factor * activation_func::dtan_h(prev_layer->map[i].data[k]); } // dW double sum = 0.0; for (int k = 0; k < size; k++) { sum += prev_layer->map[i].data[k] * prev_layer->map_common[k]; } layer->kernel[i].dW[0] += sum * scale_factor; // db sum = 0.0; for (int k = 0; k < layer->map_w * layer->map_h; k++) { sum += layer->map[i].error[k]; } layer->map[i].db += sum; } } void max_pooling_bprop(Layer *layer, Layer *prev_layer) { int map_w = layer->map_w; int map_h = layer->map_h; int upmap_w = prev_layer->map_w; for (int k = 0; k < layer->map_count; k++) { // delta for (int i = 0; i < map_h; i++) { for (int j = 0; j < map_w; j++) { int row = 2*i, col = 2*j; double max_value = prev_layer->map[k].data[row*upmap_w + col]; for (int n = 2*i; n < 2*(i + 1); n++) { for (int m = 2*j; m < 2*(j + 1); m++) { if (prev_layer->map[k].data[n*upmap_w + m] > max_value) { row = n; col = m; max_value = prev_layer->map[k].data[n*upmap_w + m]; } else { prev_layer->map[k].error[n*upmap_w + m] = 0.0; } } } prev_layer->map[k].error[row*upmap_w + col] = layer->map[k].error[i*map_w + j] * activation_func::dtan_h(max_value); } } // dW // db } } void fully_connected_bprop(Layer *layer, Layer *prev_layer) { // delta for (int i = 0; i < prev_layer->map_count; i++) { prev_layer->map[i].error[0] = 0.0; for (int j = 0; j < layer->map_count; j++) { prev_layer->map[i].error[0] += layer->map[j].error[0] * layer->kernel[i*layer->map_count + j].W[0]; } prev_layer->map[i].error[0] *= activation_func::dtan_h(prev_layer->map[i].data[0]); } // dW for (int i = 0; i < prev_layer->map_count; i++) { for (int j = 0; j < layer->map_count; j++) { layer->kernel[i*layer->map_count + j].dW[0] += layer->map[j].error[0] * prev_layer->map[i].data[0]; } } // db for (int i = 0; i < layer->map_count; i++) { layer->map[i].db += layer->map[i].error[0]; } } void backward_propagation(double *label) { for (int i = 0; i < output_layer.map_count; i++) { output_layer.map[i].error[0] = loss_func::dmse(output_layer.map[i].data[0], label[i]) * activation_func::dtan_h(output_layer.map[i].data[0]); } // Out-->C5 fully_connected_bprop(&output_layer, &c5_conv_layer); // C5-->S4 conv_bprop(&c5_conv_layer, &s4_pooling_layer, NULL); // S4-->C3 max_pooling_bprop(&s4_pooling_layer, &c3_conv_layer);/*avg_pooling_bprop*/ // C3-->S2 conv_bprop(&c3_conv_layer, &s2_pooling_layer, connection_table); // S2-->C1 max_pooling_bprop(&s2_pooling_layer, &c1_conv_layer);/*avg_pooling_bprop*/ // C1-->In conv_bprop(&c1_conv_layer, &input_layer, NULL); }