LibTorch C++ possible problem in torch::data::transforms::Normalize<>

Tanmay_Pani: <p>Hi, I recently started using the C++ API, and need to standardize my tabular data similar to the python “sklearn.preprocessing.StandardScaler”. I did figure out the “map” utility that uses “torch::data::transforms” object, and atleast on paper, the torch::data::transforms::Normalize&lt;&gt; seems to be what I want. But applying that gives me unwanted dimensions, and it seems to arise from the two extra unsqueeze oprations I found in the implementation <a href="https://pytorch.org/cppdocs/api/program_listing_file_torch_csrc_api_include_torch_data_transforms_tensor.h.html" rel="noopener nofollow ugc">here</a>:</p>
<pre><code class="lang-auto">template &lt;typename Target = Tensor&gt;
struct Normalize : public TensorTransform&lt;Target&gt; {
  Normalize(ArrayRef&lt;double&gt; mean, ArrayRef&lt;double&gt; stddev)
      : mean(torch::tensor(mean, torch::kFloat32)
                 .unsqueeze(/*dim=*/1)
                 .unsqueeze(/*dim=*/2)),
        stddev(torch::tensor(stddev, torch::kFloat32)
                   .unsqueeze(/*dim=*/1)
                   .unsqueeze(/*dim=*/2)) {}

  torch::Tensor operator()(Tensor input) override {
    return input.sub(mean).div(stddev);
  }

  torch::Tensor mean, stddev;
};
</code></pre>
<p>I assume this is because it expects scalars for “mean” and “stddev” that have to be applied to an image? Is this intentional or a bug? because in its present form, using this for tabular data with 1-D rows becomes quite convoluted. Would it be possible to change it so that it accepts just torch::Tensor types for mean and stdDev, each element of the tensor corresponding to mean and stdDev of a feature column? with the onus of ensuring the matching of dimensions on the user?</p>

ptrblck: <p>I believe your guess is correct and the expected use case were images. Note that this transformation was added ~6 years ago in <a href="https://github.com/pytorch/pytorch/pull/15891">this PR</a> and I don’t know if the C++ API is maintained anymore, so you might want to implement a custom transformation without the <code>unsqeeze</code> calls.</p>

Tanmay_Pani: <p>Thanks <a class="mention" href="/u/ptrblck">@ptrblck</a> for the reply. For anyone looking for something similar, this is the sort of ad-hoc solution I use for my particular use case:</p>
<pre><code class="lang-auto">struct Normalize2 : public torch::data::transforms::TensorTransform&lt;torch::Tensor&gt; {
  Normalize2(std::vector&lt;double&gt; means, std::vector&lt;double&gt; stddevs):   
                mean(torch::tensor(means)), stddev(torch::tensor(stddevs)) {}

  torch::Tensor operator()(torch::Tensor input) override {
    torch::Tensor output = std::move(input);
    return output.sub(mean).div(stddev);
  }

  torch::Tensor mean, stddev;
};
</code></pre>
<p>I was hoping someone maintaining libtorch could implement a more generalized version of this, but I guess that wont be the case now <img src="https://discuss.pytorch.org/images/emoji/apple/sweat_smile.png?v=12" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20">.</p>
<p>Btw, maybe a newbie question, but what C++ ML library would you recommend instead of libtorch (since I get the vibes that it isnt maintained and documentation is very sparse)? For more context, I am a physics grad student, who was using tensorflow in python until a week ago. I just want to migrate to C++ because I like it better than python</p>

ptrblck: <aside class="quote no-group" data-username="Tanmay_Pani" data-post="3" data-topic="200637">
<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/tanmay_pani/48/69124_2.png" class="avatar"> Tanmay_Pani:</div>
<blockquote>
<p>I just want to migrate to C++ because I like it better than python</p>
</blockquote>
</aside>
<p>This is an interesting take as usually it’s the other way. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=12" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"><br>
I honestly don’t know which framework I would recommend and would hope the <code>libtorch</code> C++ API will be maintained (even if not further developed). <a class="mention" href="/u/alband">@albanD</a> might have more insight here.</p>

Tanmay_Pani: <aside class="quote no-group" data-username="ptrblck" data-post="4" data-topic="200637">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>This is an interesting take as usually it’s the other way. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=12" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Yeah I would probably have been the same if our community didn’t use <a href="https://root.cern/about/" rel="noopener nofollow ugc">the ROOT C++ data analysis framework</a>, a framework optimized for fast and efficient analysis of millions of collider events, which has us already write almost all of our analyses in C++. I almost entirely use python just for TensorFlow.</p>

albanD: <p>Hey!</p>
<p>I think it depends a little bit what you are looking for.<br>
libtorch will most likely be your best bet for very wide coverage and good performance. You will give up on the ML Compiler tools like torch.compile though, cool python-level extension points, the nn/optim/distributed APIs there are not really worked on either. But foundamental components like kernels, autograd, etc that are used from python will defintely continue to work as expected.</p>
<p>If you’re looking for a more c++ centric option and for a more research-y framework, <a href="https://github.com/flashlight/flashlight" class="inline-onebox">GitHub - flashlight/flashlight: A C++ standalone library for machine learning</a> is an actively developed one that I know of. There might be others as well but I don’t know off the top of my head.</p>