Run Your First Model
| Field | Value |
|---|---|
| Difficulty | Beginner |
| Estimated Read Time | <5 minutes |
| Labels | model, inference, foundations |
Concept
Load a compiled ResNet-50 model archive, feed it an image, and read the top-1 class in three lines of Python. This is the shortest path from "I have a model archive" to "I have a prediction."
A compiled model is a deployable .tar.gz model archive containing an MPK inference contract that Neat can load and execute on the target device. It contains the model artifacts and runtime metadata needed for inference — you provide input, call run(), and read outputs.
APIs introduced
pyneat.Model(model_path)— load the compiled model.model.run(input, timeout_ms)— synchronous inference; returns aSamplewith the model's output tensor.timeout_msis the max wall time (ms) to wait for output.-1(the default) blocks indefinitely; any> 0value throws on timeout so stalls surface loudly. Prefer a finite value (e.g.2000) in production code,-1only when you trust the runtime to always produce output.
When to use this Fastest way to verify an model archive loads and runs on hardware. For throughput, batching, or live streams, move on to chapter 002.
Prerequisites None — this is the entry chapter.
References
Learning Process
- Set up runtime inputs: parse CLI args, locate the compiled ResNet50 model archive, and prepare sample input data.
- Build the minimal model execution path for one model and one input stream.
- Run synchronous inference to keep behavior deterministic and easy to debug.
Run
Python:
python3 share/sima-neat/tutorials/001_run_your_first_model/run_your_first_model.py \
--model /tmp/resnet_50.tar.gz
C++ (prebuilt):
./lib/sima-neat/tutorials/tutorial_001_run_your_first_model \
--model /tmp/resnet_50.tar.gz
C++ (build from source):
./build.sh --target tutorial_001_run_your_first_model
./build/tutorials-standalone/tutorial_001_run_your_first_model \
--model /tmp/resnet_50.tar.gz
To integrate this chapter's C++ source into your own project with a custom CMakeLists.txt (no extras folder required), see How to Run Tutorials on the landing page.
In Practice
Where the tutorials and tests look for model archives (.tar.gz) and sample assets, and how to provide them locally. This is the prerequisite for every model-backed tutorial.
Ensure sima-cli is on PATH
Some tests invoke sima-cli from non-interactive shells. Use this once after installing sima-cli:
SIMA_CLI_BIN_DIR="<path-to-sima-cli-bin>"
grep -Fqx "export PATH=\"${SIMA_CLI_BIN_DIR}:\$PATH\"" ~/.bashrc || echo "export PATH=\"${SIMA_CLI_BIN_DIR}:\$PATH\"" >> ~/.bashrc
source ~/.bashrc
Then verify:
/bin/sh -c 'command -v sima-cli'
Model archive locations and environment variables
Extraction/runtime placement knobs:
SIMA_MPK_EXTRACT_ROOT=<dir>sets the base extract directory.SIMA_MPK_CLEANUP_EXTRACTED=0preserves extractedproc_*model data after process exit.SIMA_MPK_EXTRACT_GC_STALE_PROC=0disables dead-proc_*cleanup on startup.
ResNet50
Search order:
SIMA_RESNET50_TAR(per-model override)SIMA_MODEL_TAR(shared fallback for model-archive tests/examples)tmp/resnet_50.tar.gz- Local files moved into
tmp/if found:resnet_50.tar.gz,resnet-50.tar.gz
Download (if sima-cli is available):
sima-cli modelzoo get resnet_50
YOLOv8 (v8s)
Search order:
SIMA_YOLO_TAR(per-model override)SIMA_MODEL_TAR(shared fallback for model-archive tests/examples)tmp/yolo_v8s.tar.gz- Common local names (moved into
tmp/if found):yolo_v8s.tar.gz,yolo-v8s.tar.gz,yolov8s.tar.gz,yolov8_s.tar.gz
Download (if sima-cli is available):
sima-cli modelzoo get yolo_v8s
Sample images
Default image candidates used in tutorials/tests:
tmp/coco_sample.jpg(downloaded if missing)test.jpgtests/assets/preproc_dynamic/ilena_488.jpg
You can override the COCO image URL used by tests with:
SIMA_COCO_URL=<custom_url>
Where tests download to
Tests and examples generally place downloaded assets under tmp/ in the repo root. Tutorials will skip gracefully if required assets are missing.
Troubleshooting assets
- If a tutorial prints
SKIP: missing ..., provide the asset or pass a flag (e.g.,--model <path>,--image <path>). - If
sima-cliis unavailable, set the env vars to point to local model archives.
Code
// Run a ResNet-50 model on an image in three lines of Neat.
//
// Usage:
// tutorial_001_run_your_first_model --model /path/to/resnet_50.tar.gz [--image /path/to.jpg]
#include "neat.h"
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <stdexcept>
#include <string>
namespace fs = std::filesystem;
namespace {
bool get_arg(int argc, char** argv, const std::string& key, std::string& out) {
for (int i = 1; i + 1 < argc; ++i) {
if (key == argv[i]) {
out = argv[i + 1];
return true;
}
}
return false;
}
cv::Mat load_rgb(const fs::path& image_path, int size) {
cv::Mat bgr = cv::imread(image_path.string(), cv::IMREAD_COLOR);
if (bgr.empty())
throw std::runtime_error("failed to read image: " + image_path.string());
if (bgr.cols != size || bgr.rows != size) {
cv::resize(bgr, bgr, cv::Size(size, size), 0, 0, cv::INTER_AREA);
}
cv::Mat rgb;
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
if (!rgb.isContinuous())
rgb = rgb.clone();
return rgb;
}
simaai::neat::Model::Options build_options(int size) {
simaai::neat::Model::Options opt;
opt.preprocess.color_convert.input_format = simaai::neat::PreprocessColorFormat::RGB;
opt.preprocess.input_max_width = size;
opt.preprocess.input_max_height = size;
opt.preprocess.input_max_depth = 3;
opt.preprocess.normalize.mean = {0.485f, 0.456f, 0.406f};
opt.preprocess.normalize.stddev = {0.229f, 0.224f, 0.225f};
return opt;
}
int top1_from_output(const simaai::neat::TensorList& out) {
if (out.empty())
throw std::runtime_error("no tensor output");
const simaai::neat::Mapping m = out.front().map_read();
const size_t n = m.size_bytes / sizeof(float);
const float* p = reinterpret_cast<const float*>(m.data);
int best = 0;
for (size_t i = 1; i < n && i < 1000; ++i) {
if (p[i] > p[best])
best = static_cast<int>(i);
}
return best;
}
} // namespace
int main(int argc, char** argv) {
try {
std::string model_path, image;
if (!get_arg(argc, argv, "--model", model_path)) {
std::cerr << "Usage: tutorial_001_run_your_first_model --model <path> [--image <path>]\n";
return 1;
}
get_arg(argc, argv, "--image", image);
const int size = 224;
// CORE LOGIC
// The three-line Neat story:
simaai::neat::Model model(model_path, build_options(size));
cv::Mat input = image.empty() ? cv::Mat(size, size, CV_8UC3, cv::Scalar(99, 99, 99))
: load_rgb(image, size);
simaai::neat::TensorList sample = model.run(std::vector<cv::Mat>{input}, /*timeout_ms=*/2000);
std::cout << "top1=" << top1_from_output(sample) << "\n";
std::cout << "[OK] 001_run_your_first_model\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "[FAIL] " << e.what() << "\n";
return 1;
}
}