C++ 前端中的 Autograd

这篇具有很好参考价值的文章主要介绍了C++ 前端中的 Autograd。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ 前端中的 Autograd

autograd包对于在 PyTorch 中构建高度灵活和动态的神经网络至关重要。 PyTorch Python 前端中的大多数 autograd API 也可以在 C++ 前端中使用,从而可以轻松地将 Autograd 代码从 Python 转换为 C++。

在本教程中,我们将看几个在 PyTorch C++ 前端中进行 Autograd 的示例。 请注意,本教程假定您已经对 Python 前端中的 Autograd 有基本的了解。 如果不是这种情况,请先阅读 Autograd:自动微分。

基本的 Autograd 操作

(改编自本教程)

创建一个张量并设置torch::requires_grad()以跟踪它的计算

auto x = torch::ones({2, 2}, torch::requires_grad());
std::cout << x << std::endl;

出:

1 1
1 1
[ CPUFloatType{2,2} ]

进行张量运算:

auto y = x + 2;
std::cout << y << std::endl;

出:

 3  3
 3  3
[ CPUFloatType{2,2} ]

y是由于操作而创建的,因此具有grad_fn

std::cout << y.grad_fn()->name() << std::endl;

出:

AddBackward1

y上执行更多操作

auto z = y * y * 3;
auto out = z.mean();

std::cout << z << std::endl;
std::cout << z.grad_fn()->name() << std::endl;
std::cout << out << std::endl;
std::cout << out.grad_fn()->name() << std::endl;

出:

 27  27
 27  27
[ CPUFloatType{2,2} ]
MulBackward1
27
[ CPUFloatType{} ]
MeanBackward0

.requires_grad_( ... )原地更改现有张量的requires_grad标志。

auto a = torch::randn({2, 2});
a = ((a * 3) / (a - 1));
std::cout << a.requires_grad() << std::endl;

a.requires_grad_(true);
std::cout << a.requires_grad() << std::endl;

auto b = (a * a).sum();
std::cout << b.grad_fn()->name() << std::endl;

出:

false
true
SumBackward0

现在让我们反向传播。 因为out包含单个标量,所以out.backward()等效于out.backward(torch::tensor(1.))

out.backward();

打印梯度d(out) / dx

std::cout << x.grad() << std::endl;

出:

 4.5000  4.5000
 4.5000  4.5000
[ CPUFloatType{2,2} ]

您应该具有4.5的矩阵。 有关如何获得此值的说明,请参见本教程中的相应部分。

现在,让我们来看一个向量雅各布产品的示例:

x = torch::randn(3, torch::requires_grad());

y = x * 2;
while (y.norm().item<double>() < 1000) {
  y = y * 2;
}

std::cout << y << std::endl;
std::cout << y.grad_fn()->name() << std::endl;

出:

-1021.4020
  314.6695
 -613.4944
[ CPUFloatType{3} ]
MulBackward1

如果我们想要向量-Jacobian 乘积,请将向量作为参数传递给backward

auto v = torch::tensor({0.1, 1.0, 0.0001}, torch::kFloat);
y.backward(v);

std::cout << x.grad() << std::endl;

出:

  102.4000
 1024.0000
    0.1024
[ CPUFloatType{3} ]

您也可以通过在代码块中放置torch::NoGradGuard来停止对需要梯度的张量的跟踪历史的自动定格

std::cout << x.requires_grad() << std::endl;
std::cout << x.pow(2).requires_grad() << std::endl;

{
  torch::NoGradGuard no_grad;
  std::cout << x.pow(2).requires_grad() << std::endl;
}

出:

true
true
false

或者使用.detach()获得具有相同内容但不需要梯度的新张量:

std::cout << x.requires_grad() << std::endl;
y = x.detach();
std::cout << y.requires_grad() << std::endl;
std::cout << x.eq(y).all().item<bool>() << std::endl;

出:

true
false
true

有关 C++ 张量自动梯度 API 的更多信息,例如grad/requires_grad/is_leaf/backward/detach/detach_/register_hook/retain_grad,请参见相应的 C++ API 文档。

用 C++ 计算高阶梯度

高阶梯度的应用之一是计算梯度罚分。 我们来看看使用torch::autograd::grad的示例:

#include <torch/torch.h>

auto model = torch::nn::Linear(4, 3);

auto input = torch::randn({3, 4}).requires_grad_(true);
auto output = model(input);

// Calculate loss
auto target = torch::randn({3, 3});
auto loss = torch::nn::MSELoss()(output, target);

// Use norm of gradients as penalty
auto grad_output = torch::ones_like(output);
auto gradient = torch::autograd::grad({output}, {input}, /*grad_outputs=*/{grad_output}, /*create_graph=*/true)[0];
auto gradient_penalty = torch::pow((gradient.norm(2, /*dim=*/1) - 1), 2).mean();

// Add gradient penalty to loss
auto combined_loss = loss + gradient_penalty;
combined_loss.backward();

