1. 程式人生 > >深度學習之卷積神經網路程式設計實現(二)

深度學習之卷積神經網路程式設計實現(二)

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);
}