Edge AI: запуск моделей искусственного интеллекта на устройствах

За последние годы мне не раз приходилось запускать модели ИИ на edge-устройствах — от Raspberry Pi и Jetson до STM32 и ESP32. И речь не про лабораторные демо, а про вполне прикладные задачи: обнаружение объектов с камеры на мобильной платформе, локальная фильтрация событий на промышленном узле, анализ вибраций для предиктивного обслуживания, простая аудиоклассификация на микроконтроллере. Во всех этих сценариях быстро выясняется одна и та же вещь: если модель не умеет работать прямо на устройстве, проект начинает зависеть от сети, облака, задержек и лишней инфраструктуры.

В этой статье разберём, как запускать модели искусственного интеллекта на устройствах пошагово: что нужно по железу, как подготовить модель, чем её конвертировать, где чаще всего возникают проблемы с памятью и производительностью, и как собрать рабочий прототип без лишней магии. Постараюсь дать не только общую схему, но и инженерные акценты, которые обычно всплывают уже в реальной разработке.

Что такое Edge AI и зачем это нужно инженеру

Edge AI — это запуск моделей машинного обучения непосредственно на конечном устройстве, без постоянной опоры на облако. Вместо того чтобы передавать сырые данные на внешний сервер и ждать ответ, устройство само выполняет инференс локально: будь то камера, смартфон, промышленный контроллер, одноплатный компьютер или микроконтроллер.

Для инженера это не модный термин, а вполне практический архитектурный выбор. Как только система должна принимать решения быстро и предсказуемо, локальный инференс становится почти обязательным.

Почему это важно:

  • Низкая задержка: решение принимается за миллисекунды, что критично для автономных роботов, систем безопасности, машинного зрения на конвейере.
  • Офлайн-работа: если интернет пропал или канал нестабилен, ИИ продолжает работать локально.
  • Экономия трафика и приватность: данные не нужно постоянно отправлять в облако, а значит меньше расходов и меньше рисков с точки зрения безопасности.
  • Масштабируемость: когда устройств много, локальная обработка снимает нагрузку с серверной части.

В реальных проектах edge AI особенно хорошо показывает себя там, где связь нестабильна, а поток данных непрерывный. Камера может выдавать десятки кадров в секунду, вибродатчик — поток телеметрии, аудиомикрофон — непрерывный сигнал. Если всё это отправлять наружу без фильтрации, канал и бюджет заканчиваются очень быстро. А если часть логики перенести на устройство, система становится и быстрее, и устойчивее.

На embedded-платформах это ещё заметнее. Там приходится учитывать не только скорость, но и батарею, объём RAM, тепловой режим, а иногда и отсутствие полноценной ОС. Поэтому Edge AI — это всегда не только про модель, но и про инженерный компромисс между точностью, временем отклика и ограничениями железа.

Преимущества Edge AI перед облачными решениями

Аспект Edge AI Облако
Задержка <10 мс 50–500 мс
Зависимость от сети Нет Полная
Стоимость Разовая (аппарат) Подписка + трафик
Безопасность Данные локально Риск утечек
Ресурсы устройства Низкие (после оптимизации) Не требуется

На практике выбор между edge и облаком редко бывает идеологическим — он почти всегда связан с требованиями системы. Если проект должен работать в реальном времени, edge-подход обычно выигрывает. Это касается компьютерного зрения на производстве, голосового управления в умном доме, локального анализа вибраций на станках, контроля доступа, мобильной робототехники.

При этом стоит понимать нюанс: edge AI не отменяет облако как класс. Часто оптимальная архитектура гибридная. Например, базовый инференс идёт локально на устройстве, а агрегированные события, метрики и редкие сложные случаи уже отправляются на сервер. Такой подход я не раз видел в промышленных системах: устройство само решает, что является аномалией, а в облако уходит уже не весь поток, а только полезный сигнал.

Если же вам нужна жёсткая детерминированность, минимальная задержка и работа без сети, edge AI обычно оказывается не просто удобным вариантом, а единственно разумным.

Требования к аппаратной части для запуска моделей ИИ

Не каждое устройство адекватно потянет модель искусственного интеллекта на edge. До выбора фреймворка и оптимизаций всегда полезно трезво оценить платформу. В embedded-разработке ошибки на этом этапе стоят дорого: если модель не помещается в память или стабильно перегревает устройство, потом это не исправить одной “магической” настройкой.

