Simple RNN example not working

Maverobot: <p>Hello,</p>
<p>I was trying to learn the RNN interfaces which libtorch provides. Sadly, a simple code like the following throws out runtime error <img src="https://discuss.pytorch.org/images/emoji/apple/frowning.png?v=9" title=":frowning:" class="emoji" alt=":frowning:"></p>
<pre><code class="lang-auto">#include &lt;torch/torch.h&gt;
int main(int /*argc*/, char* /*argv*/[]) {
  // Use GPU when present, CPU otherwise.
  torch::Device device(torch::kCPU);
  if (torch::cuda::is_available()) {
    device = torch::Device(torch::kCUDA);
    std::cout &lt;&lt; "CUDA is available! Training on GPU." &lt;&lt; std::endl;
  }

  torch::nn::Sequential time_serie_detector(
      torch::nn::RNN(torch::nn::RNNOptions(1, 10).dropout(0.2).layers(2).tanh()));
  time_serie_detector-&gt;to(device);
  std::cout &lt;&lt; time_serie_detector &lt;&lt; std::endl;

  auto x = torch::ones(1).toBackend(c10::Backend::CUDA);
  auto a = torch::ones(10).toBackend(c10::Backend::CUDA);
  std::cout &lt;&lt; "x = " &lt;&lt; x &lt;&lt; std::endl;
  std::cout &lt;&lt; "a = " &lt;&lt; a &lt;&lt; std::endl;

  time_serie_detector-&gt;forward(x, a);
  time_serie_detector-&gt;zero_grad();

  return 0;
}

</code></pre>
<p>The error is as follows:</p>
<pre><code class="lang-auto">terminate called after throwing an instance of 'c10::IndexError'
  what():  Dimension out of range (expected to be in range of [-1, 0], but got 2) (maybe_wrap_dim at ../../c10/core/WrapDimMinimal.h:20)
</code></pre>
<p>I am pretty new to libtorch and pytorch in general. I guess I made some terribly stupid mistakes here… It would be nice if someone could help me out.</p>
<p>By the way, I was trying to find C++ example using <code>torch::nn::RNN</code> online but failed to find any. I would really appreciate some existing examples.</p>
<p>Cheers</p>

tom: <p>I think you are not passing in the right shapes - RNNs expect a seq x batch x feature input and output something of that shape (with the number of features potentially different). The hidden state would be batch x num_hidden (or a tuple of two things).<br>
Bidirectional RNNs double output features and num_hidden.</p>
<aside class="quote no-group quote-modified" data-username="Maverobot" data-post="1" data-topic="56511">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/maverobot/48/16130_2.png" class="avatar"> Maverobot:</div>
<blockquote>
<p>I am pretty new to libtorch and pytorch in general. …  It would be nice if someone could help me out.</p>
</blockquote>
</aside>
<p>We all started somewhere, but yes, it may be wise to follow one of the RNN-based tutorials, e.g. <a href="https://pytorch.org/tutorials/intermediate/char_rnn_generation_tutorial.html" rel="noopener nofollow ugc">Name generation one</a>.<br>
Given that the C++ library follows the Python one so closely, the Python tutorials are applicable here.</p>
<p>Best regards</p>
<p>Thomas</p>

Maverobot: <p>I have got a working code snippet in case anyone else faces the same issue.</p>
<pre><code class="lang-auto">#include &lt;torch/torch.h&gt;

template &lt;typename T&gt;
void pretty_print(const std::string&amp; info, T&amp;&amp; data) {
  std::cout &lt;&lt; info &lt;&lt; std::endl;
  std::cout &lt;&lt; data &lt;&lt; std::endl &lt;&lt; std::endl;
}

int main(int /*argc*/, char* /*argv*/[]) {
  // Use GPU when present, CPU otherwise.
  torch::Device device(torch::kCPU);
  if (torch::cuda::is_available()) {
    device = torch::Device(torch::kCUDA);
    std::cout &lt;&lt; "CUDA is available! Training on GPU." &lt;&lt; std::endl;
  }

  const size_t kSequenceLen = 1;
  const size_t kInputDim = 1;
  const size_t kHiddenDim = 5;
  const size_t kOuputDim = 1;
  auto time_serie_detector = torch::nn::LSTM(torch::nn::LSTMOptions(kInputDim, kHiddenDim)
                                                 .dropout(0.2)
                                                 .layers(kSequenceLen)
                                                 .bidirectional(false));
  time_serie_detector-&gt;to(device);
  std::cout &lt;&lt; time_serie_detector &lt;&lt; std::endl;

  torch::Tensor input = torch::empty({kSequenceLen, kInputDim});
  torch::Tensor state = torch::zeros({2, kSequenceLen, kHiddenDim});
  auto input_acc = input.accessor&lt;float, 2&gt;();
  size_t count = 0;
  for (float i = 0.1; i &lt; 0.4; i += 0.1) {
    input_acc[count][0] = i;
    count++;
  }
  input = input.toBackend(c10::Backend::CUDA);
  state = state.toBackend(c10::Backend::CUDA);
  std::cout &lt;&lt; "input = " &lt;&lt; input &lt;&lt; std::endl;
  time_serie_detector-&gt;zero_grad();

  auto i_tmp = input.view({input.size(0), 1, -1});
  auto s_tmp = state.view({2, state.size(0) / 2, 1, -1});

  pretty_print("input: ", i_tmp);
  pretty_print("state: ", s_tmp);

  auto rnn_output = time_serie_detector-&gt;forward(i_tmp, s_tmp);
  pretty_print("rnn_output/output: ", rnn_output.output);
  pretty_print("rnn_output/state: ", rnn_output.state);

  return 0;
}
</code></pre>