What exactly are ModuleHolders in libtorch

username: a_d
cooked: <p>Hello all,<br>
I am fairly new to libtorch and trying to recreate a model that I had once written in python. It consists of multiple blocks, something like that of a resnet.<br>
Following an example, I create a custom class and register each of its members. However, I am not able to register my custom Block. My code is as follows -</p>
<pre><code class="lang-auto">#include "PredictFrame.h"
#include &lt;cmath&gt;
using namespace std;

int calcInterim(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel){
    return int(floor((kernel-&gt;at(0)*kernel-&gt;at(1)*kernel-&gt;at(2)*in_channels*out_channels)/
                             ((kernel-&gt;at(1)*kernel-&gt;at(2)*in_channels)+(kernel-&gt;at(0)*out_channels))));
};

Block::Block(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel,
             ExpandingArray&lt;3UL&gt; stride, ExpandingArray&lt;3UL&gt; padding):

spatialConv(torch::nn::Conv3dOptions(in_channels, calcInterim(in_channels, out_channels, kernel), {1, kernel-&gt;at(1), kernel-&gt;at(2)})
.stride({1, stride-&gt;at(1), stride-&gt;at(2)}).padding({0, padding-&gt;at(1), padding-&gt;at(2)})),

temporalConv(torch::nn::Conv3dOptions(calcInterim(in_channels, out_channels, kernel), out_channels, {kernel-&gt;at(0),1,1})
.stride({stride-&gt;at(0), 1,1}).padding({padding-&gt;at(0),1,1})),
norm3D(torch::nn::BatchNorm3dOptions(calcInterim(in_channels, out_channels, kernel))){
    register_module("block_spatial_conv", spatialConv);
    register_module("block_temporal_conv", temporalConv);
    register_module("block_norm", norm3D);
}

torch::Tensor Block::forward(const torch::Tensor&amp; input) {
    auto output = spatialConv(input);
    output = norm3D(output);
    output = torch::nn::functional::relu(output);
    output = temporalConv(output);
    return output;
}

ResidualBlock::ResidualBlock(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel, ExpandingArray&lt;3UL&gt; stride,
                             ExpandingArray&lt;3UL&gt; padding):
conv1(in_channels, out_channels, kernel, stride, padding),
conv2(out_channels, out_channels, kernel, stride, padding),
norm3D(out_channels){
    register_module&lt;Block&gt;("conv1_res", torch::nn::ModuleHolder&lt;Block&gt;(make_shared&lt;Block&gt;(conv1)));
    register_module&lt;Block&gt;("conv2_res", torch::nn::ModuleHolder&lt;Block&gt;(make_shared&lt;Block&gt;(conv2)));
    register_module("norm3D_res", norm3D);
}

torch::Tensor ResidualBlock::forward(const torch::Tensor&amp; input) {
    auto out= conv1.forward(input);
    out = norm3D(out);
    auto out1 = torch::nn::functional::relu(out);
    out = conv2.forward(out);
    out = norm3D(out);
    return (out1+out);
}

R2plus1D::R2plus1D(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel,
                   ExpandingArray&lt;3UL&gt; stride, ExpandingArray&lt;3UL&gt; padding, int depth):
                   layer1(in_channels, out_channels, kernel, stride, padding) {
    register_module&lt;ResidualBlock&gt;("resBlock1", torch::nn::ModuleHolder&lt;ResidualBlock&gt;(make_shared&lt;ResidualBlock&gt;(layer1)));
    for (int i = 0; i &lt; depth; ++i)
        moduleList-&gt;push_back(ResidualBlock(out_channels, out_channels, kernel, stride, padding));
    layers(moduleList);
}

torch::Tensor R2plus1D::forward(const Tensor &amp;input) {
    auto out = layer1.forward(input);
    out = layers-&gt;forward(out);
    return out;
}

PredictFrame::PredictFrame():
conv1(3, 64, ExpandingArray&lt;3ul&gt;{3, 5, 5}, ExpandingArray&lt;3UL&gt;{1, 2, 2}, ExpandingArray&lt;3UL&gt;{1, 3, 3})
{
    register_module("PredictFrame_block", torch::nn::ModuleHolder&lt;Block&gt;(make_shared&lt;Block&gt;(conv1)));
    moduleList-&gt;push_back(R2plus1D(64, 64, {3,3,3}, {1,1,1}, {1,1,1}, 1));
    moduleList-&gt;push_back(R2plus1D(64, 128, {3,3,3}, {1,1,1}, {1,1,1}, 1));
    moduleList-&gt;push_back(R2plus1D(128, 256, {3, 3, 3}, {1, 1, 1}, {1, 1, 1}, 1));
    moduleList-&gt;push_back(R2plus1D(256, 512, {3, 3, 3}, {1, 1, 1}, {1, 1, 1}, 1));
    sequential(moduleList);
}

