Implantação de modelo de aprendizado profundo baseado em C ++

1.1 Introdução

 Como uma estrutura de aprendizado profundo de ponta a ponta, o PyTorch tem boas condições de implantação de ambiente de produção após a versão 1.0. Além de escrever API REST para implantação no lado da web (referência), também existem requisitos extensos para implantação do lado do software. Especialmente a versão 1.5 lançada recentemente fornece uma API de front-end C ++ mais estável.

     A maior diferença entre o mundo industrial e o mundo acadêmico é que o modelo industrial precisa ser implantado no solo. O mundo acadêmico está mais preocupado com os requisitos de precisão do modelo e menos preocupado com o desempenho de implantação do modelo. De modo geral, após treinarmos um modelo com um framework de aprendizado profundo, Python é o suficiente para implementar uma demonstração de raciocínio simples. Mas em um ambiente de produção, a portabilidade e desempenho de velocidade do Python são muito inferiores ao C ++. Portanto, para engenheiros de algoritmos de aprendizagem profunda, Python é geralmente usado para a implementação rápida de ideias e treinamento de modelo, e C ++ é usado como uma ferramenta de produção de modelos. No momento, PyTorch pode combinar os dois perfeitamente. Os principais componentes de tecnologia que implementam a implantação do modelo PyTorch são TorchScript e libtorch .

     Portanto, o processo de engenharia de algoritmo de aprendizado profundo baseado em PyTorch é aproximadamente como mostrado na figura a seguir:

                                                                                                                                          

1.2 TorchScript

     O TorchScript pode ser considerado uma representação intermediária do modelo PyTorch, e o modelo PyTorch representado pelo TorchScript pode ser lido diretamente em C ++. PyTorch pode usar TorchScript para construir modelos serializados após a versão 1.0. O TorchScript fornece dois métodos de aplicação: Rastreamento e Script.

     Os exemplos de aplicativos de rastreamento são os seguintes:

