포스트

라즈베리파이에서 NCS2 추론이 막힐 때: OpenVINO IR 변환 체크리스트

NCS2에서 추론하려면 학습된 TensorFlow 모델을 그대로 꽂는 것이 아니라, 컴퓨터에서 모델을 동결하고 OpenVINO의 .xml, .bin IR 쌍으로 변환한 뒤 라즈베리파이에서 MYRIAD 장치로 불러와야 합니다. 장치가 운영체제에 보이지 않는 문제와 변환된 모델의 shape가 틀린 문제는 증상이 비슷해도 해결 위치가 다릅니다. PB, XML/BIN, 실제 입력 tensor를 단계별로 검증하면 오래된 명령을 무작정 반복하지 않고 실패 지점을 좁힐 수 있습니다.

학습부터 NCS2 추론까지 역할을 나누기

이 기록의 구성은 Raspberry Pi 3, Neural Compute Stick 2, OpenVINO를 전제로 합니다. OpenVINO는 TensorFlow나 Caffe처럼 신경망을 학습시키는 도구가 아니라, 준비된 모델을 최적화하고 추론하는 흐름에 놓입니다.

OpenVINO와 기존 SDK 비교

작업을 장치별로 나누면 혼란이 줄어듭니다.

  1. 컴퓨터에서 모델을 학습하고 checkpoint를 저장합니다.
  2. 추론에 필요한 output node를 정해 .pb 그래프를 동결합니다.
  3. 컴퓨터의 Model Optimizer로 .xml.bin을 만듭니다.
  4. 라즈베리파이에서 Inference Engine과 NCS2를 연결합니다.
  5. 사용자 애플리케이션이 IR 파일을 읽어 추론합니다.

라즈베리파이에는 이 기록에서 사용한 .pb 변환 도구가 없으므로 변환 단계는 Windows의 OpenVINO 환경에서 진행했습니다. 핵심 판단은 “어디에서 학습하고, 어디에서 변환하고, 어디에서 추론할지”를 분리하는 것입니다.

라즈베리파이 설치에서 먼저 확인할 것

당시 설치 기록은 Intel의 Raspberry Pi 안내를 따라 작성됐습니다. 다음 다운로드 주소와 명령은 2019년 패키지명을 사용하는 역사적 기록입니다.

1
wget https://download.01.org/opencv/2019/openvinotoolkit/R1/l_openvino_toolkit_raspbi_p_2019.1.094.tgz

원문의 압축 해제 표기에는 <version> placeholder가 남아 있고 실제 다운로드 파일명과도 다릅니다. 아래는 명령 구조를 보여주는 조각이지 그대로 붙여 넣는 완전 실행법이 아닙니다. 받은 파일명과 설치 경로로 바꿔야 합니다.

1
2
3
cd ~/Downloads/
tar -xf l_openvino_toolkit_ie_p_<version>.tgz
sed -i "s|<INSTALLDIR>|$(pwd)/inference_engine_vpu_arm|" inference_engine_vpu_arm/bin/setupvars.sh

환경 변수는 ~/.bashrc 마지막에 실제 설치 경로의 setupvars.sh를 불러오도록 설정합니다. USB 권한을 위해 현재 사용자를 users 그룹에 추가하고 NCS udev 규칙 스크립트를 실행하는 과정도 필요합니다.

1
2
sudo usermod -a -G users "$(whoami)"
sh inference_engine_vpu_arm/install_dependencies/install_NCS_udev_rules.sh

샘플을 빌드할 때는 samples 디렉터리에서 CMake를 사용하고, NCS2 장치는 실행 인자에서 MYRIAD로 지정합니다. 입력 이미지 경로가 남은 다음 표기는 완성 명령이 아니라 인자 형식입니다.

1
./armv7l/Release/object_detection_sample_ssd -m face-detection-adas-0001.xml -d MYRIAD -i <path_to_image>