torch::Tensor PredictFrame::forward(const torch::Tensor&amp; input) {
    auto out = conv1.forward(input);
    return sequential-&gt;forward(out);
}
</code></pre>
<p>The header file is as follows -</p>
<pre><code class="lang-auto">//
// Created by atharva on 02/10/20.
//

#ifndef SUPERTUX_RL_PREDICTFRAME_H
#define SUPERTUX_RL_PREDICTFRAME_H

#include &lt;torch/torch.h&gt;
#include &lt;cmath&gt;

using namespace torch;
using namespace std;


class Block : public torch::nn::Module{
public:
    Block(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel,
          ExpandingArray&lt;3UL&gt; stride, ExpandingArray&lt;3UL&gt; padding);
    torch::Tensor forward(const torch::Tensor&amp; input);

private:
    torch::nn::Conv3d spatialConv{nullptr};
    torch::nn::Conv3d temporalConv{nullptr};
    torch::nn::BatchNorm3d norm3D{nullptr};
};


class ResidualBlock : public torch::nn::Module{
public:
    ResidualBlock(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel, ExpandingArray&lt;3UL&gt; stride,
                  ExpandingArray&lt;3UL&gt; padding);
    torch::Tensor forward(const torch::Tensor&amp; input);

private:
    Block conv1;
    Block conv2;
    torch::nn::BatchNorm3d norm3D{nullptr};
};

class R2plus1D : public torch::nn::Module{
public:
    R2plus1D(int in_channels, int out_channels, ExpandingArray&lt;3UL&gt; kernel, ExpandingArray&lt;3UL&gt; stride, ExpandingArray&lt;3UL&gt; padding,
             int depth);
    torch::Tensor forward(const torch::Tensor&amp; input);

private:
    ResidualBlock layer1;
    torch::nn::ModuleList moduleList;
    torch::nn::Sequential layers;
};

class PredictFrame : public torch::nn::Module{
public:
    PredictFrame();
    torch::Tensor forward(const torch::Tensor&amp; input);
private:
    Block conv1;
    torch::nn::ModuleList moduleList;
    torch::nn::Sequential sequential;

};


#endif //SUPERTUX_RL_PREDICTFRAME_H

</code></pre>
<p>As in the code above, I have used <code>torch::nn::ModuleHolder(make_shared&lt;Block&gt;(conv1))</code> to not get an error. But I am not understanding what I am doing over here, and am I on the correct path. Any help would be appreciated.<br>
TIA</p>
<p>Edit - It does not work, on compilation  I get the following error -</p>
<pre><code class="lang-auto">[ 33%] Building CXX object CMakeFiles/SuperTux_RL.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/SuperTux_RL.dir/PredictFrame.cpp.o
In file included from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/modules/container/any_value.h:5,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/modules/container/any_module_holder.h:3,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/module.h:3,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/cloneable.h:3,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn.h:3,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/all.h:13,
                 from /home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/torch.h:3,
                 from /home/atharva/CLionProjects/SuperTux_RL/PredictFrame.h:8,
                 from /home/atharva/CLionProjects/SuperTux_RL/PredictFrame.cpp:5:
/home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/pimpl.h: In instantiation of ‘torch::detail::return_type_of_forward_t&lt;Contained, Args ...&gt; torch::nn::ModuleHolder&lt;Contained&gt;::operator()(Args&amp;&amp; ...) [with Args = {torch::nn::ModuleList&amp;}; Contained = torch::nn::SequentialImpl; torch::detail::return_type_of_forward_t&lt;Contained, Args ...&gt; = void]’:
/home/atharva/CLionProjects/SuperTux_RL/PredictFrame.cpp:61:22:   required from here
/home/atharva/libtorch/libtorch/include/torch/csrc/api/include/torch/nn/pimpl.h:125:56: error: return-statement with a value, in function returning ‘torch::detail::return_type_of_forward_t&lt;torch::nn::SequentialImpl, torch::nn::ModuleList&amp;&gt;’ {aka ‘void’} [-fpermissive]
     return impl_-&gt;forward(::std::forward&lt;Args&gt;(args)...);
                                                        ^
make[2]: *** [CMakeFiles/SuperTux_RL.dir/build.make:76: CMakeFiles/SuperTux_RL.dir/PredictFrame.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/SuperTux_RL.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
</code></pre>
<p>Could anyone please tell me the correct way of doing this?</p>