Начните с базовой проверки:

  • Процессор: ARM Cortex-A для Linux-устройств вроде Raspberry Pi 4/5, NPU в Snapdragon, GPU/Tensor-ускорители у Jetson Nano и старших моделей.
  • Память: минимум 1 ГБ RAM для комфортной работы с типовыми edge-моделями; для совсем компактных сценариев возможны 512 МБ.
  • Хранение: SD-карта или eMMC от 8 ГБ — этого достаточно для ОС, зависимостей, модели и логов.
  • Периферия: USB для отладки и периферии, GPIO/I2C/SPI/UART для датчиков и исполнительных модулей.

Если говорить предметно, то для запуском моделей ИИ на Raspberry Pi обычно достаточно Pi 4 с 4 ГБ — это хороший рабочий минимум, особенно если модель класса MobileNet или PoseNet. На STM32H7 уже совсем другая история: там можно запускать только компактные сети уровня TinyML, причём с жёстким контролем размера весов, промежуточных буферов и стека.

Таблица совместимости популярных платформ:

Платформа MAX FLOPS Поддержка фреймворков Примеры задач
Raspberry Pi 5 2–5 TFLOPS TensorFlow Lite, ONNX Обнаружение объектов
NVIDIA Jetson Nano 0.5 TFLOPS TensorRT Компьютерное зрение
ESP32 0.1 GFLOPS TensorFlow Lite Micro Классификация аудио
STM32Cube.AI 0.5 GFLOPS STM32 AI Сенсоры IoT

На Linux-устройствах полезно начать с простой проверки:

cat /proc/cpuinfo

Так вы увидите архитектуру, число ядер и частоты. Дополнительно я обычно смотрю ещё доступную память, тип накопителя и наличие аппаратного ускорения. На практике именно узкие места по памяти и пропускной способности ввода-вывода чаще ломают ожидания по производительности, чем “сырая” частота CPU.

И ещё один инженерный нюанс: не оценивайте платформу только по пиковым цифрам. Важно, как устройство ведёт себя под длительной нагрузкой. Некоторые SBC на бумаге выглядят отлично, а через 10–15 минут непрерывного инференса начинают троттлить из-за температуры. Если система должна работать 24/7, это нужно проверять в самом начале.

Подготовка модели для edge-устройств: конвертация и оптимизация

Почти всегда сырая модель из PyTorch или TensorFlow в продакшен на устройстве не идёт напрямую. Она слишком тяжёлая по размеру, использует неподходящие операции или банально не помещается в доступную память. Поэтому перед развёртыванием модель обычно конвертируют в TensorFlow Lite или ONNX, а затем оптимизируют под конкретную платформу.

В реальной работе подготовка модели — это не второстепенный этап, а одна из ключевых частей проекта. Именно здесь решается, сможете ли вы получить нужный FPS, уложиться в лимит RAM и не потерять слишком много точности.

Шаг 1: Квантизация

Квантизация уменьшает разрядность весов и активаций, например переводит модель из float32 в int8. На практике это даёт очень ощутимый выигрыш: размер модели может уменьшиться примерно в 4 раза, а скорость инференса — вырасти до 3x, особенно на платформах, где есть хорошие integer-оптимизации.

Код на Python:

import tensorflow as tf

model = tf.keras.models.load_model("model.h5")
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()

with open("model.tflite", "wb") as f:
    f.write(tflite_model)

После конвертации полезно сразу проверить, что модель корректно загружается:

import tflite_runtime.interpreter as tflite

interpreter = tflite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()

Если interpreter.allocate_tensors() проходит без ошибок, это уже хороший признак: минимум на уровне структуры модель валидна и рантайм умеет с ней работать.

Из практики: квантизация почти всегда оправдана для edge-сценариев, но важно проверять не только итоговую accuracy, а поведение именно на целевых данных. Бывает, что на общем validation set падение незначительное, а на реальном потоке с шумными сенсорами или плохим освещением деградация становится заметной. Особенно это касается задач компьютерного зрения и аудиоклассификации.

Шаг 2: Прuninг и дистилляция

Следующий уровень оптимизации — pruning и дистилляция. При pruning из модели удаляются малозначимые связи или “мёртвые” нейроны, что уменьшает вычислительную нагрузку. В TensorFlow для этого можно использовать, например, tf.keras.utils.prune_low_magnitude.

Дистилляция — это отдельный полезный приём, когда компактная модель-студент обучается повторять поведение более тяжёлой модели-учителя. В edge-проектах этот метод часто даёт более практичный результат, чем попытка любой ценой запихнуть исходную большую сеть в слабое железо.

Нюанс в том, что pruning сам по себе не всегда автоматически ускоряет модель на конкретном рантайме. Иногда вы уменьшаете число параметров, но не получаете такого же выигрыша по времени инференса из-за особенностей исполнения операций. Поэтому любые такие оптимизации нужно прогонять через реальный бенчмарк на устройстве, а не оценивать только по размеру файла.

Шаг 3: Тестирование точности

После всех оптимизаций обязательно сравните качество модели до и после. Базовое правило из практики: accuracy не должна просесть более чем на 5%, если только вы осознанно не жертвуете точностью ради скорости или энергопотребления.

Используйте validation set и желательно отдельный набор данных, приближённый к реальной эксплуатации. Если модель работает на камере в цеху, тестировать её только на “чистом” датасете из ноутбука — плохая идея. Освещение, шум, ракурс, вибрации, дрожание питания, артефакты сенсора — всё это влияет на финальное качество сильнее, чем кажется на этапе обучения.

Для запуска моделей ИИ на микроконтроллерах удобен STM32Cube.AI: загружаете ONNX-модель, после чего инструмент генерирует C-код и оценку по памяти. Это хороший способ быстро понять, помещается ли сеть в конкретный MCU и какие ограничения появятся по SRAM/Flash ещё до ручной интеграции.

Фреймворки для Edge AI: что выбрать

  • TensorFlow Lite: универсальный вариант для ARM/Linux. Хорошо встраивается в Python и C++.
  • ONNX Runtime: кросс-платформенный рантайм с широкой поддержкой устройств.
  • TensorRT (NVIDIA): один из лучших вариантов для GPU на платформах NVIDIA, часто даёт ускорение до 5x.
  • TinyML (uTensor): для микроконтроллеров и систем без полноценной ОС.

Выбор здесь зависит не только от платформы, но и от того, насколько вам важны удобство разработки, переносимость и возможность тонкой оптимизации.

В проекте на Raspberry Pi я чаще беру TFLite: порог входа низкий, интеграция простая, а для типовых моделей этого более чем достаточно. Действительно можно уложиться в десяток строк кода и получить инференс на уровне 30 FPS для нетяжёлых сетей. Если же речь про Jetson и интенсивное компьютерное зрение, то TensorRT обычно оправдывает себя почти сразу — там выигрыш по latency и throughput особенно заметен.

ONNX Runtime хорош там, где нужен более универсальный пайплайн и есть шанс миграции между платформами. А для микроконтроллеров, где нет Linux, нормальной файловой системы и динамического распределения памяти в привычном виде, уже нужен класс TinyML-решений.

Совет из практики простой: берите не “самый модный” фреймворк, а тот, который даёт предсказуемый путь от обученной модели до стабильного инференса на вашем железе. В embedded-разработке экзотические стеки быстро превращаются в проблему сопровождения.

Практический гайд: запуск на Raspberry Pi

Для быстрого старта на Raspberry Pi установите рантайм:

sudo apt install python3-tflite-runtime

Дальше можно запустить простой инференс, например MobileNet на изображении:

import tflite_runtime.interpreter as tflite
import numpy as np
from PIL import Image

interpreter = tflite.Interpreter(model_path="mobilenet.tflite")
interpreter.allocate_tensors()

input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

img = Image.open("test.jpg").resize((224, 224))
input_data = np.expand_dims(np.array(img, dtype=np.uint8), axis=0)

interpreter.set_tensor(input_details[0]["index"], input_data)
interpreter.invoke()

output = interpreter.get_tensor(output_details[0]["index"])
print(output)

Запуск:

python infer.py

Оценить производительность можно так:

time python infer.py

Практическая цель для лёгких моделей — выйти на >20 FPS, если речь про поток с камеры. Для одиночных классификаций это не так критично, а вот в задачах компьютерного зрения уже имеет значение.

Если подключить камеру через picamera2, модель сможет анализировать видеопоток в реальном времени. Но здесь важно помнить о нескольких вещах, которые обычно становятся заметны только после первых тестов:

  • предобработка кадра иногда съедает не меньше времени, чем сам инференс;
  • конвертация форматов изображения и ресайз могут стать узким местом;
  • если писать всё в один цикл без буферизации, легко получить дроп кадров;
  • карта памяти и файловая система на Pi тоже влияют на стабильность, если вы параллельно логируете результаты.

В одном из похожих сценариев у меня самый большой прирост скорости дал не переход на “более умную” модель, а банальная оптимизация пайплайна: уменьшение лишних копирований массива, фиксированный размер входа и отказ от избыточной постобработки в Python. Для edge-систем это типичная история: модель — только часть общей задержки.

Запуск моделей на микроконтроллерах: TinyML в деле

На ESP32 или STM32 привычные desktop-подходы уже не работают. Здесь обычно используют TensorFlow Lite Micro или аналогичные инструменты для TinyML. Главная идея — уместить модель, буферы и код в очень ограниченный объём памяти, сохранив предсказуемое время выполнения.

