簡體   English   中英

如何使用 Eigen::Tensor::convolve 與多個內核?

[英]How to use Eigen::Tensor::convolve with multiple kernels?

將形狀為(3, 20, 30)的輸入張量(通道優先表示法)與形狀為(3, 5, 7)8個過濾器進行卷積應該得到形狀為(8, 24, 16)的張量。 我正在嘗試使用Eigen::Tensor::convolve來實現它,但結果形狀是(1, 24, 16) 因此,似乎只應用了一個過濾器而不是全部8個。

這是一個最小的例子:

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

及其output:

Expected output shape: (8, 24, 16)
Actual shape: (1, 24, 16)

當然,可以一個一個地遍歷過濾器並為每個過濾器調用.convolve但這

  • 會導致張量的通道不是第一維
  • 可能不如一次性完成所有性能優化
  • 需要更多自定義代碼

所以我想我在使用 Eigen 庫時做錯了什么。 它是如何正確完成的?

它不支持同時使用多個內核進行卷積( 文檔):

作為卷積一部分的 output 張量的維度的維度大小將通過以下公式減少:output_dim_size = input_dim_size - kernel_dim_size + 1(要求:input_dim_size >= kernel_dim_size)。 不屬於卷積的維度的維度大小將保持不變。

根據上面的expected_output_channels應該等於1 = 3 - 3 + 1

我不認為應該可以如你所願,因為卷積運算是一種數學運算並且定義明確,所以如果它不遵循數學定義會很奇怪。

未測試的解決方案

我沒有檢查,但我相信下一個代碼會如您所願產生 output :

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::Tensor<float, 3> output(kernel_count, expected_output_width, expected_output_height);

Eigen::array<ptrdiff_t, 3> dims({0, 1, 2});

for (int i = 0; i < kernel_count; ++i){
    output.chip(i, 0) = input.convolve(filters.chip(i, 3), dims).chip(0, 0);
}

如您所見,第一個和第三個問題都不是大問題。 希望你會很幸運,這部分代碼不會成為你的瓶頸:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM