分享一个caffe中Upsample层的实现

原创
2019/10/15 09:43
阅读数 4.5K

caffe中cpu的Upsample层实现,方便跑起来某些网络

public:
	SETUP_LAYERFUNC(Upsample);

	virtual void setup(const char* name, const char* type, const char* param_str, int phase, Blob** bottom, int numBottom, Blob** top, int numTop) {

		const int b0_width = bottom[0]->width();
		const int b0_height = bottom[0]->height();
		const int b1_width = bottom[1]->width();
		const int b1_height = bottom[1]->height();

		w_ratio_ = b0_width / b1_width;
		h_ratio_ = b0_height / b1_height;

		/*vector<int> container_shape;
		container_shape.push_back(b0_height);
		container_shape.push_back(b0_width);
		container_shape.push_back(b1_height);
		container_shape.push_back(b1_width);
		container_.Reshape(container_shape);*/
	}

	virtual void forward(Blob** bottom, int numBottom, Blob** top, int numTop) {
		const int num = bottom[0]->num();
		const int channels = bottom[0]->channel();
		const int b0_height = bottom[0]->height();
		const int b0_width = bottom[0]->width();
		const int b1_height = bottom[1]->height();
		const int b1_width = bottom[1]->width();
		const float* b1_data = bottom[1]->cpu_data();
		float* top_data = top[0]->mutable_cpu_data();
		const int b0_dim = bottom[0]->count(1);
		const int b1_dim = bottom[1]->count(1);
		const int b0_spatial = bottom[0]->count(2);
		const int b1_spatial = bottom[1]->count(2);

		// correlation in kernel wise
		for (int n = 0; n < num; n++)
			for (int x = 0; x < b0_width; x++)
				for (int y = 0; y < b0_height; y++)
				{
					const float b1_x = (x + 1) / w_ratio_ - 1.0;
					const float b1_y = (y + 1) / h_ratio_ - 1.0;

					const int x_l = max(int(b1_x), 0);
					const int x_h = min(int(b1_x) + 1, b1_width - 1);
					const float wxl = int(b1_x) < 0 ? 0.0 : (1 - (b1_x - int(b1_x)));
					const float wxh = int(b1_x) + 1 > (b1_width - 1) ? 0.0 : (1 - wxl);

					const int y_l = max(int(b1_y), 0);
					const int y_h = min(int(b1_y) + 1, b1_height - 1);
					const float wyl = int(b1_y) < 0 ? 0.0 : (1 - (b1_y - int(b1_y)));
					const float wyh = int(b1_y) + 1 > (b1_height - 1) ? 0.0 : (1 - wyl);

					for (int c = 0; c < channels;c++)
					{
						float temp = 0.0;
						temp += wxl * wyl*b1_data[n*b1_dim + c * b1_spatial + y_l * b1_width + x_l];
						temp += wxh * wyl*b1_data[n*b1_dim + c * b1_spatial + y_l * b1_width + x_h];
						temp += wxl * wyh*b1_data[n*b1_dim + c * b1_spatial + y_h * b1_width + x_l];
						temp += wxh * wyh*b1_data[n*b1_dim + c * b1_spatial + y_h * b1_width + x_h];
						top_data[n*b0_dim + c * b0_spatial + y * b0_width + x] = temp;
					}
				}
	}

	virtual void backward(Blob** bottom, int numBottom, Blob** top, int numTop, const bool* propagate_down) {
		const int num = bottom[0]->num();
		const int channels = bottom[0]->channel();
		const int b0_height = bottom[0]->height();
		const int b0_width = bottom[0]->width();
		const int b1_height = bottom[1]->height();
		const int b1_width = bottom[1]->width();
		const float* b1_data = bottom[1]->cpu_data();
		const float* top_diff = top[0]->cpu_diff();
		float* b1_diff = bottom[1]->mutable_cpu_diff();
		const int b0_dim = bottom[0]->count(1);
		const int b1_dim = bottom[1]->count(1);
		const int b0_spatial = bottom[0]->count(2);
		const int b1_spatial = bottom[1]->count(2);

		if (propagate_down[1])
		{// backpropagate gradient for blob1
			caffe_set(bottom[1]->count(), float(0.0), b1_diff);
			for (int n = 0; n < num; n++)
				for (int x = 0; x < b0_width; x++)
					for (int y = 0; y < b0_height; y++)
					{
						const float b1_x = (x + 1) / w_ratio_ - 1.0;
						const float b1_y = (y + 1) / h_ratio_ - 1.0;

						const int x_l = max(int(b1_x), 0);
						const int x_h = min(int(b1_x) + 1, b1_width - 1);
						const float wxl = int(b1_x) < 0 ? 0.0 : (1 - (b1_x - int(b1_x)));
						const float wxh = int(b1_x) + 1 > (b1_width - 1) ? 0.0 : (1 - wxl);

						const int y_l = max(int(b1_y), 0);
						const int y_h = min(int(b1_y) + 1, b1_height - 1);
						const float wyl = int(b1_y) < 0 ? 0.0 : (1 - (b1_y - int(b1_y)));
						const float wyh = int(b1_y) + 1 > (b1_height - 1) ? 0.0 : (1 - wyl);

						for (int c = 0; c < channels;c++)
						{
							float temp = 0.0;
							b1_diff[n*b1_dim + c * b1_spatial + y_l * b1_width + x_l] += wxl * wyl*top_diff[n*b0_dim + c * b0_spatial + y * b0_width + x];
							b1_diff[n*b1_dim + c * b1_spatial + y_l * b1_width + x_h] += wxh * wyl*top_diff[n*b0_dim + c * b0_spatial + y * b0_width + x];
							b1_diff[n*b1_dim + c * b1_spatial + y_h * b1_width + x_l] += wxl * wyh*top_diff[n*b0_dim + c * b0_spatial + y * b0_width + x];
							b1_diff[n*b1_dim + c * b1_spatial + y_h * b1_width + x_h] += wxh * wyh*top_diff[n*b0_dim + c * b0_spatial + y * b0_width + x];
						}
					}
		}
	};

	virtual void reshape(Blob** bottom, int numBottom, Blob** top, int numTop) {
		top[0]->ReshapeLike(*bottom[0]);
	}

private:
	WPtr<Blob> diff_;
	int w_ratio_;
	int h_ratio_;
	Blob container_; // auxiliary container for backward gradients
};```
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部