7.16. Підсумок

У цьому розділі розглянуто частини модуля ml, до яких звертається застосунок OpenMV, коли крок інференсу є частиною конвеєра:

  • Концепції – що таке нейронна мережа в арифметичних термінах (стек навчуваних операторів, що відображує тензор у тензор), що змінило машинне навчання порівняно з класичною обробкою зображень (написаний вручну алгоритм узагальнення зник, замінений вагами, отриманими з позначених даних), та демонстраційний приклад, який запустив детектор облич у кілька рядків Python.

  • Модуль ml – об’єкт ml.Model та його властивості для перевірки вхідних і вихідних тензорів, шляхи до файлів моделей, які він приймає, та місця їх зберігання: розділ ROMFS, доступний лише для читання, для виконання безпосередньо з флеш-пам’яті, або будь-яка інша файлова система MicroPython, коли модель може бути скопійована до RAM під час завантаження.

  • Конвеєр інференсу – три етапи, які predict() виконує послідовно (попередня обробка, виклик двигуна, постобробка), дескриптор Normalization на першому етапі, дескриптор постпроцесора на третьому етапі, та арифметика квантування, яка пов’язує цілочисельні тензори, що виконуються на камері, з дійсними числами, на яких навчалася мережа.

  • Двигуни інференсу – TFLM (інтерпретатор операторів, який використовують більшість камер), CMSIS-NN (бібліотека SIMD-ядер під ним для Cortex-M) та NPU (Arm Ethos-U55 на AE3 у парі з офлайн-компілятором Vela, ST Neural-ART на N6 у парі з STAI та STEdgeAI). Двигун визначається камерою; скрипт його не обирає.

  • Декодування виводу – постпроцесори, що перетворюють вихідні тензори на обмежувальні прямокутники, ключові точки або списки по класах; клас NMS, що згортає перекриваючі кандидати; покрокова демонстрація YOLOv8, яка показує, як прискорити декодування, застосовуючи поріг перед деквантуванням; а також протокол написання власного декодера, коли каталог не охоплює певну модель.

7.16.1. Що стало доступним

Три речі, до яких готує цей розділ:

  • Завантаження навченої моделі та її запуск. Усе, що знаходиться в /rom/, працює без додаткової підготовки; усе, що надається зовні як сумісний файл .tflite, працює після того, як офлайн-інструмент для цільової камери (Vela для AE3, STEdgeAI для N6) сформує правильний макет.

  • Декодування будь-якого вихідного тензора. Якщо архітектура є в каталозі, вибір правильного постпроцесора є механічним: YoloV8 для моделі YOLOv8, BlazeFace для BlazeFace тощо. Якщо ні, протокол writing-your-own описує контракт, а покрокова демонстрація YOLOv8 є найчистішим прикладом для копіювання.

  • Оцінка продуктивності. Модель, що виконується зі швидкістю 30 FPS на NPU, може виконуватися зі швидкістю 3 FPS на Cortex-M7; співвідношення залежить від того, яку частину мережі камера може перенести з CPU. Квантування, розміщення в ROMFS, компіляція для NPU та підтримка операторів цільового двигуна – чотири важелі впливу, і кожен з них розглянуто в розділі.

7.16.2. Навчання власної моделі

Цей розділ відправною точкою взяв уже навчений файл .tflite. Створення такого файлу для власного завдання – нового набору класів об’єктів або спеціалізованого класифікатора – не означає необхідності вручну будувати конвеєр навчання: два хмарні сервіси охоплюють весь цикл: від збору та розмітки даних через навчання до експорту моделі, яку камера може завантажити.

  • Edge Impulse – наскрізна платформа embedded-ML; збирайте дані з камери, розмічайте їх, навчайте модель і експортуйте квантований файл .tflite, готовий до роботи з механізмом висновків OpenMV.

  • Roboflow – управління наборами даних і розмітка з хмарним навчанням, орієнтоване на виявлення об’єктів; експортуйте модель YOLOv8, яку постпроцесор YoloV8 декодує безпосередньо.

7.16.3. Інтеграція ML з іншими можливостями камери

Логовиводення рідко виконується ізольовано. Модуль зображень захоплює та попередньо обробляє кадр, модуль ml запускає мережу, а ulab.numpy виконує числові обчислення, для яких жодна зі сторін не має вбудованих засобів. Типовий скрипт виявлення поєднує всі три: захоплення за допомогою csi, необов’язкове налаштування кадру через image, виклик predict(), постобробка результату відповідним модулем із ml.postprocessing та використання ulab.numpy для будь-яких додаткових математичних обчислень над боксами, повернутими постпроцесором. Три модулі використовують спільну модель пам’яті; межі між ними є безкопіювальними де можливо.