Hi, I’m starting playing with the C++ Front-end and I wanted to know what would be the most correct way of using auto-differentiation to compute the derivatives or arbitrary functions with respect to different parameters.
I wrote the following minimal toy-example where I just wanted to see how to compute the derivative of pointsInFrame1
with respect a change on pointsInFrame0
(in particular just the first dimension of the pointsInFrame1 vector). In order to do that I used pointsInFrame1ActiveDerivatives
to indicate that I wanted the derivative with respect to the first dimension, however I wonder if there is a cleaner way of doing this?
#include <torch/torch.h>
#include <iostream>
int main ()
{
// One tensor containing one homogeneous 3D point in frame0 coordinates
torch::Tensor pointsInFrame0 = torch::empty(4);
pointsInFrame0[0] = -12.0;
pointsInFrame0[1] = 13.0;
pointsInFrame0[2] = -14.0;
pointsInFrame0[3] = 1.0;
pointsInFrame0.set_requires_grad(true);
std::cout << "pointsInFrame0:\n" << pointsInFrame0 << "\n";
// One tensor containing a 4x4 isometry transformation matrix, transforming
// world coordinates to frame0 coordinates
torch::Tensor frame0FromWorld = torch::zeros({4,4});
frame0FromWorld[0][0] = std::sqrt(3.0)/2.0;
frame0FromWorld[0][1] = -1.0/2.0;
frame0FromWorld[1][0] = 1.0/2.0;
frame0FromWorld[1][1] = std::sqrt(3.0)/2.0;
frame0FromWorld[2][2] = 1.0;
frame0FromWorld[3][3] = 1.0;
frame0FromWorld.set_requires_grad(true);
std::cout << "frame0FromWorld:\n" << frame0FromWorld << "\n";
// One tensor containing a 4x4 isometry transformation matrix, transforming
// world coordinates to frame1 coordinates
torch::Tensor frame1FromWorld = torch::zeros({4,4});
frame1FromWorld[0][0] = 1.0;
frame1FromWorld[0][3] = -2.0;
frame1FromWorld[1][1] = 1.0;
frame1FromWorld[1][3] = 3.0;
frame1FromWorld[2][2] = 1.0;
frame1FromWorld[2][3] = -4.0;
frame1FromWorld[3][3] = 1.0;
frame1FromWorld.set_requires_grad(true);
std::cout << "frame1FromWorld:\n" << frame1FromWorld << "\n";
// One tensor containing the transformed 3D points in frame1 coordinates
torch::Tensor pointsInFrame1 = at::matmul(frame1FromWorld, at::matmul(torch::inverse(frame0FromWorld), pointsInFrame0));
std::cout << "pointsInFrame1:\n" << pointsInFrame1 << "\n";
// One tensor computing the partial derivatives dpointsInFrame1/dpointsInFrame0
torch::Tensor pointsInFrame1ActiveDerivatives = torch::zeros({4});
pointsInFrame1ActiveDerivatives[0] = 1; // <-- NOTE: my intention is to compute dpointsInFrame1.x/dpointsInFrame0
pointsInFrame1.backward(pointsInFrame1ActiveDerivatives);
std::cout << "dpointsInFrame1/dpointsInFrame0:\n" << pointsInFrame0.grad() << "\n";
// Check expected output
torch::Tensor expectedPointsInFrame1Derivatives = torch::empty({4});
expectedPointsInFrame1Derivatives[0] = 0.86604;
expectedPointsInFrame1Derivatives[1] = 0.50002;
expectedPointsInFrame1Derivatives[2] = 0.00000;
expectedPointsInFrame1Derivatives[3] = -2.00000;
assert((pointsInFrame0.grad()-expectedPointsInFrame1Derivatives).norm().item<float>() < 5e-5);
}
Thanks a lot in advance!