\copydoc Layer::Forward(int flag, const Tensor&)
| 105 | |
| 106 | /// \copydoc Layer::Forward(int flag, const Tensor&) |
| 107 | const Tensor Convolution::Forward(int flag, const Tensor &input) { |
| 108 | CHECK(buf_.empty()); |
| 109 | CHECK_EQ(input.device()->lang(), kCpp); |
| 110 | CHECK_EQ(input.nDim(), 4u); |
| 111 | if (flag & kTrain) buf_.push(input); |
| 112 | size_t batchsize = input.shape(0); |
| 113 | size_t imagesize = input.Size() / batchsize; |
| 114 | // TODO(wangwei) update the layer config if the input sample shape changes |
| 115 | CHECK(input.shape(1) == channels_ && input.shape(2) == height_ && |
| 116 | input.shape(3) == width_) << "input sample shape should not change"; |
| 117 | DataType dtype = input.data_type(); |
| 118 | auto dev = input.device(); |
| 119 | Shape shape{batchsize, num_filters_, conv_height_, conv_width_}; |
| 120 | Tensor output(shape, dev, dtype); |
| 121 | Tensor col_data(Shape{col_height_, col_width_}); |
| 122 | float *data_col = new float[col_height_ * col_width_]; |
| 123 | auto in_data = input.data<float>(); |
| 124 | for (size_t b = 0; b < batchsize; b++) { |
| 125 | Im2col(in_data + b * imagesize, channels_, height_, width_, kernel_h_, |
| 126 | kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, data_col); |
| 127 | col_data.CopyDataFromHostPtr(data_col, col_height_ * col_width_); |
| 128 | Tensor each = Mult(weight_, col_data); |
| 129 | if (bias_term_) { |
| 130 | AddColumn(bias_, &each); |
| 131 | } |
| 132 | CopyDataToFrom(&output, each, each.Size(), b * each.Size()); |
| 133 | } |
| 134 | delete[] data_col; |
| 135 | return output; |
| 136 | } |
| 137 | |
| 138 | /// \copydoc Layer::Backward(int, const Tensor&, const Tensor&); |
| 139 | const std::pair<Tensor, vector<Tensor>> Convolution::Backward( |
nothing calls this directly
no test coverage detected