title: How to use Datasets with the Pytorch C++ API with simple float I/O Data?
body: <p>I'm trying to use the Pytorch C++ API to train a simple neural net that has float input and output values. The Values are saved in "input.csv" and a output.csv" files. There are just 10x10 inputs and outputs that represent the negation. So if the input is 1 the output is 0.</p>
  
  <p>I was able to build a simple neural net by creating input and output tensors manually. The code for this is on my repo in the master branch that you can find here: <a href="https://github.com/shyney7/libtorch_win_test" rel="nofollow noreferrer">master branch repo</a>.</p>
  
  <p>But now I wanted to use <code>torch::data::make_data_loader</code> and <code>torch::data::datasets</code> to make my own custom dataset and being able to shuffle my data and also to create batch sizes for the training loop.</p>
  
  <p>Unfortunately all of the examples and tutorials for the pytorch cpp API only show how to do it for complex image recognition. These examples are way to complicated for a programming beginner like me. (Just started programming a few months ago)</p>
  
  <p>I've tried it myself by creating a custom dataset class as shown in most examples and then using this class to make a dataloader. You can find it here: <a href="https://github.com/shyney7/libtorch_win_test/tree/dataset_test" rel="nofollow noreferrer">dataset test branch</a>.</p>
  
  <p>I've been following a Chinese tutorial since this was the only tutorial that was somewhat beginner friendly: <a href="https://www.pytorchtutorial.com/pytorch-c-api-2-custom-data-loading/" rel="nofollow noreferrer">Chinese Tutorial</a>.</p>
  
  <p>I think what I want to accomplish is something like in this python tutorial:
  <a href="https://github.com/hunkim/PyTorchZeroToAll/blob/master/08_1_dataset_loader.py" rel="nofollow noreferrer">pytorch dataset loader with python</a></p>
  
  <p>Here is my Class defined in src/owndata.cpp:</p>
  
  <pre><code>#include &lt;fstream&gt;
  #include &lt;iostream&gt;
  #include &lt;sstream&gt;
  #include &lt;string&gt;
  #include &lt;torch/torch.h&gt;
  #include &lt;vector&gt;
  //#include "include/owndata.h"
  
  //----------------------Funktionsprototyp Onelinevector----------------------
  
  std::vector&lt;float&gt;
  onelinevector(const std::vector&lt;std::vector&lt;float&gt;&gt; &amp;invector);
  
  //------------------------Funktionsprototyp csv2Dvector----------------------
  
  std::vector&lt;std::vector&lt;float&gt;&gt; csv2Dvector(std::string inputFileName);
  
  //-------------------Custom Dataset Class------------------------------------
  
  class CustomDataset : public torch::data::datasets::Dataset&lt;CustomDataset&gt; {
  
  private:
  std::vector&lt;std::vector&lt;float&gt;&gt; xdata, ydata;
  torch::Tensor outputtensor, inputtensor;
  public:
  CustomDataset(std::string xpath, std::string ypath) {
      xdata = csv2Dvector(xpath);
      ydata = csv2Dvector(ypath);
  
      //create input tensor:
      unsigned int ivsize = xdata.size() * xdata.front().size();
      std::vector&lt;float&gt; olinevec(ivsize);
      olinevec = onelinevector(xdata);
  
      inputtensor = torch::from_blob(
        olinevec.data(), {static_cast&lt;unsigned int&gt;(xdata.size()),
                          static_cast&lt;unsigned int&gt;(xdata.front().size())});
      //create output tensor:
      unsigned int ovsize = ydata.size() * ydata.front().size();
      std::vector&lt;float&gt; iovec(ovsize);
      iovec = onelinevector(ydata);
  
      outputtensor = torch::from_blob(
        iovec.data(), {static_cast&lt;unsigned int&gt;(ydata.size()),
                          static_cast&lt;unsigned int&gt;(ydata.front().size())});
  };
  
  torch::data::Example&lt;&gt; get(size_t index) override {
  
      torch::Tensor sample_input = inputtensor[index];
      torch::Tensor sample_output = outputtensor[index];
  
      return {sample_input.clone(), sample_output.clone()};
  };
  
  // Return the length of data
  torch::optional&lt;size_t&gt; size() const override {
      return ydata.size();
    };
  
  };
  
  size_t batch_size = 5;
  
  //-----------------------------NETZDEFINITION-----------------------------
  struct MeinNetz : torch::nn::Module {
    MeinNetz() {
      fc1 = register_module("fc1", torch::nn::Linear(10, 10));
      fc2 = register_module("fc2", torch::nn::Linear(10, 10));
    }
  
    torch::Tensor forward(torch::Tensor x) {
      x = torch::relu(fc1-&gt;forward(x));
      x = fc2-&gt;forward(x);
      return x;
    }
  
    torch::nn::Linear fc1{nullptr}, fc2{nullptr};
  };
  
  
  //-------------------------------------main-Funktion-------------------------
  
  int main() {
  
    auto custom_dataset = CustomDataset("input.csv","output.csv");
    auto data_loader = torch::data::make_data_loader&lt;torch::data::samplers::SequentialSampler&gt;(std::move(custom_dataset),batch_size);
  
    auto dataset_size = custom_dataset.size().value();
    int n_epochs = 50;
  
    auto net = std::make_shared&lt;MeinNetz&gt;();
  
    torch::optim::SGD optimizer(net-&gt;parameters(), 0.2);
  
    for(int epoch=1; epoch&lt;=n_epochs; epoch++) {
      for(auto&amp; batch: *data_loader) {
        auto data = batch.data;
        auto target = batch.target;
  
        data = data.to(torch::kF32);
        target = target.to(torch::kF32);
  
        optimizer.zero_grad();
  
        auto prediction = net-&gt;forward(data);
        auto loss = torch::mse_loss(prediction, target);
  
        loss.backward();
  
        optimizer.step();
  
        std::cout &lt;&lt; "Epoch: " &lt;&lt; epoch &lt;&lt; " Loss: " 
        &lt;&lt; loss.item&lt;float&gt;() &lt;&lt; std::endl;
      }
    }
  
    return 0;
  }
  
  //--------------------------Funktionen--------------------------------------------
  
  std::vector&lt;float&gt;
  onelinevector(const std::vector&lt;std::vector&lt;float&gt;&gt; &amp;invector) {
  
    std::vector&lt;float&gt; v1d;
    if (invector.size() == 0)
      return v1d;
    v1d.reserve(invector.size() * invector.front().size());
  
    for (auto &amp;innervector : invector) {
      v1d.insert(v1d.end(), innervector.begin(), innervector.end());
    }
  
    return v1d;
  }
  
  //-------------------------csv2vector Funktionsdefinition--------------------------
  
  std::vector&lt;std::vector&lt;float&gt;&gt; csv2Dvector(std::string inputFileName) {
    using namespace std;
  
    vector&lt;vector&lt;float&gt;&gt; data;
    ifstream inputFile(inputFileName);
    int l = 0;
  
    while (inputFile) {
      l++;
      string s;
      if (!getline(inputFile, s))
        break;
      if (s[0] != '#') {
        istringstream ss(s);
        vector&lt;float&gt; record;
  
        while (ss) {
          string line;
          if (!getline(ss, line, ','))
            break;
          try {
            record.push_back(stof(line));
          } catch (const std::invalid_argument e) {
            cout &lt;&lt; "NaN found in file " &lt;&lt; inputFileName &lt;&lt; " line " &lt;&lt; l
                 &lt;&lt; endl;
            e.what();
          }
        }
  
        data.push_back(record);
      }
    }
  
    if (!inputFile.eof()) {
      cerr &lt;&lt; "Could not read file " &lt;&lt; inputFileName &lt;&lt; "\n";
      throw invalid_argument("File not found.");
    }
  
    return data;
  }
  </code></pre>
  
  <p>This is not working at all.</p>
  
  <p>PS: there is also an example with Python from the pytorch repo but it's way more complicated than the Chinese example: <a href="https://github.com/pytorch/examples/blob/master/cpp/custom-dataset/custom-dataset.cpp" rel="nofollow noreferrer">python example for image import 2.</a></p>