Convolving an input tensor of shape (3, 20, 30)
(channel-first notation) with 8
filters of shape (3, 5, 7)
should result in a tensor of shape (8, 24, 16)
. I'm trying to implement this using Eigen::Tensor::convolve
, but the resulting shape is (1, 24, 16)
. So it seems like only one of the filters is applied instead of all 8
.
Here is a minimal example:
#include <cassert>
#include <iostream>
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
int main() {
int input_height = 20;
int input_width = 30;
int input_channels = 3;
int kernels_height = 5;
int kernels_width = 7;
int kernels_channels = 3;
int kernel_count = 8;
assert(kernels_channels == input_channels);
int expected_output_height = input_height + 1 - kernels_height;
int expected_output_width = input_width + 1 - kernels_width;
int expected_output_channels = kernel_count;
Eigen::Tensor<float, 3> input(input_channels, input_width, input_height);
Eigen::Tensor<float, 4> filters(kernels_channels, kernels_width, kernels_height, kernel_count);
Eigen::array<ptrdiff_t, 3> dims({0, 1, 2});
Eigen::Tensor<float, 3> output = input.convolve(filters, dims);
const Eigen::Tensor<float, 3>::Dimensions& d = output.dimensions();
std::cout << "Expected output shape: (" << expected_output_channels << ", " << expected_output_width << ", " << expected_output_height << ")" << std::endl;
std::cout << "Actual shape: (" << d[0] << ", " << d[1] << ", " << d[2] << ")" << std::endl;
}
And its output:
Expected output shape: (8, 24, 16)
Actual shape: (1, 24, 16)
Sure, one could iterate over the filters one by one and call .convolve
for each one but this
- would result in a tensor with the channels not being the first dimension
- might not be as performance-optimized as doing all in one call
- requires more custom code
So I guess I'm doing something wrong in my usage of the Eigen library. How is it done correctly?