आकार के एक इनपुट टेंसर (3, 20, 30) (चैनल-प्रथम संकेतन) को 8 आकार के फिल्टर (3, 5, 7) के साथ जोड़ने से आकार का टेंसर (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;
}

और इसका आउटपुट:

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

ज़रूर, कोई एक-एक करके फ़िल्टर पर पुनरावृति कर सकता है और .convolve को कॉल कर सकता है। हर एक के लिए लेकिन यह

  • चैनलों के साथ पहला आयाम नहीं होने के परिणामस्वरूप एक टेंसर होगा
  • एक कॉल में सभी करने के रूप में प्रदर्शन-अनुकूलित नहीं हो सकता है
  • अधिक कस्टम कोड की आवश्यकता है

तो मुझे लगता है कि मैं ईजिन लाइब्रेरी के उपयोग में कुछ गलत कर रहा हूं। इसे सही तरीके से कैसे किया जाता है?

6
Tobias Hermann 10 नवम्बर 2019, 15:00

1 उत्तर

सबसे बढ़िया उत्तर

यह एक साथ कई कर्नेल के साथ कनवल्शन का समर्थन नहीं करता (docs) :

आउटपुट टेंसर के आयामों के लिए आयाम आकार जो कि कनवल्शन का हिस्सा थे, को सूत्र द्वारा कम किया जाएगा: output_dim_size = input_dim_size - kernel_dim_size + 1 (आवश्यक: input_dim_size>= kernel_dim_size)। उन आयामों के आयाम आकार जो कनवल्शन का हिस्सा नहीं थे, वही रहेंगे।

ऊपर के अनुसार expected_output_channels 1 = 3 - 3 + 1 के बराबर होना चाहिए।

मुझे नहीं लगता कि जैसा आप चाहते हैं वैसा करना संभव होना चाहिए, क्योंकि कनवल्शन ऑपरेशन एक गणितीय है और अच्छी तरह से परिभाषित है, इसलिए यह अजीब होगा यदि यह गणित की परिभाषा का पालन नहीं करेगा।

परीक्षण नहीं किया गया समाधान

मैंने जांच नहीं की, लेकिन मेरा मानना ​​​​है कि अगला कोड आपकी इच्छानुसार आउटपुट उत्पन्न करता है:

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

जैसा कि आप देख सकते हैं, पहली और तीसरी समस्या कोई बड़ी समस्या नहीं है। आशा है कि आप भाग्यशाली होंगे और कोड का यह हिस्सा आपकी अड़चन नहीं होगा :)

2
MrPisarik 18 नवम्बर 2019, 21:04