太牛逼了,应用TinyML(嵌入式机器学习库)10分钟就可以在Arduino开发板上实现咳嗽检测
在这篇文章中,将介绍如何使用TinyML(嵌入式机器学习库)和Edge Impulse在Arduino Nano BLE Sense开发板打造一套咳嗽检测系统。
关键字: 声音 嵌入式 机器学习
TinyML 嵌入式机器学习库
Edge Impulse 一个在边缘设备上进行机器学习的在线开发平台
组件和材料
app和在线服务
项目背景
对于COVID-19和其他流感相关疾病早期检测,需要一套廉价、易于部署的解决方案。Arduino最近与联合国、Hackster、Edge Impulse和许多其他机构一道发起了联合国COVID-19检测和保护挑战,旨在为发展中国家预防和检测流感提供易于部署的解决方案。在本教程中,我们将展示如何在Arduino Nano传感器上使用Edge Impulse机器学习来实时检测人群在是否存在咳嗽病例。我们建立了一个咳嗽和背景噪音样本的数据集,并应用了一个高度优化的TInyML 模型,这个模型可以运行在廉价的嵌入式设备中。
准备开始
本教程有以下要求:
- 基本了解软件开发和Arduino平台的应用
- 安装Arduino IDE或CLI
- Android或iOS手机
- Arduino Nano BLE Sense或其它Cortex-M4+带麦克风的电路板(可选)
我们将使用Edge Impulse,这是一个在边缘设备上进行机器学习的在线开发平台。在这里你需要注册一个免费帐户。登录您的帐户,并通过单击标题为新项目命名。我们称之为“Arduino咳嗽检测”。
采集数据样本
任何机器学习项目的第一步都是收集一个数据集,该数据集表示我们希望能够在Arduino设备上匹配的已知数据样本。 首先,我们创建了一个包含10分钟音频的小型数据集,分为“咳嗽”和“噪音”两个类别。 我们将展示如何将该数据集导入Edge Impulse项目,添加您自己的样本,甚至从头开始创建自己的数据集。 此数据集很小,并且咳嗽和背景噪音样本数量有限。 因此,该数据集仅适用于实验,并且本教程中生成的模型仅能够区分安静的背景噪音和小范围的咳嗽。 我们建议您使用更广泛的咳嗽,背景噪音和其他类别(如人类语音)来扩展数据集,以提高性能。
注意:强迫自己咳嗽可能有损声带,在收集数据和测试时要小心!
首先下载我们的咳嗽数据集,然后在PC上选择提取文件的位置上: https:// cdn.edgeimpulse.com/dat asets/cough.zip
您可以使用Edge Impulse CLI Uploader将此数据集导入到Edge Impulse项目。 按照以下安装说明安装Edge Impulse CLI。
打开终端或命令提示符,并定位到提取文件的文件夹。
运行:
$ edge-impulse-uploader --clean
$ edge-impulse-uploader --category training training/*
$ edge-impulse-uploader --category testing testing/*
系统将提示输入您的Edge Impulse用户名、密码和要添加数据集的项目。数据集示例现在将在数据获取页面上可见。通过单击一个示例,我们可以看到示例的外观,并通过单击每个图下面的播放按钮来听到音频。
10分钟的咳嗽和噪音数据样本足够开始特征分析。 您可以选择使用自己的咳嗽和背景噪音样本扩展数据集。 我们可以从“数据获取”页面直接从设备收集新的数据样本。 WAV格式的音频样本也可以使用Edge Impulse CLI Uploader上载。
重要提示:实际应用中使用的模型应使用尽可能多样的数据集进行训练和测试。 此初始数据集相对较小,因此当暴露于不同类型的背景噪音或来自不同人群的咳嗽时,该模型的性能将不一致。
最简单的测试方法是使用手机收集音频数据(此处有完整的教程)。 转到设备页面,然后点击右上角的“ +连接新设备”按钮。 选择“使用您的手机”。 将会产生一个唯一的二维码,在手机浏览器上打开Web应用程序。 拍摄二维码的图片,然后选择打开链接。
该Web应用程序将与Edge Impulse项目连接,如下图所示:
现在,我们可以从Edge Impulse的“数据获取”页面直接从电话收集音频数据样本。 在“记录新数据”部分中,键入“咳嗽”或“噪音”标签,确保已选择“麦克风”作为传感器,然后单击“开始采样”。 您的电话现在将收集音频样本,并将其添加到数据集中。
还支持直接从Nano BLE Sense板收集音频数据。 请按照以下说明安装Edge Impulse固件和守护程序。 将设备连接到Edge Impulse后,您可以像上面的移动电话一样收集数据样本。
建造你自己的音频脉冲模型
接下来,我们将在“创建脉冲”页面上选择信号处理和机器学习模块。 脉冲将开始为空白,带有原始数据和输出功能块。 保留默认设置,即1000毫秒窗口大小和500毫秒窗口增加。 这意味着我们的音频数据将一次处理1秒,每0.5秒开始。 使用小窗口可以节省嵌入式设备上的内存,但是这意味着我们需要样本咳嗽数据,并且咳嗽之间不会出现大的中断。
点击“添加处理块”,然后选择音频(MFCC)块。 接下来,点击“添加学习模块”,然后选择神经网络(Keras)模块。 点击“保存冲动”。 音频块将为每个音频窗口提取一个声谱图,并且将根据我们的训练数据集对神经网络块进行训练,以将声谱图分类为“咳嗽”或“噪声”。 您产生的脉冲将如下图所示:
接下来,我们将从MFCC页面上的训练数据集中生成特征。 此页面显示从任何数据集样本中每隔1秒窗口提取的频谱图的样子。 我们可以将参数保留为默认值。
接下来,点击“生成功能”按钮,然后使用此处理块处理整个训练数据集。 这将创建完整的功能集,这些功能将用于下一步训练我们的神经网络。 按“生成功能”按钮开始处理,这需要几分钟的时间才能完成。
现在,我们可以在NN分类器页面上继续设置和训练我们的神经网络。 默认的神经网络非常适合连续的声音,如流水。 咳嗽检测更为复杂,因此我们将使用跨每个窗口的频谱图的2D卷积来配置更丰富的网络。 2D卷积以类似于图像分类的方式处理音频频谱图。 按下“神经网络设置”部分的右上角,然后选择“切换到Keras(专家)模式”。
将“神经网络体系结构”定义替换为以下代码,并将“最低可信度”设置设为“ 0.70”。 然后继续点击“开始训练”按钮。 训练将需要几秒钟。
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 architecture
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)))
# this controls the learning rate
opt = Adam(lr=0.005, beta_1=0.9, beta_2=0.999)
# train the neural network
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)
该页面将显示训练效果和设备上的效果,具体取决于您的数据集:
我们的Arduino咳嗽检测算法现在可以进行测试了!
训练和测试
实时分类页面使我们既可以使用数据集附带的现有测试数据,也可以通过流式传输来自手机或Arduino设备的音频数据来测试算法。 我们可以从一个简单的测试开始,选择任何一个测试样本,然后按“加载样本”。 这将对测试样本进行分类并显示结果:
我们还可以使用实时数据测试该算法。 通过刷新我们之前打开的手机上的浏览器页面来开始使用手机。 然后在“对新数据分类”部分中选择您的设备,然后按“开始采样”。 与数据收集步骤中一样,通过edge-impulse-daemon连接到项目时,您也可以类似地从Nano BLE Sense中流式传输音频样本。
部署
我们可以轻松地将咳嗽检测算法部署到手机上。 转到手机上的浏览器窗口并刷新,然后按“切换到分类模式”按钮。 这将自动将项目构建到WebAssembly程序包中,并在您的手机上连续执行(此后不需要云,甚至进入飞行模式!)
接下来,我们可以转到“部署”页面,将算法部署到Nano BLE Sense。 在“构建固件”下选择“ Arduino Nano 33 BLE Sense”,然后单击“构建”。
这将为Nano BLE Sense构建完整的固件,包括您的最新算法。 按照屏幕上的说明用二进制文件刷新Arduino板。
Arduino刷新后,我们可以在设备以115、200波特的速度将其插入USB时打开该设备的串行端口。 串行端口打开后,按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
Starting inferencing in 2 seconds...
Recording...
Recording done
Predictions (DSP: 495 ms., Classification: 84 ms., Anomaly: 0 ms.):
cough: 0.01562
noise: 0.98438
Starting inferencing in 2 seconds...
Recording...
Recording done
Predictions (DSP: 495 ms., Classification: 84 ms., Anomaly: 0 ms.):
cough: 0.86719
noise: 0.13281
Starting inferencing in 2 seconds...
Recording...
Recording done
Predictions (DSP: 495 ms., Classification: 84 ms., Anomaly: 0 ms.):
cough: 0.01562
noise: 0.98438
进一步优化措施
Arduino上的TinyML,传感器和Edge Impulse限制了发展的空间,以下是下一步工作的一些建议:
- 使用自己的咳嗽声和背景音扩展默认数据集,请记住要定期重新训练并进行测试。 您可以在“测试”页面下设置单元测试,以确保模型在扩展后仍能正常工作。
- 为不会咳嗽的人声添加新的类和数据,例如背景语音,打哈欠等。
- 从新的数据集开始,收集音频样本以检测新事物。 提示:您可以仅从该数据集中上传噪声等级数据以开始使用!
- 根据这些说明,将其作为Arduino Sketch的一部分部署到Arduino Library,以使用LED或显示器显示咳嗽检测
- 通过遵循本教程,可以使用其他传感器,例如Nano BLE Sense的3轴加速度计。