LibTorch 支持自动微分, 一般情况下可以调用 backward()
函数直接计算,和 python 操作基本一致。
torch::Tensor x = torch::tensor({2.0});
torch::Tensor w = torch::tensor({3.0}, torch::requires_grad());
torch::Tensor b = torch::tensor({4.0}, torch::requires_grad());
torch::Tensor y = w * x + b;
y.backward();
std::cout << w.grad() << std::endl;
std::cout << b.grad() << std::endl;
注意:只有浮点和复数可以获取梯度。
已经计算的张量也是可以通过修改 required_grad
属性,但获取梯度需要重新执行计算,接着上面的代码:
std::cout << x.requires_grad() << std::endl;
x.requires_grad_(true);
std::cout << x.grad() << std::endl;
y.backward();
std::cout << x.requires_grad() << std::endl;
注意:libtorch 默认不保留计算图,如果想要得到正确的结果需要第一次计算梯度时候设置相关参数,并且清除已有梯度。
雅可比矩阵
对于
如果向量是$v=[1, 2, 3]$,那么实际的梯度值为:
这个向量其实就可以理解为通过链式法则传递的上一层的梯度值,也可以理解为在投影方向,实现的时候传入 backward()
函数中即可。在 python 也有同样的特性,但一般各种运算算子一般都是封装好的,所以很少用到。查看下面的代码:
torch::Tensor xx = torch::randn({3}, torch::requires_grad());
torch::Tensor yy = xx * xx + 2 * xx;
yy.backward(torch::tensor({1, 2, 3}));