class MyModel(torch.nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.linear = torch.nn.Linear(4, 4)
 
 
    def forward(self, x, h):
        new_h = torch.tanh(self.linear(x) + h)
        return new_h, new_h
 
 
# 创建模型实例 
my_model = MyModel()
# 输入示例
x, h = torch.rand(3, 4), torch.rand(3, 4)
# torch.jit.trace方法对模型构建TorchScript
traced_model = torch.jit.trace(my_model, (x, h))
# 保存转换后的模型
traced_model.save('model.pt')

     Neste código, primeiro definimos um modelo simples e criamos uma instância de modelo e, em seguida, dado um exemplo de entrada, a etapa mais crítica do método Tracing é usar o método torch.jit.trace para transformar o modelo em TorchScript. Podemos obter o objeto traced_model transformado para obter seus atributos de gráfico computacional e atributos de código. Propriedades do gráfico de cálculo: 

print(traced_model.graph)
graph(%self.1 : __torch__.torch.nn.modules.module.___torch_mangle_1.Module,
      %input : Float(3, 4),
      %h : Float(3, 4)):
  %19 : __torch__.torch.nn.modules.module.Module = prim::GetAttr[name="linear"](%self.1)
  %21 : Tensor = prim::CallMethod[name="forward"](%19, %input)
  %12 : int = prim::Constant[value=1]() # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0
  %13 : Float(3, 4) = aten::add(%21, %h, %12) # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0
  %14 : Float(3, 4) = aten::tanh(%13) # /var/lib/jenkins/workspace/beginner_source/Intro_to_TorchScript_tutorial.py:188:0
  %15 : (Float(3, 4), Float(3, 4)) = prim::TupleConstruct(%14, %14)
  return (%15)

 Atributos de código:

print(traced_cell.code)
def forward(self,
    input: Tensor,
    h: Tensor) -> Tuple[Tensor, Tensor]:
  _0 = torch.add((self.linear).forward(input, ), h, alpha=1)
  _1 = torch.tanh(_0)
  return (_1, _1)

     Desta forma, podemos salvar todo o modelo no disco rígido, e o modelo salvo desta forma pode ser carregado em outros ambientes de linguagem.

     Outra implementação do TorchScript é o método Script, que pode ser considerado um suplemento do método Tracing. Quando o código do modelo contém programas de fluxo de controle, como if ou for-loop, o método Tracing é inválido.Neste momento, o método Script pode ser usado para implementar o TorchScript. O método de implementação não é muito diferente de Tracing. A chave é substituir jit.tracing pelo método jit.script. O exemplo é o seguinte.

scripted_model = torch.jit.script(MyModel)
scripted_model.save('model.pt')

      Além de Tracing e Script, também podemos misturar os dois métodos, que não serão detalhados aqui. Resumindo, o TorchScript nos fornece uma forma de representação que pode ser otimizada pelo compilador para fornecer uma execução mais eficiente.

1.3 libtorch

     Depois de converter o modelo treinado no ambiente Python, precisamos do PyTorch no ambiente C ++ para ler o modelo, compilar e implantar. PyTorch neste ambiente C ++ é libtorch. Como a libtorch é normalmente usada como a interface C ++ do modelo PyTorch, a libtorch também é chamada de front-end C ++ do PyTorch.

     Podemos baixar o pacote de instalação do libtorch compilado diretamente do site oficial do PyTorch. Claro, também podemos baixar o código-fonte e compilá-lo nós mesmos. Deve-se observar aqui que a versão instalada do libtorch deve ser consistente com a versão do PyTorch no ambiente Python.

     Depois de instalar o libtorch, você pode simplesmente testar se está normal. Por exemplo, usamos TorchScript para converter um modelo pré-treinado, um exemplo é o seguinte: 

import torch
import torchvision.models as models
vgg16 = models.vgg16()
example = torch.rand(1, 3, 224, 224).cuda() 
model = model.eval()
traced_script_module = torch.jit.trace(model, example)
output = traced_script_module(torch.ones(1,3,224,224).cuda())
traced_script_module.save('vgg16-trace.pt')
print(output)

O resultado é: 

tensor([[ -0.8301, -35.6095, 12.4716]], device='cuda:0',
        grad_fn=<AddBackward0>)

     Em seguida, mude para o ambiente C ++ e grave o arquivo CmakeLists da seguinte maneira:

cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
project(libtorch_test)
find_package(Torch REQUIRED)
message(STATUS "Pytorch status:")
message(STATUS "libraries: ${TORCH_LIBRARIES}")
add_executable(libtorch_test test.cpp)
target_link_libraries(libtorch_test "${TORCH_LIBRARIES}")
set_property(TARGET libtorch_test PROPERTY CXX_STANDARD 11)

 Continue a escrever o código test.cpp da seguinte maneira:

#include "torch/script.h"
#include "torch/torch.h"
#include <iostream>
#include <memory>
using namespace std;
 
 
int main(int argc, const char* argv[]){
    if (argc != 2) {
        std::cerr << "usage: example-app <path-to-exported-script-module>\n";
        return -1;
    }
 
 
    // 读取TorchScript转化后的模型
    torch::jit::script::Module module;
    try {
        module = torch::jit::load(argv[1]);
    }
 
 
    catch (const c10::Error& e) {
        std::cerr << "error loading the model\n";
        return -1;
    }
 
 
    module->to(at::kCUDA);
    assert(module != nullptr);
    std::cout << "ok\n";
 
 
    // 构建示例输入
    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(torch::ones({1, 3, 224, 224}).to(at::kCUDA));
 
 
    // 执行模型推理并输出tensor
    at::Tensor output = module->forward(inputs).toTensor();
    std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';}

     Compile test.cpp e execute-o.O resultado é o seguinte. Comparando os resultados da execução no ambiente Python, podemos descobrir que eles são basicamente os mesmos, o que também mostra que não há problema com a instalação do libtorch no ambiente atual. 

ok
-0.8297, -35.6048, 12.4823
[Variable[CUDAFloatType]{1,3}]

 1.4 Processo de implantação completo

     Por meio da descrição anterior do TorchScript e do libtorch, na verdade, falamos basicamente sobre a implantação do PyTorch em C ++ e aqui daremos uma olhada completa em todo o processo. O processo de implantação do modelo PyTorch baseado em C ++ é o seguinte.

Primeiro passo:

     Use o método torch.jit.trace para converter o modelo PyTorch em TorchScript. Um exemplo é o seguinte:

import torch
from torchvision.models import resnet18
model =resnet18()
example = torch.rand(1, 3, 224, 224)
tracing.traced_script_module = torch.jit.trace(model, example)

A segunda etapa:

     Serialize o TorchScript para o arquivo de modelo .pt.

traced_script_module.save("traced_resnet_model.pt")

terceiro passo:

     Importe o modelo TorchScript serializado em C ++, para isso precisamos escrever o arquivo cpp contendo o programa de chamada, o arquivo CMakeLists.txt para configuração e compilação. O conteúdo de amostra do arquivo CMakeLists.txt é o seguinte:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(custom_ops)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)

      O código de exemplo de example-app.cpp que contém o programa de chamada de modelo é o seguinte:

#include <torch/script.h> // torch头文件.
#include <iostream>#include <memory>
 
 
int main(int argc, const char* argv[]) {
  if (argc != 2) {
    std::cerr << "usage: example-app <path-to-exported-script-module>\n";
    return -1;
  }
 
 
  torch::jit::script::Module module;
  try {
    // 反序列化:导入TorchScript模型
    module = torch::jit::load(argv[1]);
  }
 
 
  catch (const c10::Error& e) {
    std::cerr << "error loading the model\n";
    return -1;
  }
  std::cout << "ok\n";}

     Depois que os dois arquivos são gravados, eles podem ser compilados:

mkdir example_test
cd example_test
cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
cmake --example_test . --config Release

a quarta etapa:

Adicione o código de inferência do modelo a example-app.cpp e execute:

std::vector<torch::jit::IValue> inputs;inputs.push_back(torch::ones({1, 3, 224, 224}));
// 执行推理并将模型转化为Tensor
output = module.forward(inputs).toTensor();std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';

     Acima está todo o processo de implantação do modelo PyTorch em C ++. Para tutoriais relacionados, consulte o PyTorch oficial: https://pytorch.org/tutorials/

Resumindo

     A implantação do modelo é muito importante para engenheiros de algoritmo e está relacionada ao fato de seu trabalho poder gerar valor real. Da mesma forma, você também precisa ter recursos de engenharia suficientes, como MySQL, Redis, C ++, algum conhecimento e técnicas de desenvolvimento de front-end e back-end, todos os engenheiros de algoritmo precisam ser capazes de entender e usar isso.

Acho que você gosta

Origin blog.csdn.net/wzhrsh/article/details/109552923
Recomendado
Clasificación