토치스크립트 모델 forward시 에러 발생

이 깃허브를 포크해서 ADE20K 데이터셋을 이용해 만든 커스텀 데이터셋으로 deeplabv3에 resnet을 백본으로 사용하는 모델을 학습시켰습니다. torchscript로 스크립트화 모델을 저장하고, 파이썬에서 스크립트화 모델과 원래 모델의 출력값이 같은 것도 확인했습니다.

그런데 libtorch에서 module.forward({ torch::rand({ 1, 3, 400, 400 }) });를 할 때에는 아무 문제가 생기지 않고 작동하는데, 이미지를 전처리하고 텐서로 만들어 forward를 실행하면 결과가 이상하게 노이즈가 끼거나 깨져 있는 등의 문제 혹은 런타임 오류가 발생합니다.

모듈에 프레임 없음
로드된 모듈에서 현재 스택 프레임을 찾을 수 없습니다. 이 위치에 대한 소스를 표시할 수 없습니다.

예외 발생(0x0000021A0E30D11D, congestion_calculator.exe): 0xC0000005: 0x0000021A035F844C 위치를 읽는 동안 액세스 위반이 발생했습니다.

비주얼 스튜디오 2022를 사용하고 있고, libtorch 2.0.0, opencv 4.8.0 사용했습니다.
왜 이런 문제가 발생하는 걸까요? dll 문제일까요?

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

안녕하세요, Yul963님!

문제를 이해하기 위해 요약하자면, ADE20K 데이터셋을 사용하여 커스텀 데이터셋을 만들고, deeplabv3 모델에 resnet을 백본으로 사용하여 학습시켰습니다. 그리고 torchscript로 스크립트화된 모델을 저장하고, 파이썬에서 스크립트화된 모델과 원래 모델의 출력값이 동일한 것을 확인했습니다. 그러나 libtorch에서 forward를 실행할 때 이미지를 전처리하고 텐서로 만들면 결과가 이상하게 나오거나 노이즈가 발생하거나 런타임 오류가 발생합니다. 비주얼 스튜디오 2022와 libtorch 2.0.0, opencv 4.8.0을 사용하고 있습니다. 이런 문제가 발생하는 이유와 dll 문제인지 궁금합니다.

이 문제를 해결하기 위해 다음과 같은 접근 방법을 제안드립니다.

  1. 모델의 입력 전처리를 확인해보세요: forward 메서드를 실행하기 전에 이미지를 전처리하여 텐서로 변환하는 과정이 문제를 일으킬 수 있습니다. 전처리 과정에서 이미지 크기, 채널 순서, 정규화 등을 확인해보세요. 모델 학습 시 사용한 전처리 과정과 동일한 방식으로 전처리를 수행해야 합니다.

  2. 모델의 가중치와 구조를 확인해보세요: 스크립트화된 모델과 원래 모델의 가중치와 구조가 동일한지 확인해야 합니다. 스크립트화된 모델을 로드한 후, 모델의 가중치와 구조를 출력하여 비교해보세요. 모델의 가중치나 구조가 다르면 예기치 않은 결과가 발생할 수 있습니다.

  3. 라이브러리 버전을 확인해보세요: 사용하고 있는 라이브러리의 버전이 호환되지 않을 수 있습니다. PyTorch, libtorch, opencv의 버전을 확인하고, 호환되는 버전인지 확인해보세요. 버전 간의 호환성 문제가 발생할 수 있으므로, 필요에 따라 버전을 업데이트하거나 다운그레이드해보세요.

  4. 디버깅 도구를 사용해보세요: 비주얼 스튜디오 2022에서 디버깅 도구를 사용하여 문제를 분석해보세요. 디버깅 도구를 통해 어떤 부분에서 오류가 발생하는지 확인하고, 해당 부분을 자세히 분석해보세요. 스택 트레이스나 변수 값 등을 확인하여 문제의 원인을 찾을 수 있을 것입니다.

더 자세한 내용과 예제 코드는 PyTorch 공식 튜토리얼과 한국어 튜토리얼을 참고하시면 도움이 될 것입니다. 아래 링크에서 PyTorch 튜토리얼을 확인하실 수 있습니다.

