11、时间序列分类与音频唤醒词检测实战
本文介绍了时间序列分类与音频唤醒词检测在TinyML中的实战应用。内容涵盖数据手动标注、特征工程(如统计矩、自相关、形状指标)、窗口化处理及分类链构建,并演示了如何将模型部署到Arduino设备。同时,详细说明了基于Edge Impulse平台的音频唤醒词检测流程,包括硬件选型、数据采集、MFCC特征提取、模型训练与评估优化,最后实现‘Hey Arduino’等语音命令的本地化识别,助力低功耗嵌入
时间序列分类与音频唤醒词检测实战
时间序列分类
在时间序列分类中,数据标注是重要的初始步骤。之前章节的数据标注是自动完成的,而现在需要手动进行。这一过程可能会很繁琐,尤其是在处理大量数据时,但数据集的准备(收集和标注)通常都很耗时。不过,输入数据的质量越高,分类结果的质量也会越高。
数据标注操作步骤
- 加载时间序列数据 :使用
tinyml4allPython 包中的TimeSeries类读取 CSV 文件夹中的数据。
from tinyml4all.time.episodic.classification import TimeSeries
ts = TimeSeries.read_csv_folder("media-control")
- 运行标注 GUI :调用
label_gui()方法打开浏览器窗口,在窗口中对时间序列进行标注。
ts.label_gui()
- 保存标注结果 :标注完成后,从页面底部的 Output 标签复制内容,粘贴到一个名为
labels.json的新文件中,或者点击下载图标,然后将文件移动到media-control文件夹中。
需要注意的是,数据文件夹中可能会有 PKL 文件,这些文件是由 tinyml4all 库自动创建的,包含时间序列数据的紧凑表示,不要删除它们,因为它们可以加快代码的加载时间。
以下代码可以用来验证数据加载和标注结果:
from tinyml4all.time.episodic.classification import TimeSeries
ts = TimeSeries.read_csv_folder("media-control")
print(ts.events)
特征工程
特征工程是时间序列分类中的关键环节。在处理多维数据时,通常会对每个维度单独进行特征提取,最后将各维度的特征连接成一个特征向量。
以下是一些常用的特征:
1. 统计矩
- 均值(Mean) :数据集的平均值,反映数据的中心趋势。
- 标准差(Standard deviation) :衡量数据相对于均值的离散程度。
- 偏度(Skew) :衡量数据分布的不对称性。
- 峰度(Kurtosis) :衡量数据分布的尾部密度。
2. 自相关(Autocorrelation) :衡量时间序列在不同时间点的相似性,反映数据的短期模式。
3. 形状指标
- 峰值数量(Number of peaks) :序列中的峰值(最小值或最大值)数量。
- 高于/低于均值的样本数量(Count above/below mean) :值大于/小于均值的样本数量。
为了更全面地捕捉时间序列的模式,通常会使用窗口化方法将长输入序列分割成较短的重叠块。窗口化有两个重要参数:
- 长度(Length) :窗口内包含的样本数量。
- 偏移(Shift) :窗口满时,丢弃的样本数量,以容纳新的样本。
时间序列分类链
为了对时间序列输入数据进行预处理、窗口化、特征提取和分类,需要构建一个操作链。 Chain 类提供了一个结构化的格式,包含以下几个部分:
- pre(预处理) :对输入数据进行预处理的步骤列表,如缩放、归一化、分箱等,可选。
- chunk(分块) :定义子块的持续时间,可选。
- features(特征提取) :负责从每个窗口(或块)中提取特征的步骤(或步骤列表),必须。
- ovr(一对多分类) :在特征提取后对数据的二进制视图(感兴趣的类与非感兴趣的类)运行的步骤列表,必须。
以下是一个示例代码,展示了如何构建和使用时间序列分类链:
from tinyml4all.time.episodic.classification import TimeSeries, Chain
from tinyml4all.time.episodic.features import Window
from tinyml4all.time.features import Scale, Moments, Autocorrelation, Peaks, CountAboveMean, Select
from tinyml4all.time.models import RandomForest
ts = TimeSeries.read_csv_folder("media-control")
chain = Chain(
pre=[Scale("minmax")],
window=Window(chunk="250ms", features=[Moments(), Autocorrelation(), Peaks(), CountAboveMean()]),
ovr=[
Select(sequential="auto"),
RandomForest()
]
)
tables = chain(ts)
for table in tables:
print(table.classification_report())
| True vs Predicted | not volume-up | volume-up |
|---|---|---|
| not volume-up | 230 | 0 |
| volume-up | 0 | 26 |
部署到 Arduino
训练完成后,需要将分类链转换为 C++ 代码,以便在 Arduino 上运行。以下是具体的操作步骤:
1. 生成 C++ 代码 :使用 convert_to() 方法将分类链转换为 C++ 代码。
chain.convert_to("c++", class_name="MediaControlChain", save_to="MediaControlChain.h")
- 复制代码到项目文件夹 :将生成的
MediaControlChain.h文件复制到 Arduino 项目的文件夹中。 - 上传 Arduino 代码 :上传以下代码到 Arduino 板,实现媒体控制手势的预测。
#include <Arduino_LSM9DS1.h>
#include <PluggableUSBHID.h>
#include <USBKeyboard.h>
#include <tinyml4all.h>
#include "./MediaControlChain.h"
tinyml4all::LSM9DS1 imu;
tinyml4all::MediaControlChain chain;
USBKeyboard keyboard;
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println("Predict media control gestures");
imu.begin();
}
void loop() {
imu.readMagneticField();
if (!chain(imu.mx, imu.my, imu.mz))
return;
if (chain.output.classification.label == "idle")
return;
Serial.print("Predicted ");
Serial.print(chain.output.classification.label);
Serial.print(" with confidence ");
Serial.println(chain.output.classification.confidence);
if (chain.label == "tap")
keyboard.media_control(KEY_PLAY_PAUSE);
else if (chain.label == "next")
keyboard.media_control(KEY_NEXT_TRACK);
}
打开串口监视器,进行媒体控制手势操作,你会看到预测结果。该方法的预测时间约为 4 ms,比 Edge Impulse 模型快很多,但通常准确性较低。
音频唤醒词检测
在 TinyML 和音频处理领域,音频唤醒词检测(Keyword Spotting,KWS)对于实现设备的免提交互至关重要。从智能音箱到手机,KWS 系统不断监听特定的唤醒词或命令。然而,在资源受限的设备上实现这些系统面临着独特的挑战,特别是在高效处理原始音频数据方面。
硬件要求
要进行音频唤醒词检测,需要一个麦克风来捕获音频。以下是一些内置麦克风的 Arduino 板:
- PDM 接口 :Arduino Nano BLE Sense、Arduino RP2040 Connect 和 Nicla Vision。
- I2S 接口 :Seeed Studio Wio Terminal 和 LILYGO TTGO 变体。
如果没有这些板,可以购买外部麦克风,并根据其要求进行连接。常见的 Arduino 麦克风有两种类型:
- PDM(脉冲密度调制) :音频波形编码在数字脉冲的密度中,需要专门的软件进行解码,通常只处理单声道音频,每个样本 16 位。
- I2S(Inter-IC Sound) :音频输出已经编码,无需进一步处理,Arduino 生态系统中的 I2S 麦克风通常可以处理 32 位立体声音频。
在购买麦克风时,要确保其与所用的 Arduino 板兼容。后续的代码示例假设使用的是 Arduino Nano BLE Sense,你可以在代码仓库中找到不同设备的更多示例。
通过以上内容,我们介绍了时间序列分类和音频唤醒词检测的基本原理、操作步骤和代码实现,希望能帮助你在相关领域开展实践和研究。
时间序列分类与音频唤醒词检测实战(续)
音频唤醒词检测实战流程
在具备了合适的硬件之后,就可以开始音频唤醒词检测的实战操作了。这里以使用 Edge Impulse 低代码平台为例,构建一个类似常见语音助手激活机制的系统,用“Hey Arduino”语音命令来唤醒 Arduino 板。
数据采集
首先需要采集音频数据,这些数据将用于训练唤醒词检测模型。具体操作如下:
1. 连接硬件 :确保 Arduino 板和麦克风正常连接。若使用 Arduino Nano BLE Sense,其内置麦克风可直接使用。
2. 安装 Edge Impulse CLI :在本地环境中安装 Edge Impulse 的命令行工具,用于与 Edge Impulse 平台进行交互。
3. 初始化项目 :在命令行中使用 Edge Impulse CLI 初始化一个新的项目,并将其与 Arduino 板连接。
4. 采集数据 :在 Edge Impulse 平台上创建不同的标签,如“Hey Arduino”和“背景噪音”等。然后对着麦克风说出唤醒词和产生背景噪音,通过 CLI 工具将音频数据上传到 Edge Impulse 平台。
特征提取与模型训练
Edge Impulse 平台会自动对采集到的音频数据进行特征提取和模型训练。
- 特征提取 :平台会使用一些先进的音频特征描述符,如梅尔频率倒谱系数(MFCC)等,将音频数据转换为特征向量。
- 模型训练 :选择合适的机器学习模型,如神经网络,对特征向量进行训练。平台会自动划分训练集和验证集,以评估模型的性能。
以下是一个简单的 mermaid 流程图,展示了数据采集和模型训练的流程:
graph LR
A[连接硬件] --> B[安装 Edge Impulse CLI]
B --> C[初始化项目]
C --> D[采集数据]
D --> E[上传数据到平台]
E --> F[特征提取]
F --> G[模型训练]
模型部署
训练好模型后,需要将其部署到 Arduino 板上。
1. 生成代码 :在 Edge Impulse 平台上生成适用于 Arduino 的 C++ 代码。
2. 下载代码 :将生成的代码下载到本地,并复制到 Arduino 项目文件夹中。
3. 上传代码 :使用 Arduino IDE 将代码上传到 Arduino 板。
以下是一个简单的 Arduino 代码示例,用于运行唤醒词检测模型:
#include <Arduino_LSM9DS1.h>
#include <EdgeImpulse.h>
// 包含 Edge Impulse 生成的代码
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"
// 定义麦克风采样率等参数
#define SAMPLE_RATE 16000
#define SAMPLE_LENGTH 1000
// 音频缓冲区
float audio_buffer[SAMPLE_LENGTH];
void setup() {
Serial.begin(115200);
// 初始化麦克风等硬件
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
}
void loop() {
// 采集音频数据
for (int i = 0; i < SAMPLE_LENGTH; i++) {
audio_buffer[i] = analogRead(A0);
delayMicroseconds(1000000 / SAMPLE_RATE);
}
// 运行模型进行预测
ei_impulse_result_t result;
EI_IMPULSE_ERROR res = run_classifier(audio_buffer, &result, false);
if (res != EI_IMPULSE_OK) {
Serial.println("Failed to run classifier!");
return;
}
// 输出预测结果
for (size_t ix = 0; ix < result.classification.count; ix++) {
Serial.print(result.classification[ix].label);
Serial.print(": ");
Serial.println(result.classification[ix].value);
}
// 判断是否检测到唤醒词
if (result.classification[0].value > 0.8) {
Serial.println("Hey Arduino detected!");
// 可以在这里添加唤醒后的操作,如点亮 LED 等
}
delay(100);
}
模型评估与优化
在模型部署到 Arduino 板后,需要对其进行评估和优化。
- 评估指标 :使用准确率、召回率、F1 值等指标来评估模型的性能。
- 优化方法 :如果模型性能不理想,可以尝试增加训练数据、调整特征提取参数或更换模型结构等方法进行优化。
以下是一个简单的表格,展示了不同评估指标的含义:
| 评估指标 | 含义 |
| ---- | ---- |
| 准确率 | 模型正确预测的样本数占总样本数的比例 |
| 召回率 | 模型正确预测的正样本数占实际正样本数的比例 |
| F1 值 | 准确率和召回率的调和平均数,综合衡量模型的性能 |
总结
时间序列分类和音频唤醒词检测在 TinyML 领域都有着重要的应用。时间序列分类通过手动标注数据、特征工程和构建分类链等步骤,能够对时间序列数据进行有效的分类,并可以部署到 Arduino 等嵌入式设备上。而音频唤醒词检测则需要合适的硬件支持,借助 Edge Impulse 等低代码平台进行数据采集、特征提取、模型训练和部署,实现设备的免提交互。
虽然这两种技术都有各自的挑战,但通过合理的方法和实践,能够取得较好的效果。在实际应用中,可以根据具体需求对模型进行进一步的优化和调整,以满足不同场景的要求。未来,随着 TinyML 技术的不断发展,时间序列分类和音频唤醒词检测有望在更多的领域得到应用和拓展。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)