std::cout << input.grad() << std::endl;

出:

-0.1042 -0.0638  0.0103  0.0723
-0.2543 -0.1222  0.0071  0.0814
-0.1683 -0.1052  0.0355  0.1024
[ CPUFloatType{3,4} ]

有关如何使用它们的更多信息,请参见torch::autograd::backwardtorch::autograd::grad的文档。

在 C++ 中使用自定义 Autograd 函数

(改编自本教程)

torch::autograd添加新的基本操作需要为每个操作实现一个新的torch::autograd::Function子类。 torch::autograd::Function用于torch::autograd计算结果和梯度,并对操作历史进行编码。 每个新函数都需要您实现两种方法:forwardbackward,有关详细要求,请参见此链接。

在下面,您可以从torch::nn找到Linear函数的代码:

#include <torch/torch.h>

using namespace torch::autograd;

// Inherit from Function
class LinearFunction : public Function<LinearFunction> {
 public:
  // Note that both forward and backward are static functions

  // bias is an optional argument
  static torch::Tensor forward(
      AutogradContext *ctx, torch::Tensor input, torch::Tensor weight, torch::Tensor bias = torch::Tensor()) {
    ctx->save_for_backward({input, weight, bias});
    auto output = input.mm(weight.t());
    if (bias.defined()) {
      output += bias.unsqueeze(0).expand_as(output);
    }
    return output;
  }

  static tensor_list backward(AutogradContext *ctx, tensor_list grad_outputs) {
    auto saved = ctx->get_saved_variables();
    auto input = saved[0];
    auto weight = saved[1];
    auto bias = saved[2];

    auto grad_output = grad_outputs[0];
    auto grad_input = grad_output.mm(weight);
    auto grad_weight = grad_output.t().mm(input);
    auto grad_bias = torch::Tensor();
    if (bias.defined()) {
      grad_bias = grad_output.sum(0);
    }

    return {grad_input, grad_weight, grad_bias};
  }
};

然后,我们可以通过以下方式使用LinearFunction

auto x = torch::randn({2, 3}).requires_grad_();
auto weight = torch::randn({4, 3}).requires_grad_();
auto y = LinearFunction::apply(x, weight);
y.sum().backward();

std::cout << x.grad() << std::endl;
std::cout << weight.grad() << std::endl;

出:

 0.5314  1.2807  1.4864
 0.5314  1.2807  1.4864
[ CPUFloatType{2,3} ]
 3.7608  0.9101  0.0073
 3.7608  0.9101  0.0073
 3.7608  0.9101  0.0073
 3.7608  0.9101  0.0073
[ CPUFloatType{4,3} ]

在这里,我们给出了一个由非张量参数设置参数的函数的附加示例:

#include <torch/torch.h>

using namespace torch::autograd;

class MulConstant : public Function<MulConstant> {
 public:
  static torch::Tensor forward(AutogradContext *ctx, torch::Tensor tensor, double constant) {
    // ctx is a context object that can be used to stash information
    // for backward computation
    ctx->saved_data["constant"] = constant;
    return tensor * constant;
  }

  static tensor_list backward(AutogradContext *ctx, tensor_list grad_outputs) {
    // We return as many input gradients as there were arguments.
    // Gradients of non-tensor arguments to forward must be `torch::Tensor()`.
    return {grad_outputs[0] * ctx->saved_data["constant"].toDouble(), torch::Tensor()};
  }
};

然后,我们可以通过以下方式使用MulConstant

auto x = torch::randn({2}).requires_grad_();
auto y = MulConstant::apply(x, 5.5);
y.sum().backward();

std::cout << x.grad() << std::endl;

出:

 5.5000
 5.5000
[ CPUFloatType{2} ]

有关torch::autograd::Function的更多信息,请参见其文档。

将 Autograd 代码从 Python 转换为 C++

在较高的层次上,在 C++ 中使用 Autograd 的最简单方法是先在 Python 中拥有可用的 Autograd 代码,然后使用下表将您的 Autograd 代码从 Python 转换为 C++:

Python C++
torch.autograd.backward torch::autograd::backward
torch.autograd.grad torch::autograd::grad
torch.Tensor.detach torch::Tensor::detach
torch.Tensor.detach_ torch::Tensor::detach_
torch.Tensor.backward torch::Tensor::backward
torch.Tensor.register_hook torch::Tensor::register_hook
torch.Tensor.requires_grad torch::Tensor::requires_grad_
torch.Tensor.retain_grad torch::Tensor::retain_grad
torch.Tensor.grad torch::Tensor::grad
torch.Tensor.grad_fn torch::Tensor::grad_fn
torch.Tensor.set_data torch::Tensor::set_data
torch.Tensor.data torch::Tensor::data
torch.Tensor.output_nr torch::Tensor::output_nr
torch.Tensor.is_leaf torch::Tensor::is_leaf

