Run Your First Model
| Field | Value |
|---|---|
| Difficulty | Beginner |
| Estimated Read Time | <5 minutes |
| Labels | model, mpk, inference, foundations |
Concept
Load a compiled ResNet-50 MPK, 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 package" to "I have a prediction."
A compiled model is a deployable model package (.tar.gz, often called an MPK) 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(mpk_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 MPK 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 MPK, 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 \
--mpk /tmp/resnet_50_mpk.tar.gz
C++ (prebuilt):
./lib/sima-neat/tutorials/tutorial_001_run_your_first_model \
--mpk /tmp/resnet_50_mpk.tar.gz
C++ (build from source):
./build.sh --target tutorial_001_run_your_first_model
./build/tutorials-standalone/tutorial_001_run_your_first_model \
--mpk /tmp/resnet_50_mpk.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.
Code
// Run a ResNet-50 model on an image in three lines of Neat.
//
// Usage:
// tutorial_001_run_your_first_model --mpk /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 mpk, image;
if (!get_arg(argc, argv, "--mpk", mpk)) {
std::cerr << "Usage: tutorial_001_run_your_first_model --mpk <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(mpk, 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;
}
}