Машинное обучение на Edge: от теории к практике на контроллере HI
COURSE-16-M03-L07 — Машинное обучение на Edge: от теории к практике на контроллере HI
Введение: Что такое Edge ML и зачем это инженеру?
Машинное обучение (Machine Learning, ML) — это технология, позволяющая системам не просто следовать жестко заданным инструкциям, а обучаться на основе данных и делать выводы. Когда мы говорим о "ML на Edge" (или Edge AI), мы имеем в виду выполнение алгоритмов машинного обучения непосредственно на конечном устройстве — в нашем случае, на контроллере HI.
В отличие от облачных ML-сервисов, где данные отправляются на удаленный сервер для анализа, Edge ML предлагает ключевые преимущества для объектов автоматизации:
- Автономность и надежность: Система продолжает работать, делать прогнозы и обнаруживать аномалии даже при полном отсутствии интернет-соединения. Это критично для систем безопасности, управления климатом и производственных процессов.
- Низкая задержка (Low Latency): Решения принимаются мгновенно, без задержек на отправку данных в облако и обратно. Это позволяет реализовать реактивные сценарии, например, экстренное отключение оборудования при обнаружении аномальной вибрации.
- Безопасность и конфиденциальность: Чувствительные данные (например, информация о присутствии людей, показатели технологических процессов) не покидают пределы объекта, что снижает риски утечек и соответствует требованиям к защите данных.
- Экономия трафика и облачных ресурсов: Обработка данных на месте значительно сокращает объемы информации, передаваемой в облако, что снижает затраты на интернет-канал и облачные вычисления.
Контроллер HI, оснащенный 4-ядерным процессором и 4 ГБ оперативной памяти, является идеальной платформой для реализации сценариев Edge ML.
Практические задачи ML на объекте автоматизации
Давайте рассмотрим, какие реальные задачи инженера по автоматизации можно решить с помощью машинного обучения на контроллере HI.
* Пример: Прогнозирование энергопотребления офисного здания на следующий час на основе данных за прошлые сутки и текущей уличной температуры. Это позволяет заранее оптимизировать работу систем отопления и кондиционирования.
* Источники данных: Данные с Modbus-счетчика электроэнергии, показания датчика уличной температуры (1-Wire или MQTT).
* Пример: Мониторинг вибрации насоса с помощью аналогового датчика. Модель ML, обученная на "нормальных" данных, мгновенно обнаружит отклонение в характере вибраций, которое предшествует поломке, и отправит уведомление о необходимости предиктивного обслуживания.
* Источники данных: Аналоговый вход (4-20 мА) с датчика вибрации.
* Пример: Классификация состояния переговорной комнаты: "Свободно", "Идет встреча", "Заканчивается встреча". Модель анализирует данные с датчиков CO₂, движения и шума. На основе этого система может автоматически управлять освещением, климатом и системой бронирования.
* Источники данных: Универсальные входы (датчик движения), MQTT-датчики (CO₂, шум).
Инструменты ML на контроллере HI
Хотя мощные фреймворки, такие как TensorFlow и Keras, часто используются для создания сложных моделей на Python, для решения 90% практических задач на объекте достаточно более простых и интегрированных инструментов, доступных в Node-RED.
- Основной подход: Специализированные узлы Node-RED
- Продвинутый подход: Интеграция с Python
Практический пример: Прогнозирование энергопотребления
Задача: Создать поток в Node-RED, который обучается на данных о потреблении электроэнергии и предсказывает его значение на следующий час. Легенда:- Источник данных: Modbus-счетчик электроэнергии (Slave ID=15), который отдает текущее потребление (в кВт) в Holding Register `40100` (адрес 99).
- Цель: Каждые 15 минут предсказывать потребление на час вперед.
// ================= FLOW-ML-ENERGY-PREDICT-001 =================
// ------------ Ветка обучения модели (запускается вручную) ------------
[Inject: "train"] --> [Function: Prepare Train Data] --> [simple-regression: train] --> [Debug: "Model Trained"]
// ------------ Ветка прогнозирования (запускается каждые 15 мин) ------------
[Inject: 15 min] --> [Modbus-Getter] --> [Function: Prepare Predict Data] --> [simple-regression: predict] --> [Function: Format Output] --> [MQTT Out]
|
+--> [Status Node]
// --------------------- Ветка обработки ошибок ----------------------
[Catch: All Nodes] --> [Function: Format Error] --> [Log to MySQL]
Пошаговая реализация:
Шаг 1: Установка палитры
В интерфейсе Node-RED перейдите в `Menu -> Manage palette -> Install` и установите `node-red-contrib-simple-regression`.
Шаг 2: Создание потока обучения
// Контракт сообщения для обучения:
// msg.payload должен быть массивом массивов [[x1, y1], [x2, y2], ...]
// Где x - час дня (0-23), y - потребление (кВт)
const trainingData = [
[0, 2.5], [1, 2.1], [2, 2.0], [3, 2.2], [4, 2.8], [5, 3.5],
[6, 5.0], [7, 7.5], [8, 9.0], [9, 11.5], [10, 12.0], [11, 12.2],
[12, 11.8], [13, 11.5], [14, 11.9], [15, 12.5], [16, 13.0], [17, 11.0],
[18, 9.5], [19, 8.0], [20, 7.2], [21, 6.0], [22, 4.5], [23, 3.1]
];
msg.payload = trainingData;
node.status({fill:"blue", shape:"dot", text:"Sending training data"});
return msg;
* Mode: `train`
* Name: `Energy Model`
Шаг 3: Создание потока прогнозирования
// Входящее сообщение от Modbus: msg.payload.data = [125] (означает 12.5 кВт)
// Нам для прогноза нужен час, на который мы делаем прогноз.
const now = new Date();
// Прогнозируем на следующий час
const nextHour = (now.getHours() + 1) % 24;
// Контракт сообщения для предсказания:
// msg.payload должен быть числом (значение X)
msg.payload = nextHour;
// Сохраняем контекст для следующего узла
flow.set("prediction_hour", nextHour);
return msg;
* Mode: `predict`
* Name: `Energy Model` (то же имя, что и у обучающего узла).
// Входящее сообщение от узла регрессии: msg.payload - это предсказанное число
const predictionValue = parseFloat(msg.payload.toFixed(2));
const predictionHour = flow.get("prediction_hour");
// 1. Валидация
if (isNaN(predictionValue)) {
node.status({fill:"red", shape:"dot", text:"Prediction failed"});
node.error("Prediction returned NaN", msg);
return null;
}
// 2. Формирование по контракту
msg.payload = {
value: predictionValue,
unit: "kW",
source: "FLOW-ML-ENERGY-PREDICT-001",
ts: Date.now(),
meta: {
prediction_for_hour: predictionHour
}
};
// 3. Установка топика для маршрутизации
msg.topic = "telemetry/building/main/energy/prediction";
// 4. Визуальный статус
node.status({fill:"green", shape:"dot", text:`Pred for ${predictionHour}:00 -> ${predictionValue} kW`});
return msg;
💡 Совет: Обучение модели — ресурсоемкая операция. Запускайте ее либо вручную после обновления данных, либо автоматически, но редко (например, раз в сутки ночью).
Типовые ошибки и диагностика
⚠️ Проблема: Модель предсказывает неточные или бессмысленные значения.
- Причина 1: Недостаточно данных для обучения. Модели нужно "увидеть" разные ситуации, чтобы делать точные прогнозы.
- Решение: Накопите данные за несколько дней или недель в базе MySQL на контроллере и используйте их для обучения.
- Причина 2: Выбранная модель слишком проста. Линейная регрессия хорошо работает для простых зависимостей. Для сложных паттернов (например, учет дня недели и праздников) могут потребоваться более сложные модели.
- Решение: Рассмотрите возможность использования узлов для полиномиальной регрессии или продвинутый подход с Python.
⚠️ Проблема: Узел `simple-regression` в режиме `predict` выдает ошибку или не возвращает ничего.
- Причина: Модель с таким именем еще не была обучена. Узлы `train` и `predict` связываются по имени модели.
- Решение: Убедитесь, что вы хотя бы один раз запустили ветку обучения. Проверьте, что поле `Name` в обоих узлах совпадает.
⚠️ Проблема: Поток потребляет слишком много ресурсов CPU.
- Причина: Слишком частый запуск ветки обучения (`train`).
- Решение: Обучайте модель только при необходимости, а не при каждом прогнозе. Прогнозирование (`predict`) — очень быстрая операция.
---
Завершение модуля
📋 Лабораторные работы
COURSE-16-M03-LAB13: Создание модели прогнозирования температуры* Создать ветку для накопления данных (последние 20 значений) в переменной контекста `flow`.
* Создать ветку обучения, которая использует накопленные данные для тренировки модели линейной регрессии. В качестве `X` используйте временную метку, в качестве `Y` — температуру.
* Создать ветку прогнозирования, которая по запросу предсказывает температуру на 10 минут вперед.
* Обеспечить визуальный статус для всех ключевых узлов.
* Оформить исходящее сообщение с прогнозом в соответствии с контрактом Академии.
* (30%) Поток корректно собирает и хранит данные для обучения.
* (40%) Модель успешно обучается и делает прогнозы без ошибок.
* (20%) Все сообщения соответствуют контракту, используется визуальный статус.
* (10%) Поток содержит комментарии и имеет понятную структуру.
COURSE-16-M03-LAB14: Разработка системы обнаружения аномалий* Создать поток, который подсчитывает количество импульсов в минуту.
* Используя узел `Function` и контекст `flow`, реализовать логику обнаружения аномалии (состояние "аномалия" должно сохраняться 3 минуты).
* При обнаружении аномалии система должна:
* Отправить сообщение в MQTT-топик `alarms/apartment-1/water-leak`.
* Записать событие в лог-файл с помощью узла `file`.
* Система должна автоматически сбрасывать тревогу, если потребление возвращается в норму.
* (40%) Логика подсчета импульсов и определения аномалии реализована корректно.
* (30%) Система корректно генерирует и сбрасывает тревоги.
* (20%) Все события тревоги логируются в требуемом формате.
* (10%) Поток отказоустойчив и содержит обработку ошибок.
📋 Тест по модулю (COURSE-16-M03-QUIZ)
* a) Обучение моделей в облаке Microsoft Azure.
* b) Выполнение ML-алгоритмов непосредственно на конечном устройстве (контроллере).
* c) Использование машинного обучения для заточки ножей.
* d) Обучение моделей на данных с пограничного контроля.
* a) Возможность смотреть видео в высоком качестве.
* b) Снижение стоимости контроллера.
* c) Автономная работа системы при отсутствии интернета.
* d) Увеличение дальности работы Wi-Fi.
* a) Классификация.
* b) Регрессия.
* c) Обнаружение аномалий.
* d) Кластеризация.
* a) Текущее потребление.
* b) Час дня.
* c) День недели.
* d) Температура на улице.
* a) `Inject`
* b) `Debug`
* c) `Catch`
* d) `Switch`
* a) Перезагрузить контроллер.
* b) Предварительно обучить модель с тем же именем с помощью узла в режиме `train`.
* c) Обновить Node-RED до последней версии.
* d) Подключить его к базе данных MySQL.
* a) Чтобы модель получала данные в строго определенном и ожидаемом формате.
* b) Это требование законодательства.
* c) Чтобы увеличить скорость работы MQTT-брокера.
* d) Это просто красивая традиция.
* a) Неправильный цвет узлов в потоке.
* b) Недостаточное или нерелевантное количество данных для обучения.
* c) Слишком длинное имя у модели.
* d) Использование Wi-Fi вместо Ethernet.
* a) Для отправки SMS-сообщений.
* b) Для визуального отображения текущего состояния и результата прогноза прямо в редакторе Node-RED.
* c) Для измерения температуры процессора контроллера.
* d) Для записи данных на EEPROM.
* a) Прогнозирование (`predict`).
* b) Обучение (`train`).
* c) Обе операции одинаковы по нагрузке.
* d) Отправка сообщения в `Debug`.
📋 Мини-runbook "Если не работает"
- Проблема: Узел ML (например, `simple-regression`) находится в состоянии ошибки.
* Действие 1: Проверьте, что на вход узла приходят данные в правильном формате (для `train` — массив массивов, для `predict` — число). Подключите узел `Debug` к выходу предыдущего узла и проверьте `msg.payload`.
* Действие 2: Если это узел `predict`, убедитесь, что модель с таким именем была успешно обучена. Запустите ветку `train`.
- Проблема: Прогноз всегда один и тот же или не меняется.
* Действие: Соберите больше данных за более длительный период и переобучите модель. Убедитесь, что на вход узла `predict` приходят разные значения `X`.
- Проблема: Поток не запускается по расписанию.
* Действие: Убедитесь, что галочка "Inject once after [X] seconds, then" установлена, и выбран правильный интервал. Нажмите кнопку `Deploy` после внесения изменений.