Обнаружение кашля с TinyML на Arduino Nano 33 BLE Sense для ранней диагностики гриппа
Компоненты и материалы
| Arduino Nano 33 BLE Sense | 1 |
Приложения и онлайн-сервисы
- Edge Impulse Studio (платформа ML для эдж-устройств)
О проекте
Существует огромная потребность в дешевых, легко развертываемых решениях для раннего обнаружения COVID-19 и гриппа. Вместе с ООН, Hackster, Edge Impulse и другими запущен UN Covid Detect & Protect Challenge для создания доступных инструментов профилактики и детектирования в развивающихся странах. В этом туториале показано, как использовать Edge Impulse (TinyML) на Arduino Nano BLE Sense для обнаружения кашля в реальном времени по аудиосигналу.
Мы собрали датасет из 10 минут аудиозаписей двух классов — «cough» (кашель) и «noise» (фоновый шум), обучили высокооптимизированную TinyML-модель, которая работает в реальном времени менее чем в 20 КБ ОЗУ на Nano BLE Sense. Подход применим ко многим задачам аудио-паттерн-матчинга: уход за пожилыми, безопасность, мониторинг оборудования. Проект и датасет начал Картик Тхакор для помощи в борьбе с COVID-19.
Начало работы
Требования:
- Базовые знания разработки и Arduino
- Установленный Arduino IDE или CLI
- Android или iOS смартфон
- Arduino Nano BLE Sense (или аналог на Cortex-M4+ с микрофоном) — опционально
Используем Edge Impulse — онлайн-платформу ML для эдж-устройств. Создайте бесплатный аккаунт, войдите, назовите проект (например, «Arduino Cough Tutorial»).
Сбор датасета
Первый шаг любого ML-проекта — сбор репрезентативного датасета. Мы подготовили небольшой датасет (10 мин аудио, классы «cough» и «noise»). Покажем, как импортировать его в Edge Impulse, добавить свои сэмплы или начать с нуля.
Внимание: Принудительный кашель вреден для голосовых связок — будьте осторожны при сборе данных и тестировании!
- Скачайте датасет: cough.zip и распакуйте.
- Установите Edge Impulse CLI.
- В терминале перейдите в папку с данными и выполните:
$ edge-impulse-uploader --clean $ edge-impulse-uploader --category training training/* $ edge-impulse-uploader --category testing testing/* - Введите логин/пароль Edge Impulse и выберите проект. Сэмплы появятся на странице Data acquisition. Клик по сэмплу показывает волну и позволяет прослушать.
10 минут достаточно для старта. Можно расширить датасет своими записями. Сбор данных с телефона — проще всего (полный туториал здесь). На странице Devices нажмите «+ Connect a new device» → «Use your mobile phone» → отсканируйте QR-код камерой телефона.
Теперь на странице Data acquisition в разделе «Record new data» выберите лейбл «cough» или «noise», сенсор «Microphone», нажмите «Start sampling». Телефон запишет сэмпл и добавит в датасет.
Сбор с Nano BLE Sense также поддерживается: установите файрмварь и демон Edge Impulse, затем собирайте данные так же, как с телефона.
Создание импульса (Impulse)
На странице Create impulse выберите блоки обработки и обучения. Оставьте Window size = 1000 мс, Window increase = 500 мс (аудио обрабатывается окнами по 1 сек со сдвигом 0.5 сек). Маленькое окно экономит память, но требует кашля без больших пауз.
- Add processing block → Audio (MFCC).
- Add learning block → Neural Network (Keras).
- Save Impulse.
Audio-блок извлекает спектрограмму для каждого окна, нейросеть классифицирует её как «cough» или «noise».
На странице MFCC генерация признаков: оставьте параметры по умолчанию, нажмите «Generate features» (занимает пару минут).
Обучение нейросети
На странице NN Classifier настроим сеть. Для кашля нужна более сложная архитектура с 2D-конволюцией по спектрограмме (как в классификации изображений). Нажмите «Switch to Keras (expert) mode» в правом верхнем углу «Neural Network settings».
Замените архитектуру на:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, InputLayer, Dropout, Flatten, Reshape, BatchNormalization, Conv2D, MaxPooling2D, AveragePooling2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.constraints import MaxNorm
model = Sequential()
model.add(InputLayer(input_shape=(X_train.shape[1], ), name='x_input'))
model.add(Reshape((int(X_train.shape[1] / 13), 13, 1), input_shape=(X_train.shape[1], )))
model.add(Conv2D(10, kernel_size=5, activation='relu', padding='same', kernel_constraint=MaxNorm(3)))
model.add(AveragePooling2D(pool_size=2, padding='same'))
model.add(Conv2D(5, kernel_size=5, activation='relu', padding='same', kernel_constraint=MaxNorm(3)))
model.add(AveragePooling2D(pool_size=2, padding='same'))
model.add(Flatten())
model.add(Dense(classes, activation='softmax', name='y_pred', kernel_constraint=MaxNorm(3)))
opt = Adam(lr=0.005, beta_1=0.9, beta_2=0.999)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size=32, epochs=9, validation_data=(X_test, Y_test), verbose=2)
Установите Minimum confidence rating = 0.70. Нажмите «Start training» (несколько секунд).
Алгоритм обнаружения кашля готов к тесту!
Обучение и тестирование
Страница Live classification позволяет тестировать на тестовых данных или стримить аудио с телефона/платы. Выберите тестовый сэмпл → «Load sample» → классификация.
Для живого теста обновите страницу на телефоне, выберите устройство в «Classify new data» → «Start sampling». Так же работает с Nano BLE Sense через edge-impulse-daemon.
Развертывание (Deployment)
На телефон: обновите браузер на телефоне → «Switch to classification mode». Проект соберется в WebAssembly и будет работать локально (даже в авиарежиме).
На Nano BLE Sense: страница Deployment → «Arduino Nano 33 BLE Sense» под «Build firmware» → «Build».
Соберется полная прошивка с вашей моделью. Следуйте инструкциям на экране для прошивки платы.
После прошивки откройте Serial Monitor (115200 baud), нажмите Enter для промпта, введите:
> AT+RUNIMPULSE
Inferencing settings:
Interval: 0.06 ms.
Frame size: 16000
Sample length: 1000 ms.
No. of classes: 2
Starting inferencing, press 'b' to break
Recording...
Recording done
Predictions (DSP: 495 ms., Classification: 84 ms., Anomaly: 0 ms.):
cough: 0.01562
noise: 0.98438
...
(при кашле: cough: 0.86719, noise: 0.13281)
Дальнейшая работа
- Расширьте датасет своими записями кашля и фоновых звуков, переобучайте и тестируйте периодически. Настройте юнит-тесты на странице Testing.
- Добавьте класс «human sounds» (речь, зевание и т.д.).
- Создайте новый датасет для детекции других звуков (можно использовать шум из этого датасета как базу).
- Разверните как Arduino Library для скетча с индикацией на LED/дисплее.
- Используйте другие сенсоры Nano BLE Sense (акселерометр 3 оси) по этому туториалу.
Производственный процесс
- Датчик CO2 K30: мониторинг качества воздуха в реальном времени на Arduino
- Устройство для общения глухосліпых людей с помощью 1Sheeld и Arduino
- Умная копилка: управление монетоприёмником на Arduino Nano
- Управление светодиодом по Bluetooth с Arduino: простой DIY-гид
- Интеграция ёмкостного сканера отпечатков DFRobot с Arduino или ESP8266
- Интерактивный HMI-проект на Nextion с Arduino Mega и датчиками
- Роботизированная рука 6 степеней свободы на Arduino Mega с управлением через Nunchuk
- Оценка здоровья растений с TinyML: Практическое руководство
- Система мониторинга лесных пожаров в реальном времени с SMS-уведомлениями
- Измерение солнечной радиации на Arduino UNO с Ethernet Shield