Torchvision의 retinanet을 libtorch를 이용해 c++에서 추론하기

토치비전의 레티나넷을 파이썬에서 훈련하고
C++에서 libtorch를 이용해 추론하려고 합니다.
현재 resnet18 의경우는 c++에서도 추론이 잘 되었습니다.
하지만 retinanet은 모댈을 불러오는 부분에서
익셉션 에러가 발생하네요.
Msg_=schemas.size() 라는 에러가 보이는데
어떻개해야할지 모르겠습니다.
혹시몰라 도움을 요청합니다.

감사합니다.

  • 아래 답변은 OpenAI의 GPT-4-Turbo 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요, 김재현님.

문제 상황에 대해 공유해주셔서 감사합니다. 파이썬에서 훈련된 토치비전의 레티나넷 모델을 C++ 환경에서 libtorch를 사용하여 추론하려고 하시는데, 모델을 불러오는 과정에서 schemas.size() 관련 예외가 발생하는 문제를 겪고 계신 것으로 이해했습니다. ResNet18 모델은 정상적으로 추론이 되었지만, RetinaNet 모델에서만 문제가 발생하는 것으로 보입니다.

이 문제를 해결하기 위해 몇 가지 점검해볼 사항들을 제안드리겠습니다.

  1. 모델 저장 방법 확인: 파이썬에서 모델을 저장할 때 torch.save(model.state_dict(), 'model.pth') 방식으로 저장했는지 확인해주세요. 모델의 구조와 가중치만 저장하는 것이 중요합니다.

  2. 모델 로딩 방법 확인: C++에서 모델을 로드할 때는 먼저 모델의 구조를 정의하고, torch::load(model, "model.pth")를 사용하여 가중치를 로드해야 합니다.

  3. libtorch 버전 확인: 파이썬에서 사용한 PyTorch 버전과 C++에서 사용하는 libtorch 버전이 일치하는지 확인해주세요. 버전 불일치는 종종 이러한 문제를 일으킬 수 있습니다.

  4. 커스텀 레이어 또는 연산자: RetinaNet 모델에 커스텀 레이어나 연산자가 포함되어 있다면, 이를 C++에서도 정의하고 등록해야 합니다.

  5. 직렬화 및 역직렬화: 모델을 저장하고 불러올 때 직렬화 및 역직렬화 과정에서 문제가 없는지 확인해보세요.

아래는 C++에서 libtorch를 사용하여 모델을 로드하는 예시 코드입니다.

#include <torch/script.h> // One-stop header.
#include <iostream>
#include <memory>

int main() {
    // 모델 구조를 정의합니다. (예시 코드이므로 실제 모델 구조에 맞게 수정해야 합니다.)
    struct Net : torch::nn::Module {
        Net() {
            // 모델 레이어 정의
        }

        torch::Tensor forward(torch::Tensor x) {
            // 순전파 정의
            return x;
        }
    };

    // 모델 인스턴스를 생성합니다.
    Net model;

    // 모델의 가중치를 로드합니다.
    torch::load(model, "model.pth");

    // 추론을 위한 입력 데이터를 준비합니다.
    torch::Tensor input = torch::rand({1, 3, 224, 224});

    // 모델을 평가 모드로 설정합니다.
    model.eval();

    // 추론을 수행합니다.
    torch::Tensor output = model.forward(input);

    std::cout << output << std::endl;

    return 0;
}

이 코드는 단순한 예시이며, 실제 사용하시는 RetinaNet 모델의 구조에 맞게 수정해야 합니다. 또한, 모델을 저장할 때와 동일한 구조로 모델을 정의해야 합니다.

추가적인 정보나 도움이 필요하시면, PyTorch 공식 문서의 C++ API 섹션을 참고하시기 바랍니다. libtorch 관련 문서는 다음 링크에서 확인하실 수 있습니다:

제 답변이 정확하지 않을 수도 있으니, 문제가 계속 발생한다면 추가적인 정보를 제공해주시면 더 도움을 드릴 수 있을 것 같습니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 Anthropic의 Claude-2 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

김재현님, 안녕하세요.

Torchvision의 retinanet 모델을 파이썬에서 학습하고 C++의 libtorch를 사용해 추론하려다가 schemas.size() 에러가 발생하는 문제에 대해 질문 주셨군요.

이 문제는 retinanet 모델의 구조가 resnet과 다르기 때문에 발생하는 것 같습니다.

해결하기 위해서는 다음과 같은 접근이 필요합니다:

  1. RetinaNet 모델 저장 시에 JIT 스크립팅을 사용하여 torch.jit.script를 사용하여 traced 모델을 저장합니다.
  2. C++에서 이 traced 모델을 불러올 때 schemas를 명시적으로 정의해주어야 합니다.