NCS2 샘플 실행 화면

NCS2 얼굴 검출 결과

PB를 XML과 BIN으로 바꿀 때 생기는 오류

TensorFlow 모델은 먼저 변수 값을 상수로 바꾼 frozen graph가 필요합니다. 아래 코드는 전체 저장 프로그램이 아니라 이미 열린 sess와 정확한 output_node_name이 있다는 전제의 핵심 조각입니다.

1
2
3
4
5
6
from tensorflow.python.framework import graph_io

frozen = tf.graph_util.convert_variables_to_constants(
    sess, sess.graph_def, ["output_node_name"]
)
graph_io.write_graph(frozen, "./", "graph.pb", as_text=False)

TensorBoard 그래프와 summarize_graph.py로 입력과 출력 이름을 먼저 확인해야 합니다. 원문 모델의 입력은 [1, -1, -1, 3]이었고, 변환할 때 실제 추론 크기 [1, 256, 256, 3]을 지정했습니다.

1
2
python summarize_graph.py --input_model mcnn.pb
python mo_tf.py --input_model mcnn.pb --input_shape [1,256,256,3]

이 두 줄도 당시 Windows OpenVINO Model Optimizer 디렉터리와 파일이 준비됐을 때의 명령입니다. 입력이 둘 이상이거나 shape와 output node가 모델과 맞지 않으면 변환 오류가 날 수 있습니다. 학습 단계에서 추론용 입력을 하나로 정리하고, 저장할 때 지정한 output node를 TensorBoard에서 다시 확인하는 것이 우선입니다.

그래프 입력 정보 확인

Model Optimizer 변환 성공 화면

성공 여부를 판단하는 최소 점검표

IR 변환이 끝났다고 배포가 끝난 것은 아닙니다. .xml은 네트워크 구조, .bin은 가중치이므로 두 파일을 같은 모델 쌍으로 옮겨야 합니다. 그다음 다음 항목을 순서대로 확인합니다.

  • 라즈베리파이에서 setupvars.sh가 실제 설치 경로를 가리키는가
  • NCS2의 udev 규칙과 사용자 그룹 설정이 적용됐는가
  • Model Optimizer에 준 input shape가 애플리케이션의 이미지 크기와 같은가
  • 저장한 output node 이름이 추론하려는 출력과 같은가
  • 실행 장치가 MYRIAD로 지정됐는가

이 글의 설치 URL, 폴더명과 TensorFlow API는 당시 버전에 묶여 있습니다. 최신 환경의 범용 설치법으로 포장하기보다, Windows 설치 문서, TensorFlow 모델 변환 안내, 그래프 저장 예제를 해당 패키지와 대조하며 변환 파이프라인을 이해하는 자료로 사용하는 편이 안전합니다.

오류 메시지는 어느 단계의 문제를 뜻하나

lsusb 수준에서 장치가 보이지 않으면 케이블, 포트, 전원과 운영체제 인식부터 봅니다. 장치는 보이지만 응용 프로그램이 접근하지 못한다면 udev 규칙과 사용자 권한을 확인합니다. 이 단계에서는 모델 파일을 바꿀 이유가 없습니다. 반대로 장치 로드는 되지만 네트워크를 읽지 못한다면 XML/BIN 쌍과 대상 장치가 지원하는 정밀도를 살펴야 합니다.

입력 오류는 세 값을 나눠 기록하면 찾기 쉽습니다. 원본 그래프의 input 이름과 shape, Model Optimizer에 지정한 shape, 추론 직전 배열의 shape입니다. 공간 크기만 같아도 채널 순서나 batch 축이 다르면 올바른 입력이 아닙니다. 출력도 동결할 때 지정한 node와 애플리케이션이 읽는 layer 이름이 같은지 대조해야 합니다.