Базовые шаги выглядят так:

  1. Сконвертируйте модель в .tflite, желательно сразу в int8.
  2. Сгенерируйте C-представление модели: xxd -i model.tflite > model_data.cc.
  3. Вызовите инференс в loop() или в цикле задачи RTOS.

Пример:

#include "model_data.h"

void loop() {
  // Подготовка входных данных
  // Запуск инференса
  // Чтение результата
}

Проверять работу удобно через Serial: выводите сырые значения входа, результаты инференса и тайминги. На раннем этапе это часто полезнее любой красивой визуализации. По энергопотреблению для таких сценариев можно ориентироваться на <1 мА на инференс, если модель действительно компактная и запускается не непрерывно, а по событию или таймеру.

Из практики TinyML-проектов: основные проблемы начинаются не на этапе “модель запустилась”, а когда нужно встроить её в реальный цикл устройства. Появляются конкурирующие задачи — опрос датчиков, связь по BLE/Wi-Fi, watchdog, работа с прерываниями, запись телеметрии. И внезапно оказывается, что инференс в чистом виде занимает приемлемое время, но вся система в целом уже не укладывается в требования по отклику. Поэтому на MCU важно проектировать не только модель, но и расписание всей прошивки.

Оптимизация под ограничения: память, энергия, скорость

На edge-устройствах модель почти всегда приходится подгонять под три ограничения одновременно: память, энергопотребление и скорость. Игнорировать хотя бы одно из них — значит получить красивый демо-стенд, который не доживёт до реальной эксплуатации.

  • Память: используйте арены и минимизируйте аллокации. Для некоторых сценариев помогает interpreter.set_num_threads(1), если лишняя многопоточность только увеличивает накладные расходы.
  • Энергия: запускайте инференс по таймеру или по событию, а между вызовами переводите систему в sleep.
  • Скорость: держите batch=1, используйте фиксированные размеры входов и избегайте лишней динамики в пайплайне.

Как ориентир, хорошая практическая цель — добиться порядка 95% accuracy при 10 мс/инференс, если задача это допускает. Разумеется, целевые метрики зависят от домена: для аудио, CV и сенсорики они будут разными, но принцип один и тот же — считать надо не абстрактную точность, а итоговую полезность модели в рамках ограничений платформы.

Полезные инструменты:

  • TensorBoard — для анализа модели и профилинга;
  • perf на Linux — для измерения узких мест по CPU и вызовам;
  • простые собственные таймеры вокруг этапов предобработки, инференса и постобработки.

Последний пункт особенно важен. В реальной оптимизации лучше всего работает не интуиция, а точные замеры. Я не раз видел ситуации, когда команда пыталась ускорить модель, хотя основная задержка была в декодировании изображения, ожидании данных с камеры или сериализации результата для API. Без раздельного профилирования это почти невозможно заметить.

Интеграция с датчиками и API

В реальном проекте модель почти никогда не живёт отдельно. Обычно она работает в связке с датчиками, исполнительными устройствами, обменом по сети и прикладной логикой. Простой пример: камера плюс акселерометр, где видеоанализ дополняется данными о движении или вибрациях.

  • GPIO: управление реле, светодиодами, внешними сигналами состояния.
  • MQTT: отправка событий и алертов в инфраструктуру мониторинга.
  • ROS2: удобный вариант для роботов и распределённых систем.

Типовой сценарий выглядит так: в основном цикле или задаче вы читаете данные по I2C/SPI/UART, подготавливаете входы, подаёте их в модель, затем по результату выполняете действие — включаете реле, поднимаете тревогу, отправляете сообщение в MQTT или публикуете топик в ROS2.

Здесь особенно важны два инженерных момента. Во-первых, синхронизация данных. Если у вас несколько источников, например камера и инерциальный датчик, надо понимать, относятся ли эти данные к одному и тому же моменту времени. Во-вторых, устойчивость интерфейсов. Любой API, брокер сообщений или драйвер датчика рано или поздно даст сбой, и модель не должна из-за этого “вешать” всё приложение.

В production-системах я бы закладывал очереди сообщений, таймауты, ретраи и раздельное логирование для inference-пайплайна и периферии. Иначе отладка быстро превращается в гадание: проблема в модели, в драйвере камеры, в MQTT-брокере или в банальном переполнении буфера.

Типичные ошибки и как их фиксить

  • Out of memory: применяйте более жёсткую квантизацию, уменьшайте размер модели и пересматривайте промежуточные буферы.
  • Низкая точность: recalibrate датасет под реальные edge-условия, а не только под тренировочный набор.
  • Перегрев: снижайте частоту или режим работы CPU, например через cpufreq-set -g powersave.
  • Нет ускорения: проверьте, включены ли NEON/VFP и действительно ли сборка использует аппаратные возможности платформы.