예를 들어 다음과 같이 할 수 있습니다:

import torch
from torchvision.models.detection import retinanet_resnet50_fpn

model = retinanet_resnet50_fpn(pretrained=True)
model.eval()

# Traced model 저장 
example_input = torch.rand(1, 3, 640, 640)
traced_model = torch.jit.trace(model, example_input)
traced_model.save("retinanet.pt")
#include <torch/script.h>

int main() {
  torch::jit::script::Module module;
  try {
    // schemas 정의
    module = torch::jit::load("retinanet.pt", c10::intrusive_ptr<c10::ivalue::TupleType>[]); 
  } catch (const c10::Error& e) {
    std::cerr << "error loading the model\n";
    return -1;
  }

  std::vector<torch::jit::IValue> inputs;
  // 입력 생성
  inputs.push_back(torch::rand({1, 3, 640, 640})); 

  module.forward(inputs).toTuple()->elements()[0].toTensor().print();

  return 0;
}

위 코드에서 볼 수 있듯이 traced 모델을 저장할 때 JIT 스크립팅을 사용하고, C++에서 불러올 때 schemas를 명시적으로 정의하면 문제를 해결할 수 있습니다.

더 자세한 내용이 필요하시다면 댓글로 질문해 주세요. 최선을 다해 도와드리겠습니다.

감사합니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요 KimjaeHyun님,

문제를 겪고 계신 것에 대해 안타깝게 생각합니다. 질문을 요약해보면, Python에서 훈련된 Torchvision의 RetinaNet 모델을 C++ 환경에서 LibTorch를 사용하여 추론하려고 할 때, 모델을 불러오는 과정에서 schemas.size() 관련 예외가 발생하는 문제를 겪고 계신 것으로 이해됩니다. ResNet18 모델은 C++에서 추론이 잘 되었지만, RetinaNet에서는 문제가 발생하는 상황인 것 같습니다.

이 문제를 해결하기 위해 몇 가지 점검해야 할 사항들이 있습니다:

  1. LibTorch 버전: 사용하고 있는 LibTorch의 버전이 Python에서 모델을 훈련시킨 PyTorch의 버전과 일치하는지 확인해야 합니다. 버전 불일치는 모델 로딩 시 문제를 일으킬 수 있습니다.

  2. 사용자 정의 레이어: RetinaNet은 사용자 정의 레이어나 연산을 포함할 수 있습니다. 이러한 레이어들은 C++에서도 정의되어 있어야 합니다.

  3. 모델 저장 방식: 모델을 저장할 때 torch.jit.trace 또는 torch.jit.script를 사용하여 스크립트 모듈로 변환한 후 저장했는지 확인해야 합니다. 이렇게 변환하는 과정은 C++에서 모델을 불러올 때 필요한 호환성을 제공합니다.

아래는 C++에서 LibTorch를 사용하여 모델을 불러오고 추론하는 기본적인 예제 코드입니다. 이 코드를 참고하여 RetinaNet 모델을 불러오는 부분을 수정해 볼 수 있습니다.

#include <torch/script.h> // torch::jit::script::Module을 포함합니다.
#include <torch/torch.h>  // torch의 다양한 기능들을 포함합니다.
#include <iostream>
#include <memory>

int main() {
    // 모델을 불러옵니다.
    torch::jit::script::Module module;
    try {
        // 'model.pt'는 Python에서 저장한 스크립트 모듈입니다.
        module = torch::jit::load("model.pt");
    }
    catch (const c10::Error& e) {
        std::cerr << "모델을 불러오는데 실패했습니다.\n";
        return -1;
    }

    std::cout << "모델을 성공적으로 불러왔습니다.\n";

    // 추론을 위한 입력 데이터를 준비합니다.
    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(torch::ones({1, 3, 224, 224}));

    // 모델을 평가 모드로 설정합니다.
    module.eval();

    // 추론을 실행합니다.
    at::Tensor output = module.forward(inputs).toTensor();
    std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';

    return 0;
}

이 코드를 사용하여 모델을 불러오고 추론을 수행할 수 있습니다. 만약 여전히 문제가 발생한다면, 모델을 저장하는 Python 코드와 모델을 불러오는 C++ 코드를 더 자세히 살펴보아야 할 것입니다.

추가적인 정보와 LibTorch의 사용법에 대해서는 PyTorch 공식 문서의 C++ API 섹션을 참조하실 수 있습니다:

제 답변이 정확하지 않을 수도 있으니, 문제가 계속되면 추가적인 정보와 함께 새로운 질문을 올려주시면 감사하겠습니다.


  • 이 답변이 도움이 되셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!