翻译后,您的大多数 Python Autograd 代码都应仅在 C++ 中工作。 如果不是这种情况,请在 GitHub ISSUE 中提交错误报告,我们将尽快对其进行修复。

总结

现在,您应该对 PyTorch 的 C++ autograd API 有了一个很好的了解。文章来源地址https://www.toymoban.com/news/detail-507961.html

到了这里,关于C++ 前端中的 Autograd的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Pytorch Tutorial【Chapter 2. Autograd】

    1. Review Matrix Calculus 1.1 Definition向量对向量求导 ​ Define the derivative of a function mapping f : R n → R m f:mathbb{R}^ntomathbb{R}^m f : R n → R m as the n × m ntimes m n × m matrix of partial derivatives. That is, if x ∈ R n , f ( x ) ∈ R m xinmathbb{R}^n,f(x)inmathbb{R}^m x ∈ R n , f ( x ) ∈ R m , the derivative of f

    2024年02月14日
    浏览(38)
  • 深度解析 PyTorch Autograd:从原理到实践

    本文深入探讨了 PyTorch 中 Autograd 的核心原理和功能。从基本概念、Tensor 与 Autograd 的交互,到计算图的构建和管理,再到反向传播和梯度计算的细节,最后涵盖了 Autograd 的高级特性。 关注TechLead,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理

    2024年02月03日
    浏览(59)
  • PyTorch 中autograd.Variable模块的基本操作

    在 PyTorch 中, autograd.Variable 是一个自动求导变量,用于构建计算图并进行梯度自动求导。 Variable 提供了许多基本操作,下面介绍其中的一些常用操作: 创建变量: 访问数据: 注意,PyTorch 1.0 版本后, Variable 被弃用,可以直接使用 Tensor。 反向传播计算梯度: 在创建变量时

    2024年02月11日
    浏览(34)
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**

    PyTorch月学习计划 - 第6-7天: 自动梯度(Autograd) 学习目标: 掌握自动微分的基本原理,特别是在深度学习中的应用。 学会如何在PyTorch中使用autograd模块进行自动梯度计算。 学习内容: 自动微分和计算图的概念 自动微分:自动微分是深度学习中用于自动计算导数或梯度的技

    2024年01月21日
    浏览(47)
  • 深度学习 -- pytorch 计算图与动态图机制 autograd与逻辑回归模型

    pytorch中的动态图机制是pytorch这门框架的优势所在,阅读本篇博客可以使我们对动态图机制以及静态图机制有更直观的理解,同时在博客的后半部分有关于逻辑回归的知识点,并且使用pytorch中张量以及张量的自动求导进行构建逻辑回归模型。 计算图是用来描述运算的有向无环

    2024年02月01日
    浏览(46)
  • PyTorch翻译官网教程6-AUTOMATIC DIFFERENTIATION WITH TORCH.AUTOGRAD

    Automatic Differentiation with torch.autograd — PyTorch Tutorials 2.0.1+cu117 documentation 当训练神经网络时,最常用的算法是方向传播算法。在该算法中,根据损失函数与给定参数的梯度来调整模型参数(权重)。 为了计算这些梯度,PyTorch有一个内置的微分引擎,名为torch.autograd。它支持任

    2024年02月16日
    浏览(53)
  • PyTorch 之 简介、相关软件框架、基本使用方法、tensor 的几种形状和 autograd 机制

    本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 PyTorch 是一个基于 Torch 的 Python 开源机器学习库,用于自然语言处理等应用程序。它主要由 Facebook 的人工智能小组开发,不仅能够实现强大的 GPU 加速,同时还支持动态神经网络,这一点是现在很多主流框架

    2024年01月18日
    浏览(54)
  • PyTorch C++ 前端:张量

    本篇文章将尝试了解 PyTorch 组件的高级概述以及它们如何配合。 PyTorch 组件的高级概述 后端 PyTorch 后端是用 C++ 编写的,它提供 API 来访问高度优化的库,例如:用于高效矩阵运算的张量库、用于执行 GPU 运算的 CUDA 库以及用于梯度计算的自动微分等。 前端 可以使用 Python 或

    2024年02月07日
    浏览(38)
  • 前端(六)——TypeScript在前端中的重要性与应用

    😊博主:小猫娃来啦 😊文章核心: TypeScript在前端中的重要性与应用 随着Web应用的复杂性不断增加,开发人员需要更强大的工具来应对这些挑战。TypeScript作为一种静态类型语言,满足了许多开发者对代码质量和可维护性的需求。下面我们将深入探讨TypeScript在前端中的定位

    2024年02月16日
    浏览(40)
  • 前端开发中的最佳实践

    部分数据来源: ChatGPT 引言         前端开发是一个繁忙而庞杂的领域,其中充满了技术和工具。因此,始终保持最佳实践是确保您的项目顺利完成并高效运行的关键。本文将讨论前端开发的一些最佳实践,以帮助您最大化生产力并确保项目成功。 1. 版本控制       

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包