마지막으로 변환 성공과 의미 있는 추론을 구분합니다. 파일이 생성되고 장치에 로드됐다는 사실은 전처리와 후처리가 맞다는 뜻이 아닙니다. 같은 입력을 원래 환경과 NCS2 경로에 넣어 출력 shape와 값의 범위를 비교하고, 모델이 기대한 resize, 정규화가 적용됐는지 확인해야 배포 성공으로 볼 수 있습니다.

함께 읽으면 이해가 이어지는 글

자주 묻는 질문

NCS2가 인식되지 않을 때 모델 변환부터 다시 해야 하나요?

먼저 USB 장치 인식, udev 규칙, 사용자 그룹과 OpenVINO 환경 변수를 확인해야 합니다. 장치 계층 문제라면 PB나 IR을 다시 만들어도 해결되지 않습니다.

OpenVINO의 XML과 BIN은 각각 무엇인가요?

XML은 변환된 네트워크 구조를, BIN은 가중치를 담습니다. 서로 다른 변환에서 나온 파일을 섞으면 안 되며 같은 출력 디렉터리에서 생성된 쌍을 함께 배포해야 합니다.

이 글의 설치 명령은 현재 환경에도 그대로 적용되나요?

아닙니다. 2019년의 Raspberry Pi와 OpenVINO API를 기준으로 한 기록입니다. 현재 패키지의 지원 장치와 경로를 확인하되, 학습, 동결, 변환, 실행을 분리해 진단하는 순서를 참고해야 합니다.

변환 파일을 다시 만들기 전 확인할 체크포인트

PB 단계에서는 그래프를 읽을 수 있는지, input과 output node가 무엇인지, 변수 값이 상수로 동결됐는지를 확인합니다. 파일 크기만으로 정상 여부를 판단하지 않습니다. 같은 테스트 입력을 원래 TensorFlow 경로에 넣어 기준 output을 저장해 두면 IR 결과를 비교할 수 있습니다.

Model Optimizer 단계에서는 실행한 전체 명령, 변환 로그, 생성 시각을 XML/BIN 쌍과 함께 보관합니다. 이름만 같은 오래된 BIN이 남아 있으면 구조와 가중치가 다른 조합을 배포할 수 있습니다. 입력 shape와 정밀도를 파일명이나 기록에 남겨 애플리케이션 설정과 대조합니다.

장치 단계에서는 NCS2가 없는 CPU 경로와 있는 MYRIAD 경로를 구분해 실행합니다. 같은 전처리 입력에서 output shape와 주요 값이 어느 정도 대응하는지 확인한 뒤 실제 카메라로 넘어갑니다. 이 순서를 지키면 카메라, USB, 모델 변환 오류가 한 번에 섞이는 것을 피할 수 있습니다.

배포 파일에는 모델 이름만 적지 말고 원본 checkpoint, output node, 변환 옵션과 생성한 XML/BIN의 대응을 남깁니다. 모델을 다시 학습한 뒤 파일명만 덮어쓰면 장치에 어느 가중치가 올라갔는지 확인하기 어렵습니다. 고정 입력의 예상 결과까지 함께 보관하면 파일 교체 후 빠르게 회귀 검사를 할 수 있습니다.

실행 중 USB가 분리되는 경우와 잘못된 IR을 지정한 경우의 오류도 확인합니다. 프로그램이 재시도하는지 종료하는지, 사용자에게 어떤 로그를 남기는지를 정해야 합니다. 정상 추론 시간만 측정하고 실패 동작을 확인하지 않으면 장치 데모를 운영 가능한 배포로 오해할 수 있습니다.

THE END / OPSOAI

여기까지 읽었습니다

핵심 장면을 한 번 더 떠올려 보세요. 이해가 남았다면 이 책은 제 역할을 다했습니다.

다른 책 고르기
표지 1

키와 좌우 스와이프를 지원합니다. 읽던 페이지는 이 기기에 저장됩니다.

CONTENTS

이 책의 목차

    8개 장 15 분읽는 시간