ГлавнаяАкадемияCOURSE-16: Основы Интернета Вещей и практическое применение → Машинное обучение на Edge: от теории к практике на контроллере HI

Машинное обучение на Edge: от теории к практике на контроллере HI

Урок 6 · COURSE-16: Основы Интернета Вещей и практическое применение · theory

COURSE-16-M03-L07 — Машинное обучение на Edge: от теории к практике на контроллере HI

Введение: Что такое Edge ML и зачем это инженеру?

Машинное обучение (Machine Learning, ML) — это технология, позволяющая системам не просто следовать жестко заданным инструкциям, а обучаться на основе данных и делать выводы. Когда мы говорим о "ML на Edge" (или Edge AI), мы имеем в виду выполнение алгоритмов машинного обучения непосредственно на конечном устройстве — в нашем случае, на контроллере HI.

В отличие от облачных ML-сервисов, где данные отправляются на удаленный сервер для анализа, Edge ML предлагает ключевые преимущества для объектов автоматизации:

Контроллер HI, оснащенный 4-ядерным процессором и 4 ГБ оперативной памяти, является идеальной платформой для реализации сценариев Edge ML.

Практические задачи ML на объекте автоматизации

Давайте рассмотрим, какие реальные задачи инженера по автоматизации можно решить с помощью машинного обучения на контроллере HI.

  • Предсказание (Prediction): Прогнозирование будущих значений на основе исторических данных.
  • * Пример: Прогнозирование энергопотребления офисного здания на следующий час на основе данных за прошлые сутки и текущей уличной температуры. Это позволяет заранее оптимизировать работу систем отопления и кондиционирования.

    * Источники данных: Данные с Modbus-счетчика электроэнергии, показания датчика уличной температуры (1-Wire или MQTT).

  • Обнаружение аномалий (Anomaly Detection): Выявление нетипичных или аномальных показаний, которые могут свидетельствовать о неисправности или нештатной ситуации.
  • * Пример: Мониторинг вибрации насоса с помощью аналогового датчика. Модель ML, обученная на "нормальных" данных, мгновенно обнаружит отклонение в характере вибраций, которое предшествует поломке, и отправит уведомление о необходимости предиктивного обслуживания.

    * Источники данных: Аналоговый вход (4-20 мА) с датчика вибрации.

  • Классификация (Classification): Определение состояния системы или типа события на основе совокупности данных от разных датчиков.
  • * Пример: Классификация состояния переговорной комнаты: "Свободно", "Идет встреча", "Заканчивается встреча". Модель анализирует данные с датчиков CO₂, движения и шума. На основе этого система может автоматически управлять освещением, климатом и системой бронирования.

    * Источники данных: Универсальные входы (датчик движения), MQTT-датчики (CO₂, шум).

    Инструменты ML на контроллере HI

    Хотя мощные фреймворки, такие как TensorFlow и Keras, часто используются для создания сложных моделей на Python, для решения 90% практических задач на объекте достаточно более простых и интегрированных инструментов, доступных в Node-RED.

    Для задач прогнозирования и обнаружения аномалий существуют готовые узлы, которые позволяют обучать модели и использовать их без написания сложного кода. В рамках данного курса мы будем использовать палитру `node-red-contrib-simple-regression`. Она идеально подходит для создания моделей линейной регрессии. Для более сложных задач контроллер HI позволяет запускать Python-скрипты. Модель, обученная на большом наборе данных (например, на ПК инженера с использованием Scikit-learn), сохраняется в файл (например, `model.pkl`) и загружается на контроллер. В Node-RED с помощью узла `Exec` можно вызвать Python-скрипт, который загрузит модель и выполнит предсказание на основе данных, полученных в `msg.payload`. Этот подход выходит за рамки курса Foundation, но важно знать о такой возможности.

    Практический пример: Прогнозирование энергопотребления

    Задача: Создать поток в Node-RED, который обучается на данных о потреблении электроэнергии и предсказывает его значение на следующий час. Легенда: Flow Diagram (ASCII):
    // ================= 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: Создание потока обучения
  • Узел `Inject`: Настроен на отправку строки `"train"` в `msg.payload` при ручном нажатии.
  • Узел `Function` ("Prepare Train Data"): Эмулирует набор данных для обучения. В реальной системе эти данные будут собираться из базы данных MySQL, где они накапливались.
  •     // Контракт сообщения для обучения:

    // 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;

  • Узел `simple-regression`:
  • * Mode: `train`

    * Name: `Energy Model`

    Шаг 3: Создание потока прогнозирования
  • Узел `Inject`: Настроен на запуск каждые 15 минут.
  • Узел `Modbus-Getter`: Настроен на чтение Holding Register `99` с устройства с `Unit-ID: 15`.
  • Узел `Function` ("Prepare Predict Data"): Получает текущее время и формирует запрос для модели.
  •     // Входящее сообщение от 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;

  • Узел `simple-regression`:
  • * Mode: `predict`

    * Name: `Energy Model` (то же имя, что и у обучающего узла).

  • Узел `Function` ("Format Output"): Форматирует результат согласно "Контракту сообщения" Академии.
  •     // Входящее сообщение от узла регрессии: 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;

  • Узел `MQTT Out`: Публикует `msg` в топик `telemetry/building/main/energy/prediction`.
  • Узел `Catch`: Подключен к централизованному потоку логирования ошибок.
  • 💡 Совет: Обучение модели — ресурсоемкая операция. Запускайте ее либо вручную после обновления данных, либо автоматически, но редко (например, раз в сутки ночью).

    Типовые ошибки и диагностика

    ⚠️ Проблема: Модель предсказывает неточные или бессмысленные значения.

    ⚠️ Проблема: Узел `simple-regression` в режиме `predict` выдает ошибку или не возвращает ничего.

    ⚠️ Проблема: Поток потребляет слишком много ресурсов CPU.

    ---

    Завершение модуля

    📋 Лабораторные работы

    COURSE-16-M03-LAB13: Создание модели прогнозирования температуры
  • Задача: Создать поток, который предсказывает температуру в комнате через 10 минут на основе текущей температуры.
  • Скелет потока: Вам предоставляется поток с узлом, эмулирующим датчик температуры (1-Wire), который каждые 5 минут выдает новое значение.
  • Задания:
  • * Создать ветку для накопления данных (последние 20 значений) в переменной контекста `flow`.

    * Создать ветку обучения, которая использует накопленные данные для тренировки модели линейной регрессии. В качестве `X` используйте временную метку, в качестве `Y` — температуру.

    * Создать ветку прогнозирования, которая по запросу предсказывает температуру на 10 минут вперед.

    * Обеспечить визуальный статус для всех ключевых узлов.

    * Оформить исходящее сообщение с прогнозом в соответствии с контрактом Академии.

  • Рубрика оценивания:
  • * (30%) Поток корректно собирает и хранит данные для обучения.

    * (40%) Модель успешно обучается и делает прогнозы без ошибок.

    * (20%) Все сообщения соответствуют контракту, используется визуальный статус.

    * (10%) Поток содержит комментарии и имеет понятную структуру.

    COURSE-16-M03-LAB14: Разработка системы обнаружения аномалий
  • Задача: Создать систему, которая обнаруживает аномально высокое потребление воды в квартире.
  • Контекст: Импульсный счетчик воды подключен к дискретному входу контроллера. Каждый импульс — 1 литр. Нормальное потребление — не более 10 импульсов в минуту. Аномалия — более 20 импульсов в минуту в течение 3 минут подряд.
  • Задания:
  • * Создать поток, который подсчитывает количество импульсов в минуту.

    * Используя узел `Function` и контекст `flow`, реализовать логику обнаружения аномалии (состояние "аномалия" должно сохраняться 3 минуты).

    * При обнаружении аномалии система должна:

    * Отправить сообщение в MQTT-топик `alarms/apartment-1/water-leak`.

    * Записать событие в лог-файл с помощью узла `file`.

    * Система должна автоматически сбрасывать тревогу, если потребление возвращается в норму.

  • Рубрика оценивания:
  • * (40%) Логика подсчета импульсов и определения аномалии реализована корректно.

    * (30%) Система корректно генерирует и сбрасывает тревоги.

    * (20%) Все события тревоги логируются в требуемом формате.

    * (10%) Поток отказоустойчив и содержит обработку ошибок.

    📋 Тест по модулю (COURSE-16-M03-QUIZ)

  • Что такое "Edge ML"?
  • * a) Обучение моделей в облаке Microsoft Azure.

    * b) Выполнение ML-алгоритмов непосредственно на конечном устройстве (контроллере).

    * c) Использование машинного обучения для заточки ножей.

    * d) Обучение моделей на данных с пограничного контроля.

  • Какое ключевое преимущество дает Edge ML в системах автоматизации?
  • * a) Возможность смотреть видео в высоком качестве.

    * b) Снижение стоимости контроллера.

    * c) Автономная работа системы при отсутствии интернета.

    * d) Увеличение дальности работы Wi-Fi.

  • Какую задачу решает модель, прогнозирующая отказ оборудования на основе данных о вибрации?
  • * a) Классификация.

    * b) Регрессия.

    * c) Обнаружение аномалий.

    * d) Кластеризация.

  • В практическом примере урока, что используется в качестве "входа" (X) для обучения модели прогнозирования энергопотребления?
  • * a) Текущее потребление.

    * b) Час дня.

    * c) День недели.

    * d) Температура на улице.

  • Какой узел Node-RED используется для перехвата ошибок в потоке?
  • * a) `Inject`

    * b) `Debug`

    * c) `Catch`

    * d) `Switch`

  • Что необходимо сделать, чтобы узел `simple-regression` в режиме `predict` начал работать?
  • * a) Перезагрузить контроллер.

    * b) Предварительно обучить модель с тем же именем с помощью узла в режиме `train`.

    * c) Обновить Node-RED до последней версии.

    * d) Подключить его к базе данных MySQL.

  • Почему важно использовать "Контракт сообщения" при работе с ML-моделями?
  • * a) Чтобы модель получала данные в строго определенном и ожидаемом формате.

    * b) Это требование законодательства.

    * c) Чтобы увеличить скорость работы MQTT-брокера.

    * d) Это просто красивая традиция.

  • Что является наиболее вероятной причиной, если ваша модель постоянно выдает неточные прогнозы?
  • * a) Неправильный цвет узлов в потоке.

    * b) Недостаточное или нерелевантное количество данных для обучения.

    * c) Слишком длинное имя у модели.

    * d) Использование Wi-Fi вместо Ethernet.

  • Для чего в потоке прогнозирования используется узел `Status`?
  • * a) Для отправки SMS-сообщений.

    * b) Для визуального отображения текущего состояния и результата прогноза прямо в редакторе Node-RED.

    * c) Для измерения температуры процессора контроллера.

    * d) Для записи данных на EEPROM.

  • Какая операция является более ресурсоемкой для контроллера?
  • * a) Прогнозирование (`predict`).

    * b) Обучение (`train`).

    * c) Обе операции одинаковы по нагрузке.

    * d) Отправка сообщения в `Debug`.

    📋 Мини-runbook "Если не работает"

    * Диагностика: Наведите курсор на красный треугольник под узлом, чтобы увидеть текст ошибки.

    * Действие 1: Проверьте, что на вход узла приходят данные в правильном формате (для `train` — массив массивов, для `predict` — число). Подключите узел `Debug` к выходу предыдущего узла и проверьте `msg.payload`.

    * Действие 2: Если это узел `predict`, убедитесь, что модель с таким именем была успешно обучена. Запустите ветку `train`.

    * Диагностика: Проверьте данные, на которых обучалась модель. Возможно, они не содержат достаточной вариативности.

    * Действие: Соберите больше данных за более длительный период и переобучите модель. Убедитесь, что на вход узла `predict` приходят разные значения `X`.

    * Диагностика: Проверьте настройки узла `Inject`.

    * Действие: Убедитесь, что галочка "Inject once after [X] seconds, then" установлена, и выбран правильный интервал. Нажмите кнопку `Deploy` после внесения изменений.