모델
Model은 컴파일된 모델 아카이브를 로드하고 Neat이 실행할 수 있는 경로를 노출합니다.
각 전처리, 추론 및 후처리 단계를 수동으로 연결하지 않고 모델을 인식하는 방식으로 실행하려는 경우 Model을 사용합니다. 먼저 계약을 검사한 다음 실행합니다. 알 수 없는 텐서는 없습니다.
Model이 제공하는 기능
input_specs()및output_specs()는 모델이 예상하고 생성하는 텐서 계약을 보여줍니다.metadata(),info()및 Pythonsummary()는 로드된 모델을 검사하는 데 도움이 됩니다.run(...)은 단일 추론을 실행합니다.build(...)는 푸시/풀 실행을 위한 재사용 가능한 모델 러너를 만듭니다.graph()는 모델 경로를 재사용 가능한Graph조각으로 반환합니다.preprocess(),inference()및postprocess()는 고급 구성을 위한 경로 단계를 노출합니다.
참조:
모델 아카이브 로드
이 페이지의 예제에서는 model_path가 Model Compiler에서 컴파일된 모델 아카이브를 가리키고, 일반적으로 Neat을 실행하는 시스템에 복사된 .tar.gz 파일을 사용한다고 가정합니다. 먼저 기본 옵션을 사용하고, 계약 또는 입력 소스에서 필요한 경우에만 ModelOptions를 추가합니다.
const std::string model_path = "resnet_50_model.tar.gz";
simaai::neat::Model model(model_path);
const auto info = model.info();
const auto inputs = model.input_specs();
const auto outputs = model.output_specs();
이 검사 단계가 예상치 못한 결과를 보인다면, 여기서 멈추세요. 더 큰 애플리케이션을 작성하기 전에 모델 경로, 아티팩트 또는 계약을 수정하세요.
모델 실행 경로 선택
작업에 맞는 경로를 선택하세요. 간단한 테스트는 작게 유지하고, 그래프 수준의 문제를 해결하기 위해 그래프 수준의 기능을 사용하세요.
| 필요 | 사용 | 반환 값 |
|---|---|---|
| 모델 입력을 한 번 실행 | model.run(...) | 텐서 입력의 경우 TensorList, 샘플 입력의 경우 Sample |
| 여러 입력에 걸쳐 모델 경로 재사용 | model.build(...) 및 모델 러너 | 모델 경로 주변의 푸시/풀 제어 |
| 모델 실행만 측정 | model.benchmark(...) 또는 측정된 모델 러너 | BenchmarkReport 또는 MeasureReport |
| 모델을 애플리케이션 흐름에 포함 | graph.add(model) | Graph 단계 |
| 구성에 대한 경로 경계 노출 | model.graph(route_options) | 재사용 가능한 Graph 조각 |
| 하나의 모델 단계를 디버깅 | model.fragment(ModelStage::...) | 단계별 Graph 조각 |
직접적인 모델 호출을 사용하여 확실하게 하세요. 모델이 애플리케이션의 일부가 될 때 Graph를 사용하세요. (예: 명명된 입력, 소스 노드, 분기, 조인, 렌더링, 비디오 출력, 메타데이터 출력 또는 여러 모델)
모델 옵션 선택
기본 ModelOptions로 시작하세요. 모델 계약 또는 입력 소스에서 필요한 경우에만 옵션을 추가하세요.
| 목표 | 사용할 옵션 | 참고 사항 |
|---|---|---|
| 디코딩된 이미지 입력을 전송 | preprocess.kind, preprocess.preset 및 크기 조정, 색상, 레이아웃, 정규화, 양자화 또는 테셀레이션과 같은 특정 전처리 필드 | 애플리케이션에서 픽셀을 전송하고 Neat가 이를 모델 계약에 맞게 조정해야 할 때 사용하세요. |
| 모델 모양의 텐서 입력을 전송 | preprocess.kind = Tensor; 텐서가 이미 모델 계약을 충족하는 경우에만 preprocess.enable = Off를 설정하세요. | 애플리케이션에서 이미 전처리를 수행하는 경우에 사용하세요. |
| 감지 출력을 디코딩 | decode_type, decode_type_option, score_threshold, nms_iou_threshold, top_k, num_classes | 감지 모델은 명시적인 디코딩 의도가 필요합니다. |
| 추출된 모델 파일을 검사를 위해 보관 | cleanup_extracted_model_data = false | 디버깅 중에 유용합니다. 일반 실행에서는 기본값을 유지하세요. |
| 하나의 프로세스에서 여러 모델 경로 실행 | name_suffix 및 그래프 요소 이름 접두사/접미사 | 생성된 이름과 진단 정보를 읽기 쉽게 유지합니다. |
| 모델 경로 조기 중단 | inference_terminal | 고급 경로 디버깅 경로입니다. 처음 실행하는 코드에는 사용하지 마세요. |
| 실행 배치 또는 내부 큐 조정 | processcvu, processmla, advanced_execution | 고급 기능입니다. 조정하기 전에 기본 경로를 먼저 측정하세요. |
감지 디코딩을 사용한 이미지 입력
모델이 이미지 전처리를 예상하고 YOLO 스타일의 감지 결과를 출력할 때 이 패턴을 사용하세요.
simaai::neat::Model::Options options;
options.preprocess.kind = simaai::neat::InputKind::Image;
options.preprocess.preset = simaai::neat::NormalizePreset::COCO_YOLO;
options.decode_type = simaai::neat::BoxDecodeType::YoloV8;
options.score_threshold = 0.25f;
options.nms_iou_threshold = 0.45f;
options.top_k = 100;
simaai::neat::Model model(model_path, options);
설정을 일관성 있게 유지하세요. 필요한 계약 내용을 변경하지 않는 한 기본값이나 더 이상 사용되지 않는 필드를 설정하지 마세요. 텐서 또는 이미지 메타데이터에 이미 소스 형식이 포함되어 있는 경우, 페이지에서 그 이유를 설명하지 않는 한 반복하지 않도록 하세요.
객체 감지 디코딩 필드 가이드
경로가 원시 추론 텐서 대신 디코딩된 박스, 포즈 결과 또는 분할 결과를 반환해야 할 때 객체 감지 디코딩 옵션을 설정하세요. 원시 모델 출력을 원하는 경우 필드를 설정하지 않은 상태로 두세요.
| 필드 | 사용 시점 | 기본 의미 |
|---|---|---|
decode_type | 객체 감지 모델에 BoxDecode 단계를 연결하기 위해 Neat이 필요합니다. | Unspecified; 객체 감지 디코딩 의도가 없습니다. |
decode_type_option | 객체 감지 헤드 텐서 순서에 특정 변형이 필요합니다. | Auto; 모델 계약 및 경로 계획자가 결정하도록 합니다. |
score_threshold | 디코딩 중에 낮은 신뢰도의 후보를 제거하려는 경우. | 0; 이후 필터링 전에 후보를 유지합니다. |
nms_iou_threshold | 디코딩 경로에 비최대값 억제(NMS)를 적용해야 합니다. | 0; NMS가 비활성화됩니다. |
top_k | 출력당 감지 횟수에 제한을 두려는 경우. | 0; 상위 K 제한이 없습니다. |
num_classes | 클래스 헤드 깊이를 안정적으로 추론할 수 없는 경우(예: 단일 클래스 YOLO 분할 헤드). | 0; MPK 메타데이터 또는 이전 추론을 사용합니다. |
대부분의 YOLO 스타일 모델의 경우 decode_type, score_threshold, nms_iou_threshold 및 top_k로 시작하세요. 모델 계약에 도움이 필요한 경우에만 num_classes를 추가하세요. 텐서 순서에 특정 선택자가 필요한 것으로 알려지지 않은 한 decode_type_option을 Auto로 유지하세요.
simaai::neat::Model::Options options;
options.decode_type = simaai::neat::BoxDecodeType::YoloV8;
options.score_threshold = 0.25f;
options.nms_iou_threshold = 0.45f;
options.top_k = 100;
options.num_classes = 1; // Set only when the model contract needs the class count.
simaai::neat::Model model(model_path, options);
새 예제에서는 boxdecode_original_width 또는 boxdecode_original_height를 사용하지 마십시오. 좌표 반전은 전처리 메타데이터를 사용합니다. 이미지 크기를 하드 코딩하는 대신 해당 메타데이터를 유지하십시오.
원시 텐서 입력
앱에서 이미 컴파일된 모델에서 예상하는 형태, 데이터 유형 및 레이아웃으로 텐서를 생성하는 경우 이 패턴을 사용하십시오.
simaai::neat::Model::Options options;
options.preprocess.kind = simaai::neat::InputKind::Tensor;
options.preprocess.enable = simaai::neat::AutoFlag::Off;
simaai::neat::Model model(model_path, options);
텐서가 아직 모델에 적합한 형태로 되어 있지 않다면, 이 단계를 강제로 적용하지 마세요. 전처리 과정을 통해 텐서를 조정하거나, 텐서 생성 코드를 수정하세요.
전처리 필드 가이드
ModelOptions.preprocess는 어떤 종류의 입력을 제공할지, 그리고 Neat이 추론 전에 어떤 방 식으로 조정할지를 나타냅니다.
| 필요 | 필드 |
|---|---|
| 이미지 또는 텐서 입력 선택 | preprocess.kind |
| 이미 형태가 지정된 텐서에 대한 전처리 비활성화 | preprocess.enable = Off |
| 동적 이미지 입력 제한 | preprocess.input_max_width, preprocess.input_max_height, preprocess.input_max_depth |
| 크기 조정, 자르기 또는 레터박스 적용 | preprocess.resize |
| RGB, BGR, NV12, I420 또는 흑백으로 변환 | preprocess.color_convert |
| HWC, CHW 또는 다른 축 순서로 변환 | preprocess.layout_convert |
| 평균/표준 편차 정규화 적용 | preprocess.normalize 또는 preprocess.preset |
| 추론 전에 양자화 | preprocess.quantize |
| 추론 전에 테셀레이션 | preprocess.tessellate |
| 순서가 지정된 변환 목록으로 재정의 | preprocess.transforms |
실제로 전송하는 입력에 대한 가장 작은 옵션 세트를 설정하세요. 사양은 계약이고, 결정된 전처리 계획은 영수증입니다.
사양 검토 및 직접 실행
Graph를 구성하기 전에 모델 계약을 검토하세요. 사양은 무엇을 할당하고, 전송하고, 디코딩해야 하는지 알려줍니다.
simaai::neat::Model model(model_path, options);
const auto inputs = model.input_specs();
const auto outputs = model.output_specs();
const auto metadata = model.metadata();
const auto info = model.info();
for (const auto& input : inputs) {
const auto& shape = input.shape;
}
for (const auto& output : outputs) {
const auto& shape = output.shape;
}
simaai::neat::Tensor input = simaai::neat::Tensor::from_cv_mat(
frame,
simaai::neat::ImageSpec::PixelFormat::BGR,
simaai::neat::TensorMemory::CPU);
simaai::neat::TensorList result = model.run(
simaai::neat::TensorList{input},
/*timeout_ms=*/2000);
Python에서는 입력 목록 또는 튜플을 전달합니다. model.run([tensor])는 “모델 입력 하나”를 의미합니다. 배치 차원을 추가하지 않습니다.
model.run(...)은 호출할 때마다 다시 빌드하는 방식이 아니라 한 번에 실행되는 방식입니다. 첫 번째 호출 시 내부 실행기를 지연 방식으로 빌드하고 캐시하며, 이후 호출에서는 해당 실행기를 재사용하고 이를 통해 데이터를 전달합니다. 라우팅 옵션, 런타임 옵션, 측정, 종료/비우기 제어 또는 프로듀서/컨슈머 루프가 필요한 경우 명시적인 model.build(...)를 사용하십시오.
OpenCV 지원으로 빌드된 C++는 model.run(std::vector<cv::Mat>{frame}, timeout_ms)를 노출합니다. 예제에서 픽셀 형식 또는 메모리 소유권을 명시해야 하는 경우 명시적인 Tensor::from_cv_mat(...) 경로를 사용하십시오.
여러 입력 및 배치와 함께 작업
모델은 여러 입력 포트, 컴파일된 배치 크기 또는 둘 다를 가질 수 있습니다. 이러한 개념을 혼합하지 마십시오.
- 여러 입력은 모델 입력당 텐서 하나를 의미합니다. 예상되는 순서와 계약을 확인하려면
model.input_specs()를 검사하십시오. - 배치는 모델이 추론당 여러 논리적 샘플을 처리하도록 컴파일되었음을 의미합니다.
model.compiled_batch_size()를 검사하십시오. - Python 입력 목록은 배치 차원이 아닌 입력 목록을 선택합니다.
model.run([tensor])는 입력 하나입니다.tensor를 배치 크기 1로 변환하지 않습니다.
const int batch = model.compiled_batch_size();
const auto specs = model.input_specs();
// Two-input model: pass one tensor per ingress.
simaai::neat::TensorList inputs{left_tensor, right_tensor};
simaai::neat::TensorList outputs = model.run(inputs, /*timeout_ms=*/2000);
일괄 처리 모델이 [N, ...] 형태를 예상하는 경우, 입력 사양에 따라 텐서 형태에 N을 넣습니다. 모델에 N 입력 포트가 없는 한, N 별도의 Python 목록 항목을 전달하지 마십시오.
라우트 계획 검사
전처리, 출력 토폴로지 또는 라우트 선택이 예상과 다를 경우, 추측하기보다는 라우트를 검사하십시오.
| 질문 | 검사 |
|---|---|
| 모델이 어떤 텐서 형태와 데이터 유형을 노출합니까? | input_specs() 및 output_specs() |
| 컴파일된 아티팩트는 무엇을 선언했습니까? | info() 및 metadata() |
| 전처리는 어떤 입력을 예상합니까? | preprocess_requirements() |
| Neat은 어떤 전처리 경로를 컴파일했습니까? | resolved_preprocess_plan() / Python preprocess_plan() |
| 어떤 배치 크기가 컴파일되었습니까? | compiled_batch_size() |
| 어떤 출력 형식을 디코딩해야 합니까? | 출력 사양 + info().output_topology |
const auto requirements = model.preprocess_requirements();
const auto plan = model.resolved_preprocess_plan();
std::cout << "preprocess: " << plan.to_debug_string() << "\n";
해결된 계획은 감사 추적 기록입니다. 여기에는 요청된 옵션, 적용된 옵션, 그래프 계열, 입력 계약, MLA 계약 및 경고가 포함됩니다.
모델 경로 스냅샷을 읽습니다.
모델 아카이브를 직접 읽지 않고 간결한 경로 스냅샷이 필요한 경우 info()를 사용합니다. Python은 또한 빠른 텍스트 보기를 위해 summary()를 제공합니다. C++는 구조화된 info() 결과를 사용합니다.
| 질문 | 검사할 info() 필드 |
|---|---|
| 어떤 아티팩트를 로드했습니까? | model_name, mpk_json_path |
| 어떤 어댑터 단계가 필요합니까? | needs |