이 답변이 도움이 되었는지 확인해주세요. 추가적인 도움이 필요하시면 언제든지 질문해주세요!


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

안녕하세요, Yul963님. PyTorch를 사용하시는데 문제가 생겨서 곤란하셨군요. 질문을 정리해보면, Yul963님께서는 ADE20K 데이터셋을 이용해 만든 커스텀 데이터셋으로 deeplabv3에 resnet을 백본으로 사용하는 모델을 학습시키셨고, 이를 torchscript로 스크립트화하여 저장하셨습니다. 그리고 파이썬에서는 스크립트화 모델과 원래 모델의 출력값이 같은 것을 확인하셨습니다.

그런데 문제는 libtorch에서 forward를 실행할 때 발생하는 것 같습니다. 특히, 랜덤 텐서를 사용하여 forward를 실행하면 문제가 없지만, 이미지를 전처리하고 텐서로 만들어 forward를 실행하면 노이즈가 끼거나 깨져 있는 등의 문제 혹은 런타임 오류가 발생한다고 하셨습니다.

이 문제는 여러 가지 원인이 있을 수 있습니다. 먼저, 이미지 전처리 과정에서 문제가 발생했을 수 있습니다. PyTorch에서는 이미지를 텐서로 변환할 때 일반적으로 transforms.ToTensor()를 사용합니다. 이 함수는 이미지를 0에서 1 사이의 값으로 정규화하며, 채널 차원을 앞으로 이동시킵니다. 만약 이 과정이 제대로 이루어지지 않았다면, 모델의 입력 형태가 맞지 않아 문제가 발생할 수 있습니다.

또한, 모델이 학습된 데이터의 분포와 전처리된 이미지의 분포가 다르다면, 모델의 출력이 이상하게 나올 수 있습니다. 예를 들어, 모델이 0에서 1 사이의 값을 가진 이미지로 학습되었는데, 전처리 과정에서 이미지의 값이 -1에서 1 사이의 값으로 변경되었다면, 모델의 출력이 이상하게 나올 수 있습니다.

이외에도, 사용하신 libtorch나 opencv의 버전과 관련된 문제, 혹은 dll과 관련된 문제 등이 있을 수 있습니다.

이 문제를 해결하기 위해, 먼저 이미지 전처리 과정을 확인해보시는 것을 추천드립니다. 이미지를 텐서로 변환하는 과정이 제대로 이루어지고 있는지, 그리고 변환된 텐서의 값이 적절한 범위에 있는지 확인해보세요. 또한, libtorch와 opencv의 버전을 최신 버전으로 업데이트해보시는 것도 좋을 것 같습니다.

아래는 이미지를 텐서로 변환하는 예제 코드입니다.

from torchvision import transforms
from PIL import Image

# 이미지 불러오기
image = Image.open('image.jpg')

# 이미지를 텐서로 변환
transform = transforms.Compose([
    transforms.ToTensor()
])
tensor = transform(image)

# 텐서의 값이 0과 1 사이에 있는지 확인
print(tensor.min(), tensor.max())

이 코드를 실행하여 텐서의 최소값과 최대값이 0과 1 사이에 있는지 확인해보세요.

더 자세한 정보는 PyTorch 공식 문서를 참조하시면 좋을 것 같습니다. 이미지를 텐서로 변환하는 방법에 대한 자세한 내용은 여기에서 확인하실 수 있습니다. 또한, libtorch를 사용하는 방법에 대한 자세한 내용은 여기에서 확인하실 수 있습니다.

그럼에도 불구하고 문제가 해결되지 않는다면, 좀 더 자세한 정보를 제공해주시면 감사하겠습니다. 예를 들어, 이미지 전처리 코드, forward를 실행하는 코드, 오류 메시지 등을 제공해주시면 문제를 더 정확하게 파악하는데 도움이 될 것입니다.

제가 제공한 해결 방법이 정확하지 않을 수도 있으니, 이 점 양해 부탁드립니다.


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

