PyTorch C++ API笔记

官方文档地址:
https://pytorch.org/cppdocs/

说明:以下是我学习笔记,大部分内容摘录自官方文档,也添加了一些案例。

PyTorch C++ API大致可以分为五个部分:

  • ATen:基础张量和数学运算库,所有其他功能都建立在它之上。
  • Autograd:通过自动微分增强 ATen。
  • C++前端:用于训练和评估机器学习模型的高级构造。
  • TorchScript:TorchScript JIT 编译器和解释器的接口。
  • C++扩展:一种使用自定义 C++ 和 CUDA 例程扩展 Python API 的方法。

结合起来,这些构建块形成了一个研究和生产就绪的 C++ 库,用于张量计算和动态神经网络,重点是 GPU 加速和快速 CPU 性能。

1.ATen

ATen 本质上是一个张量库,PyTorch 中几乎所有其他 Python 和 C++ 接口都建立在它之上。它提供了一个核心Tensor类,在该类上定义了数百个操作。

#include 

at::Tensor a = at::ones({2, 2}, at::kInt);
at::Tensor b = at::randn({2, 2});
auto c = a + b.to(at::kInt);

2.autograd

autograd是 PyTorch 的 C++ API 的一部分,它Tensor通过自动微分功能增强了 ATen类。autograd 系统记录对张量的操作以形成autograd 图。调用backwards()执行反向模式微分,最终产生梯度。

#include 
#include 

torch::Tensor a = torch::ones({2, 2}, torch::requires_grad());
torch::Tensor b = torch::randn({2, 2});
auto c = a + b;
c.backward(); // a.grad() will now hold the gradient of c w.r.t. a.

注意:这里需要关注at::Tensor和torch::Tensor的区别!
ATen 中的类默认是不可微的。要添加 autograd API 提供的Tensor的可微性,就必须使用来自torch::命名空间,而不是at::命名空间的Tensor函数。例如,虽然使用at::ones创建的Tensor将不可微,但使用torch::ones创建的Tensor将是可微的。

3.C++前端

PyTorch C++ 前端是一个用于 CPU 和 GPU 张量计算的 C++14 库,具有用于最先进机器学习应用程序的自动微分和高级构建块。它由以下组件组成:

  • torch::Tensor 可自动微分、高效的 CPU 和 GPU 启用张量
  • torch::nn用于神经网络建模的可组合模块的集合,包括torch.nn.Module,torch.nn.parallel.DataParallel等一系列子模块。
  • torch::optim 使用 SGD、Adam 或 RMSprop 等优化算法来训练您的模型
  • torch::data数据集、数据管道和多线程、异步数据加载器 torch::serialize 用于存储和加载模型检查点的序列化 API
  • torch::python 用胶水将你的 C++ 模型绑定到 Python 中
  • torch::jit 对 TorchScript JIT编译器的纯 C++ 访问

语法上基本和Python上是一样的,基本你熟悉pytorch就可以直接使用。

案例:Mnist的模型定义
Python版本

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

C++版本

struct Net : torch::nn::Module {
  Net()
      : conv1(torch::nn::Conv2dOptions(1, 10, /*kernel_size=*/5)),
        conv2(torch::nn::Conv2dOptions(10, 20, /*kernel_size=*/5)),
        fc1(320, 50),
        fc2(50, 10) {
    register_module("conv1", conv1);
    register_module("conv2", conv2);
    register_module("conv2_drop", conv2_drop);
    register_module("fc1", fc1);
    register_module("fc2", fc2);
  }

  torch::Tensor forward(torch::Tensor x) {
    x = torch::relu(torch::max_pool2d(conv1->forward(x), 2));
    x = torch::relu(
        torch::max_pool2d(conv2_drop->forward(conv2->forward(x)), 2));
    x = x.view({-1, 320});
    x = torch::relu(fc1->forward(x));
    x = torch::dropout(x, /*p=*/0.5, /*training=*/is_training());
    x = fc2->forward(x);
    return torch::log_softmax(x, /*dim=*/1);
  }

  torch::nn::Conv2d conv1;
  torch::nn::Conv2d conv2;
  torch::nn::FeatureDropout conv2_drop;
  torch::nn::Linear fc1;
  torch::nn::Linear fc2;
};

4.TorchScript

TorchScript 是一种 PyTorch 模型的表示,可以被 TorchScript 编译器理解、编译和序列化。从根本上说,TorchScript 本身就是一种编程语言。它是使用 PyTorch API 的 Python 子集。TorchScript 的 C++ 接口包含三个主要功能:

  • 一种在 Python 中定义的加载和执行序列化 TorchScript 模型的机制;
  • 用于定义扩展 TorchScript标准操作库的自定义操作符的 API;
  • 从 C++ 实时编译 TorchScript 程序。

前面我几篇文章写的,从Python中定义模型,但随后将它们导出到 C++ 以用于生产环境推理,就属于这种情况。另外,还有个torch::jit::compile 函数可用于直接从 C++ 访问 TorchScript 编译器。

案例:TorchScript推理
Python版本

def TorchTest():
{
example = torch.rand(1, 3, 224, 224)
model = models.resnet50(pretrained=True)
model = model.eval()
output = model (example)
print(output)
return output
}

C++版本

void TorchTest(){
    std::shared_ptr<torch::jit::script::Module> module = torch::jit::load("../resnet.pt");
    assert(module != nullptr);
    std::cout << "Load model successful!" << std::endl;
    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(torch::zeros({1,3,224,224}));
    at::Tensor output = module->forward(inputs).toTensor();
    auto max_result = output.max(1, true);
    auto max_index = std::get<1>(max_result).item<float>();
    std::cout << max_index << std::endl;
}

5. C++ 扩展

C++ 扩展 API 没有向 PyTorch C++ API 添加任何新功能。相反,它提供了与 Python setuptools 的集成以及允许从 Python 访问 ATen、autograd 和其他 C++ API 的 JIT 编译机制。
这部分我也没仔细看,暂时用不到。

6.类和文件
PyTorch C++ API 类层次
PyTorch C++ API笔记_第1张图片

PyTorch C++ API 文件层次
PyTorch C++ API笔记_第2张图片
完整的API信息查询
https://pytorch.org/cppdocs/api/library_root.html
PyTorch C++ API笔记_第3张图片

你可能感兴趣的:(人工智能,深度学习,pytorch,c++,libtorch)