Добавлю несколько практических замечаний. Ошибка Out of memory на embedded-устройстве не всегда означает, что модель “слишком большая” в лобовом смысле. Иногда проблема в предобработке, двойном буферизовании кадров, лишних копиях массивов или неудачном размещении памяти между heap и stack. На микроконтроллерах это особенно критично: один неудачный статический буфер — и система начинает падать нестабильно.

С низкой точностью очень часто помогает не переобучение “с нуля”, а адаптация пайплайна под реальные данные. Например, если камера на устройстве даёт другой баланс белого, шум или геометрию кадра, чем в обучающем датасете, модель может деградировать сильнее, чем ожидалось. В таких случаях полезно собирать небольшой, но честный датасет прямо с целевого устройства.

Перегрев и троттлинг — классическая проблема для одноплатников без нормального охлаждения. Если система должна работать непрерывно, тестировать её надо не 5 минут, а сутками. Именно поэтому правило “тестируйте на реальных данных 24/7” остаётся абсолютно актуальным. Только так становятся видны утечки памяти, деградация карты памяти, сбои по питанию, зависания драйверов и накопление ошибок в логике приложения.

Кейсы из практики

  • Дрон: YOLO-tiny на Jetson — локальное обнаружение препятствий.
  • IoT-датчик: классификатор вибраций на ESP32.
  • Камера безопасности: PoseNet на Pi Zero.

Это хорошие примеры того, как разные классы устройств решают разные задачи. На Jetson можно позволить себе более тяжёлое компьютерное зрение, если нужен детект объектов в динамике. На ESP32 уместнее компактный классификатор сенсорных данных, который работает по событиям и потребляет минимум энергии. Pi Zero — компромиссный вариант для лёгкого зрения там, где критична стоимость и не нужны большие вычислительные резервы.

В сумме такие решения нередко дают очень ощутимый эффект: автономия +90%, стоимость -70%. И это не удивительно. Когда устройство само принимает локальные решения, уменьшаются требования к каналу связи, инфраструктуре и серверной части, а архитектура системы становится проще в эксплуатации.

Но важный нюанс: такие результаты достигаются не “просто потому, что модель работает на устройстве”, а потому что правильно подобраны платформа, формат модели и логика обработки событий. Именно инженерная увязка всех компонентов и даёт итоговый выигрыш.

Заключение: ваш первый Edge AI проект

Если вы только входите в тему, самый разумный старт — взять Raspberry Pi, TensorFlow Lite и простой датасет вроде CIFAR-10. Это позволяет быстро пройти весь цикл: обучение, конвертация, запуск, профилирование, интеграция с реальным устройством. При аккуратной работе уже через неделю можно получить первую рабочую модель и понять, где на практике возникают основные ограничения.

Следующий шаг — перенос подхода на микроконтроллер или специализированную edge-платформу. И вот там уже становятся по-настоящему важны базовые инженерные навыки: понимание памяти, устройства пайплайна, работы с API, Git, отладки, сборки и поведения системы под нагрузкой. Именно это и составляет фундамент для реальных задач в edge AI.

Перелинковка: Python для ML, Embedded C++, Компьютерное зрение.

FAQ

Что такое запуск моделей ИИ на устройствах?

Это локальный инференс моделей искусственного интеллекта без обращения к облаку. Такой подход нужен прежде всего для скорости, оффлайн-работы и предсказуемой задержки.

Подходит ли Raspberry Pi для Edge AI?

Да. Raspberry Pi 4/5 вполне подходит для Edge AI и после оптимизации способен тянуть MobileNet на уровне около 30 FPS, особенно если аккуратно настроены предобработка и рантайм.

Как оптимизировать модель для микроконтроллера?

Базовый путь — квантизация в int8 плюс TensorFlow Lite Micro. Для практического использования размер модели обычно стараются держать <100 КБ, чтобы уложиться в ограничения MCU по памяти.

Сколько памяти нужно для Edge AI?

Диапазон зависит от платформы: от 512 КБ на MCU для очень компактных моделей до 2 ГБ и выше на SBC, если речь идёт о более тяжёлых сценариях.

Можно ли запустить GPT на edge?

Да, но с оговорками. Небольшие версии, например уровня DistilGPT, можно запускать на Jetson с 8 ГБ памяти. Для микроконтроллеров и слабых SBC такие модели, как правило, уже непрактичны без очень агрессивной оптимизации.