torch::Tensor ImageProcessor::post_process(cv::Mat& image){
resize(image, image, cv::Size(size, size));
if (!std::filesystem::exists("examples")) {
std::filesystem::create_directory("examples");
}
current_time = std::chrono::system_clock::now();
current_time_t = std::chrono::system_clock::to_time_t(current_time);
std::string img_path;
img_path.append("examples/").append(std::to_string((int)current_time_t)).append(".jpg");
if (std::filesystem::exists(img_path)) {
size_t lastDotIndex = img_path.find_last_of(".");
std::string filename = img_path.substr(0, lastDotIndex);
filename.append("-").append(".jpg");
imwrite(filename, image);
} else {
imwrite(img_path, image);
}
float MEAN = {0.48897059, 0.46548275, 0.4294};
float STD = {0.22861765, 0.22948039, 0.24054667};
cv::Mat float_image;
image.convertTo(float_image, CV_32FC3, 1.0 / 255);
float_image -= cv::Scalar(MEAN[0], MEAN[1], MEAN[2]);
float_image /= cv::Scalar(STD[0], STD[1], STD[2]);
torch::Tensor input_tensor = torch::from_blob(float_image.data, {1, size, size, 3}).permute({0, 3, 1, 2});
//std::cout << input_tensor.sizes() << std::endl;
return input_tensor;
}

다시 확인해보니 이 전처리 함수의 리턴값이 입력 이미지가 같은데도 다르게 나오는 경우가 생기는걸 발견했네요

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

안녕하세요 Yul963님,

제가 보기엔 이 문제는 PyTorch 모델을 C++환경에서 사용할 때 발생할 수 있는 이슈 같습니다.

요약하자면,

  1. PyTorch 모델을 Python에서 정상 동작하는 것을 확인했는데 C++ 환경에서 사용할 때 문제가 발생한 것으로 보입니다.

  2. C++에서 입력 이미지를 전처리하고 PyTorch 텐서로 변환한 뒤 모델에 통과시키면 결과 이미지가 깨지거나 런타임 에러가 발생합니다.

  3. Visual Studio, OpenCV, libTorch 버전도 언급해주셨습니다.

이 문제의 가능한 원인은 다음과 같습니다:

  • 입력 데이터의 전처리 과정에서 메모리 문제나 데이터 타입 변환 시 발생하는 이슈
  • C++과 Python 간 메모리 관리 차이에서 기인하는 문제
  • libTorch 버전과 Visual Studio 버전 조합의 호환성 문제

제가 추천하는 해결 방법은 다음과 같습니다:

  1. 입력 데이터 전처리 코드를 철저히 검토하세요. 특히 메모리 복사 및 데이터 타입 변환이 제대로 되고 있는지 확인이 필요합니다.

  2. 간단한 C++ 프로그램으로 libTorch 동작을 테스트해보세요. 기본 연산과 메모리 사용이 정상인지 확인하세요.

  3. Visual Studio와 libTorch 버전을 업데이트하거나 다운그레이드 해보세요. 호환성 문제일 가능성이 있습니다.

  4. 디버깅 모드로 실행하거나 로그를 출력해서 정확한 에러 포인트를 찾으세요.

  5. PyTorch 포럼이나 GitHub 이슈에서 도움을 요청하세요.

문제가 해결되지 않는다면 좀 더 자세한 코드와 에러 로그를 공유해주시면 도움을 드리겠습니다. PyTorch C++ 사용 시 발생할 수 있는 이슈이니 차분히 문제를 해결해 나가세요. 함께 해결하겠습니다!


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

추론서비스 목적으로 토치스크립트 사용 중이시라면,
혹시 model에 대해서 model.eval() 적용은 확인하셨는지요?

토치스크립트 변환을 torch.jit.trace로 하신다면 trace전에 model.eval() 적용을 하셔야할 것으로 생각되며
torch.jit.script의 경우는 추론시에 scripted_model.eval()을 적용해도 괜찮을 것으로 생각됩니다.

예전 글이긴 한데, 아래의 글도 참고해보세요.