译者:飞龙
协议:CC BY-NC-SA 4.0>
现在,每次某个类别得分超过 0.8 时,相应的 LED 将会点亮:
-
Led 红色开启:不确定(没有类别得分超过 0.8)
-
Led 绿色开启:Periquito > 0.8
-
Led 蓝色开启:Robot > 0.8
-
所有 LED 关闭:背景 > 0.8
这是结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file408.png
更详细地
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file409.png
图像分类(非官方)基准
可以使用多个开发板进行嵌入式机器学习(TinyML),对于计算机视觉应用(消耗低能量)最常见的是 ESP32 CAM、Seeed XIAO ESP32S3 Sense、Arduino Nicla Vison 和 Arduino Portenta。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file410.jpg
抓住机会,相同的训练模型被部署在 ESP-CAM、XIAO 和 Portenta 上(在这个例子中,模型再次进行了训练,使用灰度图像以兼容其摄像头)。以下是结果,将模型作为 Arduino 库部署:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file411.png
摘要
在我们结束之前,考虑一下计算机视觉不仅仅是图像分类。例如,你可以在多个领域的视觉周围开发边缘机器学习项目,例如:
-
自动驾驶汽车:使用传感器融合、激光雷达数据和计算机视觉算法进行导航和决策。
-
医疗保健:通过 MRI、X 射线和 CT 扫描图像分析自动诊断疾病。
-
零售:自动结账系统,在产品通过扫描仪时识别产品。
-
安全和监控:实时视频流中的面部识别、异常检测和物体跟踪。
-
增强现实:物体检测和分类,以在现实世界中叠加数字信息。
-
工业自动化:产品的视觉检查、预测性维护以及机器人和无人机引导。
-
农业:基于无人机进行作物监测和自动化收割。
-
自然语言处理:图像标题和视觉问答。
-
手势识别:用于游戏、手语翻译和人与机器交互。
-
内容推荐:基于图像的电子商务推荐系统。
资源
目标检测
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file412.jpg
DALL·E 3 提示:以 1940 年或 1950 年代的卡通风格展示宽敞的工业仓库内部。一个传送带突出显示,上面载着玩具轮子和箱子混合物。轮子以其明亮的黄色中心和黑色轮胎而可辨。箱子是白色立方体,涂有交替的黑白图案。在移动传送带的末端站着一个复古风格的机器人,装备有工具和传感器,勤奋地对到达的轮子和箱子进行分类和计数。整体美学让人联想到中世纪动画,线条粗犷,色彩经典。
概述
现在,Nicla Vision 上的图像分类的延续正在探索目标检测。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file413.png
目标检测与图像分类
图像分类模型的主要任务是生成一个列表,列出图像上最可能存在的物体类别,例如,在猫吃完饭后识别一只虎斑猫:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file414.png
但是当猫跳到酒杯附近时会发生什么呢?模型仍然只识别图像上的主要类别,即虎斑猫:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file415.png
如果图像上没有主导类别会发生什么呢?
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file416.png
模型完全错误地将上述图像识别为“废纸篓”,可能是由于色彩色调的原因。
所有先前示例中使用的模型是 MobileNet,它使用了一个大型数据集,ImageNet。
为了解决这个问题,我们需要另一种类型的模型,这种模型不仅能够找到多个类别(或标签),而且还能确定在给定图像中物体的位置。
如我们所想,这样的模型要复杂得多,体积也更大,例如,MobileNetV2 SSD FPN-Lite 320x320,使用 COCO 数据集进行训练。这个预训练的目标检测模型旨在在图像中定位多达 10 个物体,并为每个检测到的物体输出一个边界框。下面是这样一个模型在 Raspberry Pi 上运行的结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file417.png
用于目标检测的模型(如 MobileNet SSD 或 YOLO)通常大小为几个 MB,这对于 Raspberry Pi 来说是可以的,但与嵌入式设备不兼容,因为嵌入式设备的 RAM 通常低于 1 兆字节。
目标检测的创新解决方案:FOMO
Edge Impulse 于 2022 年推出,FOMO(更快的目标,更多目标),这是一种在嵌入式设备上执行目标检测的新颖解决方案,不仅适用于 Nicla Vision(Cortex M7),还适用于 Cortex M4F CPU(Arduino Nano33 和 OpenMV M4 系列以及 Espressif ESP32 设备(ESP-CAM 和 XIAO ESP32S3 Sense))。
在这个动手实验中,我们将探索使用 FOMO 进行对象检测,不会深入介绍模型本身的细节。要了解更多关于模型如何工作的信息,你可以查看 Edge Impulse 的官方 FOMO 宣布,其中 Louis Moreau 和 Mat Kelcey 详细解释了其工作原理。
对象检测项目目标
所有机器学习项目都需要从一个详细的目标开始。假设我们在一个工业设施中,必须对轮子和特殊的箱子进行分类和计数。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file418.jpg
换句话说,我们应该执行多标签分类,其中每张图像可以有三种类别:
-
背景(无对象)
-
箱子
-
轮子
这里有一些未标记的图像样本,我们将使用它们来检测对象(轮子和箱子):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file419.jpg
我们感兴趣的是图像中的哪个对象,其位置(质心),以及我们能在上面找到多少个。与 MobileNet SSD 或 YOLO 一样,FOMO 不检测对象的大小,因为边界框是模型输出之一。
我们将使用 Nicla Vision 进行图像捕捉和模型推理来开发项目。机器学习项目将使用 Edge Impulse Studio 进行开发。但在开始 Studio 中的对象检测项目之前,让我们使用包含要检测的对象的图像创建一个原始数据集(未标记)。
数据收集
对于图像捕捉,我们可以使用:
-
Web Serial Camera 工具,
-
Edge Impulse Studio,
-
OpenMV IDE,
-
一部智能手机。
在这里,我们将使用OpenMV IDE。
使用 OpenMV IDE 收集数据集
首先,我们在电脑上创建一个文件夹来保存数据,例如,“data。”然后,在 OpenMV IDE 中,我们转到“工具 > 数据集编辑器”并选择“新建数据集”以开始数据集收集:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file420.jpg
Edge Impulse 建议对象的大小应该相似,且不要重叠,以获得更好的性能。这在工业设施中是可行的,因为相机应该固定,保持与要检测的对象相同的距离。尽管如此,我们也会尝试使用不同大小和位置来查看结果。
我们不会为我们的图像创建单独的文件夹,因为每个文件夹都包含多个标签。
将 Nicla Vision 连接到 OpenMV IDE 并运行 dataset_capture_script.py。点击“捕捉图像”按钮将开始捕捉图像:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file421.jpg
我们建议使用大约 50 张图像来混合对象,并改变场景中每个对象出现的数量。尝试捕捉不同的角度、背景和光照条件。
存储的图像使用 QVGA 分辨率 320×240320\times 240 和 RGB565(颜色像素格式)。
在捕捉完你的数据集后,关闭“工具 > 数据集编辑器”中的数据集编辑工具。
Edge Impulse Studio
设置项目
前往 Edge Impulse Studio,在 登录(或创建账户)处输入您的凭据,并开始一个新项目。
在这里,您可以克隆为这个动手实践开发的该项目:NICLA_Vision_Object_Detection。
在项目 仪表板 中,转到 项目信息 并选择 边界框(目标检测),然后在页面右上角选择 目标,Arduino Nicla Vision (Cortex-M7)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file422.png
上传未标记的数据
在 Studio 中,转到 数据采集 选项卡,在 上传数据 部分从您的计算机文件上传。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file423.png
您可以离开工作室,让数据自动在训练和测试之间分割,或者手动进行。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file424.png
所有未标记的图像(51 张)都已上传,但在用作项目中的数据集之前,它们还需要适当标注。工作室有一个用于此目的的工具,您可以在链接 标注队列(51) 中找到。
您可以使用两种方式在 Edge Impulse Studio(免费版)上执行人工智能辅助标注:
-
使用 yolov5
-
在帧之间跟踪对象
Edge Impulse 为企业客户推出了 自动标注功能,简化了目标检测项目中的标注任务。
使用现有的 YOLOv5 预训练对象检测模型库(使用 COCO 数据集训练)可以快速识别和标注普通对象。但由于在我们的案例中,对象不是 COCO 数据集的一部分,我们应该选择 跟踪对象 选项。使用此选项,一旦您在一个帧中绘制边界框并标注图像,对象将自动从帧到帧跟踪,部分 标注新的对象(并非所有都正确标注)。
如果您已经有一个包含边界框的已标记数据集,请使用 EI 上传器导入您的数据。
标注数据集
从您未标记的数据的第一张图像开始,使用鼠标拖动一个框来围绕对象添加标签。然后点击 保存标签 以进入下一项。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file425.png
继续此过程,直到队列清空。最后,所有图像都应标注为以下样本中的对象:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file426.jpg
接下来,在 数据采集 选项卡上查看已标记样本。如果其中一个标签错误,可以在样本名称后的 三个点 菜单中进行编辑:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file427.png
我们将指导您替换错误的标签并纠正数据集。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file428.jpg
冲量设计
在这个阶段,我们应该定义如何:
-
预处理包括将单个图像从
320 x 240调整到96 x 96并将其压扁(方形形式,不裁剪)。之后,图像从 RGB 转换为灰度。 -
设计模型,在这种情况下,“目标检测”。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file429.png
预处理所有数据集
在本节中,选择颜色深度为灰度,适合与 FOMO 模型一起使用,并保存参数。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file430.png
Studio 会自动移动到下一个部分,即“生成特征”,在这里所有样本都将进行预处理,从而生成包含单个96×96×196\times 96\times 1图像或 9,216 个特征的数据库。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file431.png
特征探索器显示,在特征生成后,所有样本都显示出良好的分离。
其中一个样本(46 号)显然位于错误的空间中,但点击它确认标签是正确的。
模型设计、训练和测试
我们将使用 FOMO,这是一个基于 MobileNetV2(alpha 0.35)的对象检测模型,旨在将图像粗略分割成背景与感兴趣对象(在此处为框和轮子)的网格。
FOMO 是一个创新的机器学习对象检测模型,与传统模型如 Mobilenet SSD 和 YOLOv5 相比,可以节省高达 30 倍的能量和内存。FOMO 可以在小于 200 KB RAM 的微控制器上运行。这之所以可能,是因为其他模型通过围绕对象绘制一个正方形(边界框)来计算对象的大小,而 FOMO 忽略了图像的大小,仅通过其质心坐标提供有关对象在图像中位置的信息。
FOMO 是如何工作的?
FOMO 将图像转换为灰度,并使用 8 的因子将其划分为像素块。对于 96x96 的输入,网格将是12×1212\times 12 (96/8=12)(96/8=12)。接下来,FOMO 将对每个像素块运行一个分类器,以计算其中每个像素块包含框或轮子的概率,并随后确定具有最高概率包含对象的区域(如果一个像素块没有对象,它将被分类为背景)。从最终区域的重叠部分,FOMO 提供了该区域质心的坐标(与图像尺寸相关)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file432.png
对于训练,我们应该选择一个预训练的模型。让我们使用**FOMO (Faster Objects, More Objects) MobileNetV2 0.35**。这个模型大约使用 250 KB 的 RAM 和 80 KB 的 ROM(闪存),非常适合我们的板子,因为它有 1 MB 的 RAM 和 ROM。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file433.png
关于训练超参数,模型将使用以下参数进行训练:
-
迭代次数:60,
-
批处理大小:32
-
学习率:0.001。
在训练期间的验证中,20%的数据集(validation_dataset)将被保留。对于剩余的 80%(train_dataset),我们将应用数据增强,这会随机翻转、改变图像的大小和亮度,并裁剪它们,人为地增加数据集上的样本数量以供训练。
因此,该模型最终在验证数据上达到约 91%的 F1 分数(验证)和 93%(测试数据)。
注意,FOMO 自动将第三个标签背景添加到之前定义的两个标签(box和wheel)中。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file434.png
在目标检测任务中,准确率通常不是主要的评估指标。目标检测涉及对对象进行分类并在其周围提供边界框,这使得它比简单的分类更复杂。问题是我们没有边界框,只有质心。简而言之,使用准确率作为指标可能是误导性的,并且可能无法完全理解模型的性能。因此,我们将使用 F1 分数。
使用“实时分类”测试模型
由于 Edge Impulse 官方支持 Nicla Vision,让我们将其连接到 Studio。为此,请按照以下步骤操作:
-
下载最新的 EI 固件并将其解压。
-
在您的计算机上打开 zip 文件,并选择与您的操作系统相关的上传器。
-
将 Nicla-Vision 置于启动模式,按两次复位按钮。
-
执行针对您操作系统的特定批处理代码,将二进制文件(
arduino-nicla-vision.bin)上传到您的板子上。
前往 EI Studio 中的实时分类部分,并使用webUSB连接您的 Nicla Vision:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file435.png
连接后,您可以使用 Nicla 捕获实际图像,以便在 Edge Impulse Studio 上由训练模型进行测试。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file436.png
需要注意的是,模型可能会产生误报和漏报。这可以通过定义适当的置信度阈值(使用三个点菜单进行设置)来最小化。尝试使用 0.8 或更高。
部署模型
在部署选项卡上选择OpenMV 固件并按下 [构建]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file437.png
当您再次尝试使用 OpenMV IDE 连接 Nicla 时,它将尝试更新其固件。选择加载特定固件选项,或者转到工具 > 运行引导加载程序(加载固件)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file438.png
您将在计算机上找到来自 Studio 的 ZIP 文件。打开它:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file439.png
将.bin 文件加载到您的板子上:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file440.png
下载完成后,将显示一个弹出消息。按确定,并打开从 Studio 下载的脚本ei_object_detection.py。
注意:如果出现弹出窗口表示固件过时,请按
[NO],以升级它。
在运行脚本之前,让我们更改几行。请注意,您可以将窗口定义保留为 240×240240\times 240,并将捕获图像的相机设置为 QVGA/RGB。捕获的图像将由从 Edge Impulse 部署的 FW 预处理。
import sensor
import time
import ml
from ml.utils import NMS
import math
import image
sensor.reset() # Reset and initialize the sensor.
# Set pixel format (RGB565 or GRAYSCALE)
sensor.set_pixformat(sensor.RGB565)
# Set frame size to QVGA (320x240)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000) # Let the camera adjust.
重新定义最小置信度,例如,设置为 0.8 以最小化误报和漏报。
min_confidence = 0.8
如有必要,更改用于显示检测到的物体质心的圆圈颜色,以获得更好的对比度。
threshold_list = [(math.ceil(min_confidence * 255), 255)]
# Load built-in model
model = ml.Model("trained")
print(model)
# Alternatively, models can be loaded from the
# filesystem storage.
# model = ml.Model(
# '<object_detection_modelwork>.tflite',
# load_to_fb=True)
# labels = [line.rstrip('\n') for line in open("labels.txt")]
colors = [ # Add more colors if you are detecting more
# than 7 types of classes at once.
(255, 255, 0), # background: yellow (not used)
( 0, 255, 0), # cube: green
(255, 0, 0), # wheel: red
( 0, 0, 255), # not used
(255, 0, 255), # not used
( 0, 255, 255), # not used
(255, 255, 255), # not used
]
保持剩余代码不变
# FOMO outputs an image per class where each pixel in the
# image is the centroid of the trained object. So, we will
# get those output images and then run find_blobs() on them
# to extract the centroids. We will also run get_stats() on
# the detected blobs to determine their score.
# The Non-Max-Suppression (NMS) object then filters out
# overlapping detections and maps their position in the
# output image back to the original input image. The
# function then returns a list per class which each contain
# a list of (rect, score) tuples representing the detected
# objects.
def fomo_post_process(model, inputs, outputs):
n, oh, ow, oc = model.output_shape[0]
nms = NMS(ow, oh, inputs[0].roi)
for i in range(oc):
img = image.Image(outputs[0][0, :, :, i] * 255)
blobs = img.find_blobs(
threshold_list,
x_stride=1,
area_threshold=1,
pixels_threshold=1,
)
for b in blobs:
rect = b.rect()
x, y, w, h = rect
score = (
img.get_statistics(
thresholds=threshold_list, roi=rect
).l_mean()
/ 255.0
)
nms.add_bounding_box(x, y, x + w, y + h, score, i)
return nms.get_bounding_boxes()
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
for i, detection_list in enumerate(
model.predict([img], callback=fomo_post_process)
):
if i == 0:
continue # background class
if len(detection_list) == 0:
continue # no detections for this class?
print("********** %s **********" % model.labels[i])
for (x, y, w, h), score in detection_list:
center_x = math.floor(x + (w / 2))
center_y = math.floor(y + (h / 2))
print(f"x {center_x}\ty {center_y}\tscore {score}")
img.draw_circle((center_x, center_y, 12), color=colors[i])
print(clock.fps(), "fps", end="\n")
然后按下 绿色播放按钮 运行代码:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file441.png
从摄像头的视角来看,我们可以看到带有用 12 像素固定圆圈标记的质心的物体(每个圆圈都有独特的颜色,取决于其类别)。在串行终端上,模型显示了检测到的标签及其在图像窗口中的位置 (240×240)(240\times 240)。
注意,坐标原点位于左上角。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file442.jpg
注意,每秒帧率约为 8 fps(与我们使用图像分类项目得到的相似)。这是因为 FOMO 是巧妙地建立在 CNN 模型之上,而不是像 SSD MobileNet 或 YOLO 这样的物体检测模型。例如,当在 Raspberry Pi 4 上运行 MobileNetV2 SSD FPN-Lite 320×320320\times 320 模型时,延迟大约高 5 倍(大约 1.5 fps)
这里有一个展示推理结果的短视频:youtu.be/JbpoqRp3BbM
摘要
如路易斯·莫罗和马特·凯尔西在 2022 年发布时所说,FOMO 是图像处理领域的一个重大飞跃:
FOMO 是一个突破性的算法,首次将实时物体检测、跟踪和计数引入到微控制器中。
在嵌入式设备上探索物体检测(更确切地说,是计数它们)有多种可能性。这在例如计数蜜蜂的项目中非常有用。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file443.jpg
资源
关键词检测(KWS)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file444.jpg
DALL·E 3 提示:1950 年代风格的卡通场景,设置在一个复古音频研究室中。两位非裔美国女科学家位于中心。一位手持放大镜,仔细检查古老的电路,而另一位在记笔记。在他们木质桌子上,有多块带有传感器的板,其中特别突出麦克风。在这些板后面,一台带有大圆背的计算机显示 Arduino IDE。IDE 展示了 LED 引脚分配的代码和用于语音命令检测的机器学习推理。IDE 中的一个独特窗口,串行监视器,显示了表示说出的命令“是”和“否”的输出。房间氛围怀旧,有复古灯具、经典音频分析工具和描绘 FFT 图和时间域曲线的图表。
概述
在已经探索了 Nicla Vision 板在图像分类和目标检测应用中的使用后,我们现在将重点转向语音激活应用,通过一个关于关键词检测(KWS)的项目。
如在音频分类特征工程动手教程中介绍的那样,关键词检测(KWS)集成到许多语音识别系统中,使设备能够对特定的单词或短语做出响应。虽然这项技术支撑着像 Google Assistant 或 Amazon Alexa 这样的流行设备,但它同样适用于较小的、低功耗设备。本教程将指导您在配备数字麦克风的 Nicla Vision 开发板上使用 TinyML 实现 KWS 系统。
我们的设计模型将能够识别可以触发设备唤醒或特定动作的关键词,通过语音激活命令使它们活跃起来。
语音助手是如何工作的?
正如所说,市场上的语音助手,如 Google Home 或 Amazon Echo-Dot,只有在被特定的关键词“唤醒”时才会对人类做出反应,第一个是“嘿,谷歌”,第二个是“Alexa”。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file445.png
换句话说,语音命令的识别基于多阶段模型或级联检测。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file446.jpg
第一阶段:Echo Dot 或 Google Home 内部的小型微处理器持续监听,等待检测到关键词,使用边缘的 TinyML 模型(KWS 应用)。
第二阶段:只有在第一阶段由 KWS 应用触发后,数据才会被发送到云端并在更大的模型上处理。
下面的视频展示了在 Raspberry Pi 上编程 Google Assistant 的示例(第二阶段),Arduino Nano 33 BLE 作为 TinyML 设备(第一阶段)。
要探索上述 Google Assistant 项目,请参阅教程:从头开始构建智能语音助手。
在这个 KWS 项目中,我们将专注于第一阶段(KWS 或关键词检测),我们将使用 Nicla Vision,它有一个数字麦克风,将用于检测关键词。
KWS 动手项目
下面的图表展示了最终的 KWS 应用应该如何工作(在推理过程中):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file447.jpg
我们的 KWS 应用将识别四种声音类别:
-
YES(关键词 1)
-
NO(关键词 2)
-
噪声(没有说话;只有背景噪声)
-
未知(不同于 YES 和 NO 的不同单词的混合)
对于现实世界的项目,始终建议除了关键词之外,还包括其他声音,例如“噪声”(或背景)和“未知”。
机器学习工作流程
KWS 应用的主要组件是其模型。因此,我们必须使用我们特定的关键词、噪声和其他单词(“未知”)来训练这样的模型:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file448.jpg
数据集
任何机器学习工作流程的关键组件是数据集。一旦我们决定了特定的关键词,在我们的案例中是(YES和 NO),我们就可以利用 Pete Warden 开发的数据集,“Speech Commands: A Dataset for Limited-Vocabulary Speech Recognition。”这个数据集有 35 个关键词(每个有+1,000 个样本),例如 yes、no、stop 和 go。在yes和no这样的词中,我们可以得到 1,500 个样本。
您可以从 Edge Studio 下载数据集的一部分(关键词检测预构建数据集),该数据集包括我们将在此项目中使用的四个类别的样本:yes、no、noise 和 background。为此,请按照以下步骤操作:
-
下载关键词数据集
-
将文件解压到您选择的位置。
将数据集上传到 Edge Impulse Studio
在 Edge Impulse Studio(EIS)中启动一个新项目,并在“数据获取”部分选择“上传现有数据”工具。选择要上传的文件:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file449.jpg
定义标签,选择自动在训练和测试之间分割,并上传数据到 EIS。为所有类别重复此操作。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file450.jpg
数据集现在将出现在“数据获取”部分。请注意,大约 6,000 个样本(每类 1,500 个)被分为训练集(4,800 个)和测试集(1,200 个)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file451.jpg
捕获额外的音频数据
尽管我们从 Pete 的数据集中获得了大量数据,但收集一些我们自己的说话词是建议的。当与加速度计一起工作时,创建由相同类型的传感器捕获的数据集是至关重要的。在声音的情况下,这是可选的,因为我们实际上要分类的是音频数据。
声音和音频之间的关键区别是能量的类型。声音是机械扰动(纵向声波),通过介质传播,导致其压力变化。音频是表示声音的电气(模拟或数字)信号。
当我们发音一个关键词时,声波应转换为音频数据。转换应通过在 16 KHz 频率下以 16 位每样本幅度采样麦克风产生的信号来完成。
因此,任何可以生成具有此基本规格(16 KHz/16 位)的音频数据的设备都可以正常工作。作为一个 设备,我们可以使用 NiclaV、计算机,甚至您的手机。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file452.jpg
使用 NiclaV 和 Edge Impulse Studio
如我们在 设置 Nicla Vision 章节中学到的,EIS 正式支持 Nicla Vision,这简化了从其传感器(包括麦克风)捕获数据的过程。因此,请在 EIS 上创建一个新项目,并将 Nicla 连接到它,按照以下步骤操作:
-
下载最新更新的 EIS 固件 并解压。
-
在您的计算机上打开 zip 文件,并选择对应您操作系统的上传器:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file453.png
-
通过按重置按钮两次将 NiclaV 放入引导模式。
-
通过运行对应您操作系统的批处理代码,将二进制文件 arduino-nicla-vision.bin 上传到您的板子上。
前往您在 EIS 上的项目,并在 数据采集选项卡 上选择 WebUSB。将弹出一个窗口;选择显示 Nicla 已配对 的选项,并按 [连接]。
您可以在“数据采集”选项卡上的“收集数据”部分选择要选择哪些传感器数据。选择:内置麦克风,定义您的 标签(例如,是),采样 频率[16000Hz],以及 样本长度(以毫秒计),例如 [10s]。开始采样。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file454.jpg
Pete 的数据集中的数据长度为 1 秒,但记录的样本长度为 10 秒,必须分割成 1 秒的样本。在样本名称后面的 三个点 上点击,并选择 分割样本。
将弹出一个带有分割工具的窗口。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file455.jpg
一旦进入工具,将数据分割成 1 秒(1000 毫秒)的记录。如有必要,添加或删除段。此过程应适用于所有新的样本。
使用智能手机和 EI Studio
您还可以使用您的 PC 或智能手机捕获音频数据,使用 16 KHz 的采样频率和 16 位的位深度。
前往 设备,使用您的手机扫描 QR 码,并点击链接。浏览器中会出现一个数据收集应用程序。选择 收集音频,并定义您的 标签、数据捕获 长度 和 类别。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file456.jpg
重复与 NiclaV 使用的相同程序。
注意,任何应用程序,如 Audacity,都可以用于音频录制,只要您使用 16 KHz/16 位深度的样本。
创建 Impulse(预处理/模型定义)
一个 冲激 从原始数据中提取特征,使用信号处理来提取特征,然后使用学习模块来分类新数据。
冲激设计
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file457.jpg
首先,我们将使用 1 秒的窗口获取数据点,以 500 毫秒的间隔增强数据和滑动窗口。请注意,已设置零填充数据的选项。用“零”填充小于 1 秒的样本(在某些情况下,一些样本可以小于分割工具上的 1000 毫秒窗口,以避免噪声和尖峰)是至关重要的。
每个持续 1 秒的音频样本都应该进行预处理并转换为图像(例如,13×49×113\times 49\times 1)。正如在音频分类特征工程动手教程中讨论的那样,我们将使用音频(MFCC),它使用梅尔频率倒谱系数从音频信号中提取特征,这些特征非常适合人类语音,我们这里的案例。
接下来,我们选择分类模块,使用卷积神经网络(CNN)从头开始构建我们的模型。
或者,您可以使用
迁移学习(关键词检测)模块,该模块在您的数据上微调预训练的关键词检测模型。这种方法在相对较小的关键词数据集上具有很好的性能。
预处理(MFCC)
下一个步骤是创建下一阶段要训练的特征:
我们可以保留默认参数值,但我们将使用 DSP 的自动调整参数选项。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file458.jpg
我们将使用原始特征(我们的 1 秒,16 KHz 采样音频数据)并使用 MFCC 处理模块来计算处理特征。对于每 16,000 个原始特征(16,000 ×\times 1 秒),我们将得到 637 个处理特征 (13×49)(13\times 49)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file459.jpg
结果显示,我们只使用了少量的内存来预处理数据(16 KB)和 34 毫秒的延迟,这是非常出色的。例如,在 Arduino Nano(Cortex-M4f @ 64 MHz)上,相同的预处理将需要大约 480 毫秒。选择的参数,如FFT 长度[512],将显著影响延迟。
现在,让我们保存参数并切换到生成特征标签页,在这里将生成实际的特征。使用UMAP,一种降维技术,特征探索器显示了特征在二维图上的分布情况。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file460.jpg
结果看起来不错,是特征(红色)和否特征(蓝色)之间有明显的视觉分离。未知特征似乎比否空间更接近是。这表明关键字否更容易产生误报。
深入了解内部结构
要更好地了解原始声音是如何预处理的,请查看音频分类的特征工程章节。您可以通过从 GitHub 下载此notebook来尝试 MFCC 特征生成,或[在 Colab 中打开]。
模型设计和训练
我们将使用一个简单的卷积神经网络(CNN)模型,使用一维和二维卷积进行测试。基本架构有两个卷积+最大池化块([8]和[16]个过滤器,分别)和一个[0.25]的 Dropout 用于一维,[0.5]的 Dropout 用于二维。对于最后一层,在 Flattening 之后,我们有[4]个神经元,每个类别一个:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file461.jpg
作为超参数,我们将有一个[0.005]的学习率,并通过[100]个 epoch 训练模型。我们还将包括基于SpecAugment的数据增强方法。我们使用相同超参数训练了一维和二维模型。一维架构的整体结果更好(与二维的 88%相比,准确率为 90.5%,因此我们将使用一维)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file462.jpg
使用一维卷积更高效,因为它需要的参数比二维卷积少,这使得它们更适合资源受限的环境。
1D 混淆矩阵也很有趣。是的 F1 分数为 95%,否为 91%。这与我们在特征探索器中看到的结果相符(否和未知距离很近)。在尝试提高结果时,您可以仔细检查出错样本的结果。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file463.jpg
听一下出错的样本。例如,对于“是”,大多数错误都与发音为“耶”的“是”有关。您可以获取更多样本,然后重新训练您的模型。
深入了解内部结构
如果您想了解“内部结构”中发生的事情,您可以从“仪表板”选项卡下载预处理的数据集(MFCC 训练数据),并运行此Jupyter Notebook,通过代码进行操作或[在 Colab 中打开]。例如,您可以按每个 epoch 分析准确率:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file464.jpg
测试
使用为训练保留的数据(测试数据)测试模型,我们得到了大约 76%的准确率。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file465.jpg
检查 F1 分数,我们可以看到对于 YES,我们得到了 0.90,这是一个非常好的结果,因为我们预计将使用这个关键词作为我们 KWS 项目的“触发器”。最差的结果(0.70)是 UNKNOWN,这是可以接受的。
对于 NO,我们得到了 0.72,这是预期的,但为了提高这个结果,我们可以将那些未被正确分类的样本移动到训练数据集中,然后重复训练过程。
实时分类
我们可以继续进行项目的下一步,同时考虑使用 NiclaV 或智能手机捕获实时样本进行实时分类,在将训练模型部署到我们的设备之前进行测试。
部署和推理
EIS 将打包所有需要的库、预处理函数和训练模型,并将它们下载到你的电脑。转到 Deployment 部分,选择 Arduino Library,在底部选择 Quantized (Int8) 并按 Build。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file466.jpg
当选择 Build 按钮时,将创建一个 zip 文件并下载到你的电脑。在你的 Arduino IDE 中,转到 Sketch 选项卡,选择 Add .ZIP Library 选项,并选择由 EIS 下载的.zip 文件:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file467.jpg
现在,是时候进行实际测试了。我们将完全断开与 EIS 的连接进行推理。让我们使用部署 Arduino Library 时创建的 NiclaV 代码示例。
在你的 Arduino IDE 中,转到 File/Examples 选项卡,查找你的项目,并选择 nicla-vision/nicla-vision_microphone(或 nicla-vision_microphone_continuous)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file468.jpg
按下复位按钮两次,将 NiclaV 置于引导模式,将草图上传到你的板子,并测试一些真实的推理:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file469.jpg
后处理
既然我们知道模型正在工作,因为它检测到了我们的关键词,那么让我们修改代码,看看 NiclaV 完全离线(未连接到 PC,由电池、移动电源或独立的 5V 电源供电)的结果。
策略是,每当检测到关键词 YES 时,绿灯将亮起;如果听到 NO,红灯将亮起,如果是 UNKNOWN,蓝灯将亮起;在存在噪声(无关键词)的情况下,LED 将关闭。
我们应该修改其中一个代码示例。现在就让我们用 nicla-vision_microphone_continuous 来做吧。
从初始化 LED 开始:
...
void setup()
{
// Once you finish debugging your code, you can
// comment or delete the Serial part of the code
Serial.begin(115200);
while (!Serial);
Serial.println("Inferencing - Nicla Vision KWS with LEDs");
// Pins for the built-in RGB LEDs on the Arduino NiclaV
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
// Ensure the LEDs are OFF by default.
// Note: The RGB LEDs on the Arduino Nicla Vision
// are ON when the pin is LOW, OFF when HIGH.
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
...
}
创建两个函数,turn_off_leds() 函数,用于关闭所有 RGB LED
/*
* @brief turn_off_leds function - turn-off all RGB LEDs
*/
void turn_off_leds(){
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
}
另一个 turn_on_led() 函数用于根据分类器的最可能结果打开 RGB LED。
/*
* @brief turn_on_leds function used to turn on the RGB LEDs
* @param[in] pred_index
* no: [0] ==> Red ON
* noise: [1] ==> ALL OFF
* unknown: [2] ==> Blue ON
* Yes: [3] ==> Green ON
*/
void turn_on_leds(int pred_index) {
switch (pred_index)
{
case 0:
turn_off_leds();
digitalWrite(LEDR, LOW);
break;
case 1:
turn_off_leds();
break;
case 2:
turn_off_leds();
digitalWrite(LEDB, LOW);
break;
case 3:
turn_off_leds();
digitalWrite(LEDG, LOW);
break;
}
}
并且更改 loop() 中的 // 打印预测 部分的代码:
...
if (++print_results >= (EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) {
// print the predictions
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms.,
Anomaly: %d ms.)",
result.timing.dsp, result.timing.classification,
result.timing.anomaly);
ei_printf(": \n");
int pred_index = 0; // Initialize pred_index
float pred_value = 0; // Initialize pred_value
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
if (result.classification[ix].value > pred_value){
pred_index = ix;
pred_value = result.classification[ix].value;
}
// ei_printf(" %s: ",
// result.classification[ix].label);
// ei_printf_float(result.classification[ix].value);
// ei_printf("\n");
}
ei_printf(" PREDICTION: ==> %s with probability %.2f\n",
result.classification[pred_index].label,
pred_value);
turn_on_leds (pred_index);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(" anomaly score: ");
ei_printf_float(result.anomaly);
ei_printf("\n");
#endif
print_results = 0;
}
}
...
你可以在项目的 GitHub上找到完整的代码。
将草图上传到你的板子上并测试一些真实推理。想法是,当检测到关键词 YES 时,绿色 LED 将亮起,红色 LED 将亮起表示 NO,任何其他单词都将点亮蓝色 LED。如果存在寂静或背景噪音,所有 LED 都应关闭。记住,与我们在介绍中看到的一样,相同的程序可以“触发”外部设备执行所需操作,而不是点亮 LED。
摘要
你可以在 GitHub 仓库中找到本动手教程所使用的笔记本和代码。
在我们结束之前,考虑一下声音分类不仅仅是声音。例如,你可以在多个领域围绕声音开发 TinyML 项目,例如:
-
安全(破碎玻璃检测,枪声)
-
工业(异常检测)
-
医疗(打鼾,咳嗽,肺部疾病)
-
自然(蜂箱控制,昆虫声音,包装缓解)
资源
运动分类和异常检测
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file470.jpg
DALL·E 3 提示:1950 年代风格的卡通插图,描绘一个运动研究室。房间中央有一个用于在卡车、船只和叉车上运输货物的模拟集装箱。集装箱细节丰富,有铆钉和工业货箱典型的标记。集装箱周围,房间内充满了复古设备,包括示波器、各种传感器阵列和大量记录数据的厚纸卷。墙上装饰着关于交通安全和物流的教育海报。整个房间的氛围既怀旧又科学,带有一丝工业风格。
概述
交通运输是全球商业的支柱。每天通过各种方式,如船只、卡车和火车,运输数百万个集装箱到世界各地。确保这些集装箱的安全高效运输是一项艰巨的任务,需要利用现代技术,而 TinyML 无疑是其中之一。
在这个动手教程中,我们将努力解决与交通运输相关的现实世界问题。我们将使用 Arduino Nicla Vision 板、Arduino IDE 和 Edge Impulse Studio 开发运动分类和异常检测系统。这个项目将帮助我们了解集装箱在运输的不同阶段(如陆地和海上运输、通过叉车的垂直运动和仓库中的静止期)所经历的不同力和运动。
学习目标
-
设置 Arduino Nicla Vision 板
-
数据收集和预处理
-
构建运动分类模型
-
实施异常检测
-
现实世界测试和分析
到本教程结束时,你将拥有一个可以分类不同类型运动并在集装箱运输过程中检测异常的工作原型。这些知识可以成为进入蓬勃发展的 TinyML 领域,涉及振动等更高级项目的垫脚石。
IMU 安装和测试
对于这个项目,我们将使用一个加速度计。正如在动手教程“设置 Nicla Vision”中讨论的那样,Nicla Vision 板上有一个板载 6 轴 IMU:3D 加速计和 3D 陀螺仪,LSM6DSOX。让我们验证是否已安装 LSM6DSOX IMU 库。如果没有,请安装它。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file471.jpg
接下来,转到 Examples > Arduino_LSM6DSOX > SimpleAccelerometer 并运行加速度计测试。你可以通过打开 IDE 串行监视器或绘图器来检查它是否工作。值以 g(地球重力)为单位,默认范围为 +/- 4g:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file472.jpg
定义采样频率:
选择合适的采样频率对于捕捉你感兴趣研究的运动特性至关重要。奈奎斯特-香农采样定理指出,采样率应至少是信号中最高频率分量的两倍,以便正确重建。在运输中的运动分类和异常检测的背景下,采样频率的选择将取决于几个因素:
-
运动性质:不同类型的运输(陆地、海事等)可能涉及不同的运动频率范围。更快的运动可能需要更高的采样频率。
-
硬件限制:Arduino Nicla Vision 板及其相关传感器可能对数据采样速度有限制。
-
计算资源:更高的采样率将生成更多数据,这可能会计算密集,特别是在 TinyML 环境中尤为重要。
-
电池寿命:更高的采样率将消耗更多电力。如果系统是电池供电的,这是一个重要的考虑因素。
-
数据存储:更频繁的采样将需要更多的存储空间,这是对内存有限的嵌入式系统来说另一个重要的考虑因素。
在许多人类活动识别任务中,大约 50 Hz 到 100 Hz 的采样率被普遍使用。鉴于我们正在模拟运输场景,这些场景通常不是高频事件,因此在这个范围(50-100 Hz)内的采样率可能是一个合理的起点。
让我们定义一个草图,以便我们可以以定义的采样频率(例如,50 Hz)捕获我们的数据:
/*
* Based on Edge Impulse Data Forwarder Example (Arduino)
- https://docs.edgeimpulse.com/docs/cli-data-forwarder
* Developed by M.Rovai @11May23
*/
/* Include ------------------------------------------- */
#include <Arduino_LSM6DSOX.h>
/* Constant defines ---------------------------------- */
#define CONVERT_G_TO_MS2 9.80665f
#define FREQUENCY_HZ 50
#define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1))
static unsigned long last_interval_ms = 0;
float x, y, z;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
}
void loop() {
if (millis() > last_interval_ms + INTERVAL_MS) {
last_interval_ms = millis();
if (IMU.accelerationAvailable()) {
// Read raw acceleration measurements from the device
IMU.readAcceleration(x, y, z);
// converting to m/s2
float ax_m_s2 = x * CONVERT_G_TO_MS2;
float ay_m_s2 = y * CONVERT_G_TO_MS2;
float az_m_s2 = z * CONVERT_G_TO_MS2;
Serial.print(ax_m_s2);
Serial.print("\t");
Serial.print(ay_m_s2);
Serial.print("\t");
Serial.println(az_m_s2);
}
}
}
上传草图并检查串行监视器,我们可以看到我们每秒捕获 50 个样本。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file473.jpg
注意,当 Nicla 板放在桌子上(摄像头朝下)时,zz-轴测得的值约为 9.8 m/s2²,这是预期的地球加速度。
案例研究:模拟集装箱运输
我们将通过不同的场景模拟集装箱(或更好的包装)运输,使这个教程更具相关性和实用性。使用 Arduino Nicla Vision 板内置的加速度计,我们将通过手动模拟以下条件来捕获运动数据:
-
陆地运输(通过道路或火车)
-
海事相关的运输
-
通过叉车进行垂直移动
-
仓库中的**静止(空闲)**期
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file474.jpg
从上述图像中,我们可以为我们的模拟定义,主要水平运动(xx或yy轴)应与“地面类别”相关联,垂直运动(zz-轴)与“提升类别”相关联,无活动与“空闲类别”相关联,三个轴上的运动到海事类别。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file475.jpg
数据收集
对于数据收集,我们可以有多种选择。在实际情况下,我们可以将我们的设备直接连接到一个容器上,并将收集到的数据存储在文件中(例如.CSV)并存储在 SD 卡上(通过 SPI 连接)或计算机上的离线仓库。数据也可以通过蓝牙(如本项目中的传感器数据记录器)远程发送到附近的仓库,例如手机。一旦您的数据集收集并存储为.CSV 文件,就可以使用CSV 向导工具将其上传到 Studio。
在这个视频中,您可以了解将数据发送到 Edge Impulse Studio 的替代方法。
将设备连接到 Edge Impulse
我们将直接将 Nicla 连接到 Edge Impulse Studio,该 Studio 也将用于数据预处理、模型训练、测试和部署。为此,您有两个选项:
-
下载最新固件并将其直接连接到“数据收集”部分。
-
使用CLI 数据转发器工具从传感器捕获传感器数据并发送到 Studio。
选项 1 更为直接,正如我们在设置 Nicla Vision的动手实践中所看到的,但选项 2 将为您提供更多关于捕获数据的灵活性,例如采样频率定义。让我们使用最后一个选项来做。
请在 Edge Impulse Studio(EIS)上创建一个新的项目,并将 Nicla 连接到它,按照以下步骤操作:
-
在您的计算机上安装Edge Impulse CLI和Node.js。
-
上传用于数据捕获的草图(本教程中之前讨论过的那个)。
-
使用CLI 数据转发器从 Nicla 的加速度计捕获数据并发送到 Studio,如图所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file476.jpg
在您的终端上启动CLI 数据转发器,如果这是第一次使用,请输入以下命令:
$ edge-impulse-data-forwarder --clean
接下来,输入你的 EI 凭据并选择你的项目、变量(例如,accX、accY 和 accZ)以及设备名称(例如,NiclaV):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file477.jpg
前往你的 EI 项目中的设备部分,检查设备是否已连接(点应该是绿色的):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file478.jpg
你可以克隆为这个动手实践开发的工程:NICLA Vision Movement Classification。
数据收集
在数据采集部分,你应该能看到你的板 [NiclaV] 已连接。传感器可用: [具有 3 个轴(accX,accY,accZ)的传感器],采样频率为 [50 Hz]。工作室建议样本长度为 [10000] 毫秒(10 秒)。最后剩下的是定义样本标签。让我们从[terrestrial]开始:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file479.jpg
地面(卡车或火车上的托盘),水平移动。按 [开始采样] 并将你的设备水平移动,保持一个方向在你的桌子上。10 秒后,你的数据将被上传到工作室。以下是样本的收集方式:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file480.jpg
如预期,运动主要被捕捉在YY轴(绿色)。在蓝色中,我们看到ZZ轴,大约在-10 m/s2²(Nicla 的摄像头朝上)。
如前所述,我们应该从所有四个运输类别中收集数据。所以,想象一下你有一个内置加速度计的容器,面对以下情况:
海洋(愤怒海洋中的船上的托盘)。运动在所有三个轴上被捕捉:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file481.jpg
提升(托盘被叉车垂直搬运)。运动仅被捕捉在ZZ轴:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file482.jpg
空闲(仓库中的托盘)。加速度计未检测到运动:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file483.jpg
你可以捕捉,例如,2 分钟(12 个 10 秒的样本)的每个四个类别(总共 8 分钟的数据)。在每个样本之后的三个点菜单中,选择其中 2 个,为测试集保留。或者,你可以在仪表板标签页的危险区域使用自动的训练/测试分割工具。下面,你可以看到生成的数据集:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file484.jpg
一旦你捕获了你的数据集,你可以使用数据探索器来更详细地探索它,这是一个可视化工具,用于查找异常值或错误标记的数据(有助于纠正它们)。数据探索器首先尝试从你的数据中提取有意义的特征(通过应用信号处理和神经网络嵌入),然后使用降维算法,如PCA或t-SNE,将这些特征映射到二维空间。这让你可以一目了然地了解你的整个数据集。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file485.jpg
在我们的案例中,数据集看起来不错(良好的分离)。但 PCA 显示,我们可能在海洋(绿色)和提升(橙色)之间存在问题。这是预期的,一旦在船上,有时运动可能只有“垂直”。
脉冲设计
下一步是定义我们的脉冲,它将原始数据通过信号处理提取特征,然后将这些特征作为学习块的输入张量来对新数据进行分类。前往脉冲设计和创建脉冲。工作室将建议基本设计。让我们也添加一个用于异常检测的第二个学习块。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file486.jpg
这个第二个模型使用 K-means 模型。如果我们想象我们的已知类别可以作为簇,那么任何无法适应这些簇的样本可能是一个异常值,一个异常,比如一个集装箱从海洋中的船上滚落或从叉车掉落。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file487.jpg
采样频率应自动捕获,如果没有,请输入:[50]Hz。工作室建议的窗口大小为 2 秒([2000]毫秒),带有[20]毫秒的滑动窗口。我们在这一步定义的是,我们将预处理捕获的数据(时间序列数据),创建一个表格数据集(特征),这将作为神经网络分类器(DNN)和异常检测模型(K-Means)的输入,如下所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file488.jpg
让我们深入了解这些步骤和参数,以更好地理解我们在这里所做的工作。
数据预处理概述
数据预处理是从加速度计捕获的数据集中提取特征,这涉及到处理和分析原始数据。加速度计测量物体沿一个或多个轴的加速度(通常是三个,表示为XX、YY和ZZ)。这些测量可以用来理解物体的运动的各种方面,如运动模式和振动。
原始加速度计数据可能噪声较大,包含错误或不相关信息。预处理步骤,如滤波和归一化,可以清理和标准化数据,使其更适合特征提取。在我们的案例中,我们应该将数据分成更小的段或窗口。这有助于关注数据集中的特定事件或活动,使特征提取更易于管理和有意义。窗口大小和重叠(窗口增加)的选择取决于应用和感兴趣事件的频率。作为一个经验法则,我们应该尝试捕捉几个“数据周期”。
以 50 Hz 的采样率(SR)和 2 秒的窗口大小,我们将得到每个轴 100 个样本,总共 300 个样本(3 轴 ×\times 2 秒 ×\times 50 个样本)。我们将每 200 毫秒滑动这个窗口,创建一个更大的数据集,其中每个实例都有 300 个原始特性。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file489.jpg
一旦数据经过预处理和分割,你就可以提取描述运动特征的特性。从加速度计数据中提取的一些典型特性包括:
-
时域特性描述了每个段内数据的统计特性,例如均值、中位数、标准差、偏度、峰度和零交叉率。
-
频域特性是通过使用快速傅里叶变换(FFT)等技术将数据转换到频域获得的。一些典型的频域特性包括功率谱、频谱能量、主导频率(幅度和频率)和频谱熵。
-
时频域特性结合了时间和频率域信息,例如短时傅里叶变换(STFT)或离散小波变换(DWT)。它们可以提供对信号频率内容随时间变化的更详细理解。
在许多情况下,提取的特征数量可能很大,这可能导致过拟合或增加计算复杂性。特征选择技术,如互信息、基于相关性的方法或主成分分析(PCA),可以帮助确定给定应用中最相关的特征,并降低数据集的维度。工作室可以帮助进行此类特征重要性计算。
EI Studio 频谱特性
数据预处理是嵌入式机器学习的一个挑战领域,尽管如此,Edge Impulse 通过其数字信号处理(DSP)预处理步骤以及更具体的Spectral Features Block帮助克服了这一挑战。
在 Studio 中,收集到的原始数据集将成为频谱分析模块的输入,这对于分析重复运动,如加速度计数据非常出色。此模块将执行数字信号处理(DSP),提取如快速傅里叶变换或小波等特征。
对于我们的项目,一旦时间信号连续,我们应该使用 FFT,例如长度为[32]。
每个轴/通道的时域统计特征包括:
每个轴/通道的频域特征包括:
-
频谱功率: 16 个特征(FFT 长度/2)
-
偏度: 1 个特征
-
峰度: 1 个特征
因此,对于 32 点的 FFT 长度,频谱分析模块的输出将是每个轴 21 个特征(总共 63 个特征)。
你可以通过下载笔记本Edge Impulse - 频谱特征块分析 TinyML 内部:频谱分析或直接在 Google CoLab 上打开它来了解更多关于每个特征是如何计算的。
生成特征
一旦我们理解了预处理做了什么,就是时候完成工作了。所以,让我们将原始数据(时间序列类型)转换为表格数据。为此,转到参数标签页上的频谱特征部分,定义主要参数(如前所述的[FFT],长度为[32]点),并选择[保存参数]:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file490.jpg
在顶部菜单中,选择生成特征选项和生成特征按钮。每个 2 秒窗口的数据将被转换成一个包含 63 个特征的独立数据点。
特征探索器将使用UMAP在 2D 中显示这些数据。均匀流形近似和投影(UMAP)是一种降维技术,可以用于可视化,类似于 t-SNE,但也适用于一般的非线性降维。
可视化使得验证在特征生成后,现有的类别保持良好的分离成为可能,这表明分类器应该表现良好。可选地,你可以分析每个特征对于某一类别相对于其他类别的重要性。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file491.jpg
模型训练
我们的分类器将是一个密集神经网络(DNN),其输入层将有 63 个神经元,两个隐藏层分别有 20 和 10 个神经元,输出层有四个神经元(每个类别一个),如图所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file492.jpg
作为超参数,我们将使用学习率为[0.005],批大小为[32],数据验证为[20]%,持续[30]个 epoch。训练后,我们可以看到准确率为 98.5%。内存和延迟的成本微乎其微。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file493.jpg
对于异常检测,我们将选择特征提取中精确的最重要特征,再加上 accZ RMS。簇的数量将是[32],正如 Studio 所建议的:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file494.jpg
测试
我们可以使用在数据捕获阶段留下的 20%的数据来验证我们的模型在未知数据上的表现。结果是几乎 95%,这是很好的。您总是可以努力提高结果,例如,了解一个错误结果中出了什么问题。如果是独特的情况,您可以将其添加到训练数据集中,然后重复它。
对于考虑的不确定结果,默认的最小阈值是分类的[0.6]和异常的[0.3]。一旦我们有四个类别(它们的输出总和应为 1.0),您也可以为类别设置一个较低的阈值以被视为有效(例如,0.4)。您可以在三点菜单上设置置信度阈值,除了分类所有按钮。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file495.jpg
您还可以使用您的设备进行实时分类(设备应仍然连接到 Studio)。
请注意,在这里,您将使用您的设备捕获真实数据并将其上传到 Studio,在那里将使用训练好的模型进行推理(但模型不在您的设备上)。
部署
现在是时候将预处理块和训练好的模型部署到 Nicla 上了。Studio 将打包所有需要的库、预处理函数和训练好的模型,并将它们下载到您的电脑上。您应该选择Arduino Library选项,在底部,您可以选择量化(Int8)或未优化(float32),然后点击[构建]。将创建一个 Zip 文件并下载到您的电脑上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file496.jpg
在您的 Arduino IDE 中,转到草图标签,选择添加 ZIP 库,并选择 Studio 下载的.zip 文件。IDE 终端将出现一条消息:库已安装。
推理
现在,是时候进行实际测试了。我们将完全脱离 Studio 进行推理。让我们更改您部署 Arduino Library 时创建的一个代码示例。
在您的 Arduino IDE 中,转到文件/示例标签,找到您的项目,并在示例中选择Nicla_vision_fusion:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file497.jpg
注意,Edge Impulse 创建的代码考虑了一种 传感器融合 方法,其中使用了 IMU(加速度计和陀螺仪)和 ToF。在代码的开头,你有与我们项目相关的库,即 IMU 和 ToF:
/* Includes ---------------------------------------------- */
#include <NICLA_Vision_Movement_Classification_inferencing.h>
#include <Arduino_LSM6DSOX.h> //IMU
#include "VL53L1X.h" // ToF
你可以保持代码这种方式进行测试,因为训练好的模型将只使用来自加速度计的预处理特征。但请考虑,你将只使用真实项目中需要的库来编写代码。
就这样!
你现在可以将代码上传到你的设备,并继续进行推理。按下 Nicla 的 [RESET] 按钮两次以将其置于引导模式(如果仍然连接,请断开与 Studio 的连接),并将草图上传到你的板子。
现在你应该尝试用你的板子(类似于数据捕获期间所做的动作)进行不同的动作,观察每个类别在串行监视器上的推理结果:
- 空闲和提升类别:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file498.jpg
- 海洋和陆地:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file499.jpg
注意,在所有上述情况下,异常分数 的值都小于 0.0。尝试一个新的动作,这个动作不是原始数据集的一部分,例如,“滚动” Nicla,摄像头朝下面对,就像一个从船上掉下来的容器或甚至是一次船只事故:
- 异常检测:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file500.jpg
在这种情况下,异常值要大得多,超过 1.00
后处理
既然我们知道模型正在工作,因为它检测到了动作,我们建议你修改代码,以查看 NiclaV 完全离线(从 PC 断开连接并由电池、移动电源或独立的 5 V 电源供电)的结果。
策略是和 KWS 项目做同样的事情:如果检测到特定的动作,特定的 LED 就会亮起。例如,如果检测到 陆地,绿色 LED 会亮起;如果 海洋,红色 LED 会亮起;如果是 提升,蓝色 LED 会亮起;如果没有检测到动作 (空闲),LED 将会关闭。你还可以添加一个条件,当检测到异常时,例如,可以使用白色(所有 LED 同时亮起)。
摘要
在这个动手教程中使用的笔记本和代码可以在 GitHub 仓库中找到。
在我们结束之前,考虑一下,运动分类和目标检测可以在各个领域的许多应用中被利用。以下是一些潜在的应用:
应用案例
工业和制造
-
预测性维护:在故障发生之前检测机械运动的异常。
-
质量控制:监控装配线或机械臂的运动,以进行精度评估和检测与标准运动模式的偏差。
-
仓储物流:通过分类不同类型的运动并检测处理过程中的异常,使用自动化系统管理和跟踪货物的移动。
医疗保健
-
患者监控:检测老年人或有行动障碍的人的跌倒或异常运动。
-
康复:通过分类物理治疗期间的运动模式来监控受伤患者恢复的进展。
-
活动识别:为健身应用或患者监控分类身体活动类型。
消费电子产品
-
手势控制:通过特定动作来控制设备,例如用手势开关灯。
-
游戏:通过动作控制输入增强游戏体验。
交通运输与物流
-
车辆远程信息处理:监控车辆运动,以检测异常行为,如急刹车、急转弯或事故。
-
货物监控:通过检测可能表明篡改或不当处理的异常运动来确保运输过程中货物的完整性。
智慧城市与基础设施
-
结构健康监控:检测结构内部的振动或运动,这些可能表明潜在的故障或维护需求。
-
交通管理:分析行人或车辆流量,以改善城市移动性和安全性。
安全与监控
-
入侵检测:检测典型的不授权访问或其他安全违规行为的运动模式。
-
野生动物监控:在保护区检测偷猎者或异常动物活动。
农业
-
设备监控:跟踪农业机械的性能和利用率。
-
动物行为分析:监控牲畜运动,以检测表明健康问题或压力的行为。
环境监测
-
地震活动:检测地震或其他地质相关事件之前的不规则运动模式。
-
海洋学:研究波浪模式或海洋运动,用于研究和安全目的。
Nicla 3D 外壳
对于实际应用,正如之前所描述的,我们可以在我们的设备上添加一个外壳,来自 Edge Impulse 的 Eoin Jordan 为 Nicla 系列板开发了出色的可穿戴和机器健康外壳。它使用 10mm 磁铁、2M 螺丝和 16mm 带子,适用于人和机器健康用例场景。以下是链接:Arduino Nicla 语音和视觉可穿戴外壳。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file501.jpg
运动分类和异常检测的应用非常广泛,Arduino Nicla Vision 非常适合低功耗和边缘处理的场景。其小巧的尺寸和高效的处理能力使其成为部署便携式和远程应用的理想选择,在这些应用中,实时处理至关重要,而连接性可能有限。
资源
概述
这些实验室提供了获得机器学习(ML)系统实际操作经验的独特机会。与需要数据中心规模资源的的大型模型工作不同,这些练习使您能够直接使用 TinyML 与硬件和软件进行交互。这种动手方法提供了对部署 AI 挑战和机会的切实理解,尽管是在小规模上。然而,原则在很大程度上与您在处理更大系统时遇到的原则相同。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file502.png
前提条件
-
XIAOML 套件:
-
XIAO ESP32S3 Sense板
-
扩展板,带有 6 轴 IMU 和 0.42 英寸 OLED 显示屏。
-
SD 卡工具包:
-
SD 卡和 USB 适配器用于数据存储
-
用于将板子连接到您的电脑的 USB-C 线缆。
-
-
-
网络:提供互联网访问以下载必要的软件。
设置
- 设置 XIAOML 套件
练习
| 模态 | 任务 | 描述 | 链接 |
| — | — | — | — |
| 视觉 | 图像分类 | 学习对图像进行分类 | 链接 |
| 视觉 | 目标检测 | 实现目标检测 | 链接 |
| 声音 | 关键词检测 | 探索语音识别系统 | 链接 |
| IMU | 运动分类和异常检测 | 对运动数据进行分类并检测异常 | 链接 |
设置
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file503.jpg
DALL·E 提示 - 1950 年代卡通风格的 XIAO ESP32S3 板绘制,具有独特的摄像头模块,如图所示。板子放置在经典的实验室桌子上,周围有各种传感器,包括麦克风。板子后面,一台复古电脑屏幕以柔和的颜色显示 Arduino IDE,代码专注于 LED 引脚设置和语音命令的机器学习推理。IDE 上的串行监视器展示了检测到语音命令“是”和“否”的输出。这个场景将中世纪实验室的复古魅力与现代电子技术相结合。
概述
XIAOML 套件旨在提供 TinyML 应用程序的实际操作体验。套件包括强大的 XIAO ESP32S3 感应器开发板和一个扩展板,该扩展板为机器学习项目添加了必要的传感器。
完整的 XIAOML 套件组件:
-
XIAO ESP32S3 感应器: 主开发板,集成了摄像头传感器、数字麦克风和 SD 卡支持
-
扩展板: 具有六轴 IMU (LSM6DS3TR-C) 和 0.42” OLED 显示屏,用于运动感应和数据可视化
-
SD 卡工具包: 包括 SD 卡和 USB 适配器,用于数据存储和模型部署
-
USB-C 线缆: 用于将板子连接到您的电脑
-
天线和散热片
⚠️ 注意
不要安装(或小心地移除)XIAO ESP32S3 上的散热片,如果您想使用 XIAO ML 套件扩展板。更多信息请见附录。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file504.png
XIAO ESP32S3 感应器 - 核心板特性
XIAO ESP32S3 感应器作为 XIAOML 套件的核心,将嵌入式 ML 计算能力与摄影和音频功能相结合,使其成为智能语音和视觉 AI 中 TinyML 应用的理想平台。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file505.png
主要特性
-
强大的 MCU: ESP32S3 32 位,双核,Xtensa 处理器,最高运行频率 240 MHz,支持 Arduino / MicroPython
-
高级功能: 可拆卸的 OV2640 摄像头传感器,分辨率为 1600 × 1200,兼容 OV5640 摄像头传感器,还集成了数字麦克风
-
详尽的电源设计: 锂电池充电管理,具有四种功耗模式,深度睡眠模式功耗低至 14 μA
-
大容量内存: 8 MB PSRAM 和 8 MB FLASH,支持 SD 卡槽,用于外部 32 GB FAT 内存
-
卓越的射频性能: 2.4 GHz Wi-Fi 和 BLE 双无线通信,支持使用 U.FL 天线进行 100m+ 的远程通信
-
紧凑设计: 21 × 17.5 mm,采用经典的 XIAO 形状,适合空间受限的项目
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file506.png
以下是通用板子引脚图:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file507.png
如需更多详细信息,请参阅 Seeed Studio 维基页面
扩展板功能
扩展板扩展了 XIAOML Kit 在基于运动机器学习应用方面的功能:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file508.png
组件:
-
6 轴 IMU(LSM6DS3TR-C):
-
3 轴加速度计和 3 轴陀螺仪用于运动检测和分类
-
加速度计量程:±2/±4/±8/±16 g
-
陀螺仪量程:±125/±250/±500/±1000/±2000 dps
-
I2C 接口(地址:0x6A)
-
-
-
0.42” OLED 显示屏
-
单色显示屏(72×40 分辨率)用于实时数据可视化
-
控制器:SSD1306
-
I2C 接口(地址:0x3C)
-
-
-
重启按钮(EN)
-
电池连接器(BAT+,BAT-)
完整套件组装
扩展板与 XIAO ESP32S3 Sense 无缝连接,形成一个涵盖视觉、音频和运动传感的多模态机器学习实验的综合平台。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file509.png
请注意模块的安装方向:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file510.png
注意:
-
ESP32S3 Sense 底部显示的
EN连接,通过RST按钮在扩展板上可用。 -
BAT+和BAT-连接也通过BAT3.7V白色连接器提供。
XIAOML Kit 应用:
-
视觉:使用集成摄像头进行图像分类和目标检测
-
音频:使用内置麦克风进行关键词检测和语音识别
-
运动:使用 IMU 传感器进行活动识别和异常检测
-
多模态:用于复杂机器学习应用的组合传感器融合
在 Arduino IDE 上安装 XIAO ESP32S3 Sense
-
通过 USB-C 端口将 XIAOML Kit 连接到您的计算机。https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file511.png
-
根据您的操作系统下载并安装 Arduino IDE 的稳定版本。
-
打开 Arduino IDE 并选择板管理器(由
UNO Icon表示)。 -
输入 “ESP32”,选择 “esp32 by Espressif Systems。” 您可以
安装或更新板支持包。
不要选择 “Arduino ESP32 Boards by Arduino”,这些是 Arduino Nano ESP32 的支持包,而不是我们的板。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file512.png
⚠️ 注意
当使用 XIAO ESP32S3 Sense 与 Edge Impulse 部署代码时,3.x 版本可能会遇到问题。如果是这种情况,请使用最后的 2.0.x 稳定版本(例如,2.0.17)。
- 点击
Select Board,输入 xiao 或 esp32s3,在板管理器中选择XIAO_ESP32S3以及 ESP32S3 连接的相应端口。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file513.png
就这些了!设备应该没问题。让我们进行一些测试。
使用 BLINK 测试板
XIAO ESP32S3 Sense 配备了一个内置 LED,连接到 GPIO21。因此,您可以运行闪烁草图(可以在 Files/Examples/Basics/Blink 下找到。该草图使用 LED_BUILTIN Arduino 常量,它内部对应于连接到引脚 21 的 LED。或者,您可以根据需要更改闪烁草图。)
#define LED_BUILT_IN 21 // This line is optional
void setup() {
pinMode(LED_BUILT_IN, OUTPUT); // Set the pin as output
}
// Remember that the pins work with inverted logic
// LOW to turn on and HIGH to turn off
void loop() {
digitalWrite(LED_BUILT_IN, LOW); //Turn on
delay (1000); //Wait 1 sec
digitalWrite(LED_BUILT_IN, HIGH); //Turn off
delay (1000); //Wait 1 sec
}
注意,引脚使用的是反相逻辑:低电平打开,高电平关闭。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file514.png
麦克风测试
让我们从声音检测开始。使用以下代码或转到GitHub 项目下载草图:XIAOML_Kit_Mic_Test并在 Arduino IDE 上运行它:
/*
XIAO ESP32S3 Simple Mic Test
(for ESP32 Library version 3.0.x and later)
*/
#include <ESP_I2S.h>
I2SClass I2S;
void setup() {
Serial.begin(115200);
while (!Serial) {
}
// setup 42 PDM clock and 41 PDM data pins
I2S.setPinsPdmRx(42, 41);
// start I2S at 16 kHz with 16-bits per sample
if (!I2S.begin(I2S_MODE_PDM_RX,
16000,
I2S_DATA_BIT_WIDTH_16BIT,
I2S_SLOT_MODE_MONO)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
// read a sample
int sample = I2S.read();
if (sample && sample != -1 && sample != 1) {
Serial.println(sample);
}
}
打开串行绘图器,您将看到声音的响度变化曲线。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file515.png
当产生声音时,您可以在串行绘图器中验证它。
将录制的声音(.wav 音频文件)保存到 microSD 卡中。
现在,使用板载 SD 卡读卡器,我们可以保存.wav 音频文件。为此,我们首先需要启用 XIAO PSRAM。
ESP32-S3 在 MCU 芯片上只有几百千字节的内置 RAM。这可能在某些用途上不足,因此可以通过 SPI 闪存芯片连接高达 16MB 的外部 PSRAM(伪静态 RAM)(XIAO 有 8MB 的 PSRAM)。外部内存包含在内存映射中,并在某些限制下可以像内部数据 RAM 一样使用。
- 要打开它,请转到
工具->PSRAM:"OPI PSRAM"->OPI PSRAM
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file516.png
XIAO ESP32S3 Sense 支持高达32GB的 microSD 卡。如果您准备为 XIAO 购买 microSD 卡,请参考以下规格。在使用之前,将 microSD 卡格式化为FAT32 格式。
现在,将格式化为 FAT32 的 SD 卡插入 XIAO,如图下所示
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file517.png
/*
* WAV Recorder for Seeed XIAO ESP32S3 Sense
* (for ESP32 Library version 3.0.x and later)
*/
#include "ESP_I2S.h"
#include "FS.h"
#include "SD.h"
void setup() {
// Create an instance of the I2SClass
I2SClass i2s;
// Create variables to store the audio data
uint8_t *wav_buffer;
size_t wav_size;
// Initialize the serial port
Serial.begin(115200);
while (!Serial) {
delay(10);
}
Serial.println("Initializing I2S bus...");
// Set up the pins used for audio input
i2s.setPinsPdmRx(42, 41);
// start I2S at 16 kHz with 16-bits per sample
if (!i2s.begin(I2S_MODE_PDM_RX,
16000,
I2S_DATA_BIT_WIDTH_16BIT,
I2S_SLOT_MODE_MONO)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
Serial.println("I2S bus initialized.");
Serial.println("Initializing SD card...");
// Set up the pins used for SD card access
if(!SD.begin(21)){
Serial.println("Failed to mount SD Card!");
while (1) ;
}
Serial.println("SD card initialized.");
Serial.println("Recording 20 seconds of audio data...");
// Record 20 seconds of audio data
wav_buffer = i2s.recordWAV(20, &wav_size);
// Create a file on the SD card
File file = SD.open("/arduinor_rec.wav", FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing!");
return;
}
Serial.println("Writing audio data to file...");
// Write the audio data to the file
if (file.write(wav_buffer, wav_size) != wav_size) {
Serial.println("Failed to write audio data to file!");
return;
}
// Close the file
file.close();
Serial.println("Application complete.");
}
void loop() {
delay(1000);
Serial.printf(".");
}
-
将代码保存为例如
Wav_Record.ino,并在 Arduino IDE 中运行它。 -
此程序在用户打开串行监视器(或按下
RESET按钮)后仅执行一次。它记录 20 秒,并将录音文件保存到 microSD 卡上的“arduino_rec.wav”。 -
当串行监视器每秒输出“.”时,程序执行完成,您可以使用卡读卡器播放录制的声音文件。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file518.png
音质极佳!
代码如何工作的解释超出了本实验的范围,但您可以在wiki页面上找到出色的描述。
要了解更多关于 XIAO ESP32S3 Sense 文件系统的信息,请参阅此链接。
测试相机
对于测试(以及使用相机,我们可以使用几种方法:
-
SenseCraft AI Studio
-
Arduino IDE 上的 CameraWebServer 应用程序(参见下一节)
-
捕获图像并将它们保存到 SD 卡上(类似于我们处理音频的方式)
使用 SenseCraft AI Studio 测试相机
查看摄像头工作的最简单方法是使用SenseCraft AI Studio,这是一个强大的平台,提供各种与各种设备兼容的 AI 模型,包括XIAO ESP32S3 Sense和 Grove 视觉 AI V2。
我们还可以使用SenseCraft Web Toolkit,这是 SenseCraft AI Studio 的简化版本。
按照以下步骤开始使用SenseCraft AI:
- 在网页浏览器中打开SenseCraft AI 视觉工作空间,例如Chrome,并登录(或创建账户)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file519.png
- 将 XIAOML 套件物理连接到笔记本电脑,如下选择:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file520.png
注意:WebUSB 工具在某些浏览器中可能无法正常工作,例如 Safari。请使用 Chrome。同时,请确认 Arduino IDE 或任何其他串行设备没有连接到 XIAO。
要查看摄像头是否工作,我们应该上传一个模型。我们可以尝试 Seeed Studio 之前上传的几个计算机视觉模型。使用按钮“[选择模型]”并从可用模型中选择。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file521.png
将鼠标悬停在 AI 模型上,我们可以了解一些关于它们的信息,例如名称、描述、类别或任务(图像分类、目标检测或姿态/关键点检测)、算法(如 YOLO V5 或 V8、FOMO、MobileNet V2 等)以及在某些情况下,指标(准确度或 mAP)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file522.png
我们可以通过点击它并按下[确认]按钮选择一个现成的 AI 模型,例如“人员分类”,或者上传我们自己的模型。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file523.png
在预览区域,我们可以看到摄像头生成的流。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file524.png
我们将在视觉 AI 实验室中更详细地介绍 SenseCraft AI Studio。
测试 WiFi
天线安装
XIAOML 套件已完全组装。首先,将包含摄像头、麦克风和 SD 卡读卡器的 Sense 扩展板从 XIAO 上取下。
在 XIAO ESP32S3 正面左下角有一个独立的“WiFi/BT 天线连接器”。为了提高你的 WiFi/蓝牙信号,请从包装中取出天线并将其连接到连接器。
安装天线有一个小技巧。如果你直接用力按下它,你会发现很难按下,手指会感到疼痛!正确安装天线的方法是先将天线连接器的一侧插入连接块,然后轻轻按下另一侧,以确保天线牢固安装。
取下天线也是如此。不要用力直接拉天线;相反,用力拉起一侧,使天线容易取下。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file525.jpg
重新安装扩展板非常简单;你只需要将扩展板上的连接器与 XIAO ESP32S3 上的 B2B 连接器对齐,用力按下,听到“咔哒”声。安装完成。
XIAO ESP32S3 的一个特点是它的 Wi-Fi 功能。因此,让我们通过扫描其周围的 Wi-Fi 网络来测试其无线电。你可以通过在板上运行代码示例之一来完成此操作。
打开 Arduino IDE 并选择我们的板和端口。转到 Examples,在“XIAO ESP32S3 的示例”下查找 WiFI ==> WiFIScan。将草图上传到板。
你应该在串行监视器中看到你设备范围内的 Wi-Fi 网络(SSID 和 RSSI)。以下是我实验室得到的结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file526.png
简单 Wi-Fi 服务器(打开/关闭 LED)
让我们测试设备作为 Wi-Fi 服务器的功能。我们将在设备上托管一个简单的页面,该页面发送命令来打开和关闭 XIAO 内置 LED。
前往 Examples,在“XIAO ESP32S3 的示例”下查找 WiFI ==> SimpleWiFIServer。
在运行草图之前,你应该输入你的网络凭据:
const char* ssid = "Your credentials here";
const char* password = "Your credentials here";
并且将 引脚 5 修改为 引脚 21,内置 LED 安装在这里。同时,让我们修改网页(第 85 和 86 行)以反映正确的 LED 引脚和它是通过低电平激活的:
client.print("Click <a href=\"/H\">here</a> to turn the LED on pin 21 OFF.<br>");
client.print("Click <a href=\"/L\">here</a> to turn the LED on pin 21 ON.<br>");
你可以使用串行监视器来监控你的服务器性能。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file527.png
将串行监视器中显示的 IP 地址输入到你的浏览器中。你将看到一个带有可以打开和关闭 XIAO 内置 LED 的链接的页面。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file528.png
使用 CameraWebServer
在 Arduino IDE 中,转到 文件 > 示例 > ESP32 > Camera,并选择 CameraWebServer
在 board_config.h 选项卡上,注释掉所有相机模型,除了 XIAO 模型引脚:
#define CAMERA_MODEL_XIAO_ESP32S3 // 有 PSRAM
不要忘记检查
工具以查看是否启用了 PSRAM。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file529.png
如前所述,在 CameraWebServer.ino 选项卡中,输入你的 Wi-Fi 凭据并将代码上传到设备。
如果代码执行正确,你应该在串行监视器中看到地址:
WiFi connecting....
WiFi connected
Camera Ready! Use 'http://192.168.5.60' to connect
将地址复制到你的浏览器中,等待页面加载。选择相机分辨率(例如,QVGA)并选择 [START STREAM]。根据你的连接等待几秒钟。使用 [Save] 按钮,你可以将图像保存到你的电脑下载区。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file530.png
就这样!你可以直接将图像保存到你的电脑上用于项目。
测试 IMU 传感器(LSM6DS3TR-C)
惯性测量单元 (IMU) 是一种测量运动和方向的传感器。你 XIAOML 套件上的 LSM6DS3TR-C 是一个 6 轴 IMU,这意味着它结合了:
-
三轴加速度计:测量沿 X、Y 和 Z 轴的线性加速度(包括重力)
-
三轴陀螺仪:测量围绕 X、Y 和 Z 轴的角速度(旋转速率)
技术规格:
-
通信:地址
0x6A的 I2C 接口 -
加速度计范围: ±2/±4/±8/±16 g(我们默认使用±2g)
-
陀螺仪范围: ±125/±250/±500/±1000/±2000 dps(我们默认使用±250 dps)
-
分辨率: 16 位 ADC
-
功耗: 超低功耗设计
坐标系:
传感器遵循右手坐标系。当从可见点标记的角度观察 IMU 传感器(扩展板底部视图)时:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file531.png
-
X 轴: 指向右侧
-
Y 轴: 指向前方(远离你)
-
Z 轴: 指向上方(出板)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file532.png
必需的库
在上传代码之前,安装所需的库:
-
打开Arduino IDE并选择管理库(由“书籍图标”表示)。
-
对于 IMU 库,输入“*LSM6DS3”并选择“Seeed Arduino LSM6DS3 by Seeed”。您可以“安装”或“更新”板支持包。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file533.png
⚠️ 重要: 不要安装“Arduino_LSM6DS3 by Arduino” - 那是为不同板子准备的!
测试代码
在 Arduino IDE 中输入以下代码并上传到套件:
#include <LSM6DS3.h>
#include <Wire.h>
// Create IMU object using I2C interface
// LSM6DS3TR-C sensor is located at I2C address 0x6A
LSM6DS3 myIMU(I2C_MODE, 0x6A);
// Variables to store sensor readings
float accelX, accelY, accelZ; // Accelerometer values (g-force)
float gyroX, gyroY, gyroZ; // Gyroscope values (degrees per second)
void setup() {
// Initialize serial communication at 115200 baud rate
Serial.begin(115200);
// Wait for serial port to connect (useful for debugging)
while (!Serial) {
delay(10);
}
Serial.println("XIAOML Kit IMU Test");
Serial.println("LSM6DS3TR-C 6-Axis IMU Sensor");
Serial.println("=============================");
// Initialize the IMU sensor
if (myIMU.begin() != 0) {
Serial.println("ERROR: IMU initialization failed!");
Serial.println("Check connections and I2C address");
while(1) {
delay(1000); // Halt execution if IMU fails to initialize
}
} else {
Serial.println("✓ IMU initialized successfully");
Serial.println();
// Print sensor information
Serial.println("Sensor Information:");
Serial.println("- Accelerometer range: ±2g");
Serial.println("- Gyroscope range: ±250 dps");
Serial.println("- Communication: I2C at address 0x6A");
Serial.println();
// Print data format explanation
Serial.println("Data Format:");
Serial.println("AccelX,AccelY,AccelZ,GyroX,GyroY,GyroZ");
Serial.println("Units: g-force (m/s²), degrees/second");
Serial.println();
delay(2000); // Brief pause before starting measurements
}
}
void loop() {
// Read accelerometer data (in g-force units)
accelX = myIMU.readFloatAccelX();
accelY = myIMU.readFloatAccelY();
accelZ = myIMU.readFloatAccelZ();
// Read gyroscope data (in degrees per second)
gyroX = myIMU.readFloatGyroX();
gyroY = myIMU.readFloatGyroY();
gyroZ = myIMU.readFloatGyroZ();
// Print readable format to Serial Monitor
Serial.print("Accelerometer (g): ");
Serial.print("X="); Serial.print(accelX, 3);
Serial.print(" Y="); Serial.print(accelY, 3);
Serial.print(" Z="); Serial.print(accelZ, 3);
Serial.print(" | Gyroscope (°/s): ");
Serial.print("X="); Serial.print(gyroX, 2);
Serial.print(" Y="); Serial.print(gyroY, 2);
Serial.print(" Z="); Serial.print(gyroZ, 2);
Serial.println();
// Print CSV format for Serial Plotter
Serial.println(String(accelX) + "," + String(accelY) + "," +
String(accelZ) + "," + String(gyroX) + "," +
String(gyroY) + "," + String(gyroZ));
// Update rate: 10 Hz (100ms delay)
delay(100);
}
串行监视器将显示值,绘图仪将显示它们随时间的变化。例如,通过在Y 轴上移动套件,我们将看到值 2(红色线条)相应地变化。请注意,Z 轴由值 3(绿色线条)表示,接近 1.0g。蓝色线条(值 1)与X 轴相关。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file534.png
您可以选择 4 到 6 的值来查看陀螺仪的行为。
测试 OLED 显示屏(SSD1306)
OLED(有机发光二极管)显示屏是自发光屏幕,每个像素都产生自己的光。XIAO ML 套件配备了一个紧凑的 0.42 英寸单色 OLED 显示屏,非常适合显示传感器数据、状态信息和简单图形。
技术规格:
-
尺寸: 0.42 英寸对角线
-
分辨率: 72 × 40 像素
-
控制器: SSD1306
-
接口: 地址
0x3C的 I2C -
颜色: 单色(白色背景上的黑色像素,或反之)
-
观看: 高对比度,在明亮的光线下可见
-
电源: 低功耗,无需背光
显示特性:
-
像素完美: 每个 2,880 个像素(72×40)都可以单独控制
-
快速刷新: 适合动画和实时数据
-
无拖影: 瞬时像素响应
-
宽视角: 从多个观看位置清晰可见
必需的库
在上传代码之前,安装所需的库:
-
打开Arduino IDE并选择“管理库”(由“书籍图标”表示)。
-
输入u8g2并选择U8g2 by oliver。您可以“安装”或“更新”板支持包。
ℹ️ 注意: U8g2 是一个强大的图形库,支持许多显示类型
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file535.png
U8g2库是一个单色图形库,具有以下特性:
-
支持许多显示控制器(包括 SSD1306)
-
使用各种字体进行文本渲染
-
绘图原语(线条、矩形、圆形)
-
内存高效的基于页面的渲染
-
硬件和软件 I2C 支持
测试代码
使用以下代码在 Arduino IDE 中输入并上传到套件:
#include <U8g2lib.h>
#include <Wire.h>
// Initialize the OLED display
// SSD1306 controller, 72x40 resolution, I2C interface
U8G2_SSD1306_72X40_ER_1_HW_I2C u8g2(U8G2_R2, U8X8_PIN_NONE);
void setup() {
Serial.begin(115200);
Serial.println("XIAOML Kit - Hello World");
Serial.println("==========================");
// Initialize the display
u8g2.begin();
Serial.println("✓ Display initialized");
Serial.println("Showing Hello World message...");
// Clear the display
u8g2.clearDisplay();
}
void loop() {
// Start drawing sequence
u8g2.firstPage();
do {
// Set font
u8g2.setFont(u8g2_font_ncenB08_tr);
// Display "Hello World" centered
u8g2.setCursor(8, 15);
u8g2.print("Hello");
u8g2.setCursor(12, 30);
u8g2.print("World!");
// Add a simple decoration - draw a frame around the text
u8g2.drawFrame(2, 2, 68, 36);
} while (u8g2.nextPage());
// No delay needed - the display will show continuously
}
如果一切正常,您应该在显示器上看到,“Hello World”在矩形内。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file536.jpg
OLED - 文本大小和定位
-
注意文本是通过
setCursor(x, y)定位的,在这种情况下是居中的:u8g2.setCursor(8, 15); -
代码中使用的字体是中等的。
u8g2.setFont(u8g2_font_ncenB08_tr);但其他字体大小也是可用的:
-
u8g2_font_4x6_tr: 小字体(4×6 像素) -
u8g2_font_6x10_tr: 小字体(6×10 像素) -
u8g2_font_ncenB08_tr: 中等粗体字体 -
u8g2_font_ncenB14_tr: 大号粗体字体
-
形状
代码添加了一个简单的装饰,在文本周围绘制一个框架
u8g2.drawFrame(2, 2, 68, 36);
但其他形状也是可用的:
-
矩形轮廓:
drawFrame(x, y, width, height) -
填充矩形:
drawBox(x, y, width, height) -
圆形:
drawCircle(x, y, radius) -
线条:
drawLine(x1, y1, x2, y2) -
单个像素:
drawPixel(x, y)
坐标
显示器使用一个坐标系,其中:
-
原点(0,0):左上角
-
X 轴:从左到右增加(0 到 71)
-
Y 轴:从上到下增加(0 到 39)
-
文本定位:
setCursor(x, y)其中 y 是文本的基线
显示器旋转
-
您可以通过使用以下方式更改旋转参数:
-
U8G2_R0: 正常方向 -
U8G2_R1: 顺时针 90° -
U8G2_R2: 180°(颠倒) -
U8G2_R3: 顺时针 270°
-
自定义字符:
// Draw custom bitmap
static const unsigned char myBitmap[] = {0x00, 0x3c, 0x42, 0x42, 0x3c, 0x00};
u8g2.drawBitmap(x, y, 1, 6, myBitmap);
文本测量:
int width = u8g2.getStrWidth("Hello"); // Get text width
int height = u8g2.getAscent(); // Get font height
现在 OLED 显示器已准备好显示您的传感器数据、系统状态或为您的机器学习项目设计的任何自定义图形!
摘要
带有 ESP32S3 Sense 的 XIAOML 套件代表了进入 TinyML 和嵌入式机器学习世界的一个强大且易于访问的起点。通过这个设置过程,我们已经系统地测试了 XIAOML 套件的每个组件,确认所有传感器和外设都正常工作。ESP32S3 的双核处理器和 8MB 的 PSRAM 提供了足够的计算能力进行实时机器学习推理,而 OV2640 摄像头、数字麦克风、LSM6DS3TR-C IMU 和 0.42” OLED 显示器创建了一个完整的多模态传感平台。WiFi 连接为边缘到云的机器学习工作流程提供了可能性,我们的 Arduino IDE 开发环境现在已正确配置了所有必要的库。
除了功能测试之外,我们还对每个传感器的坐标系、数据格式和操作特性有了实际的认识——这些知识在设计即将到来的项目中的机器学习数据收集和预处理管道时将非常有价值。
此设置过程展示了远超这个特定套件的关键原则。在 ESP32S3 的内存限制和处理器能力下工作,提供了在边缘 AI 中固有的资源限制的真实体验——这与在智能手机、物联网设备或自主系统中部署模型时面临的考虑相同。在单个平台上拥有多种模式(视觉、音频、运动)使得可以探索多模态机器学习方法,这在现实世界的 AI 应用中越来越重要。
最重要的是,从原始传感器数据到模型推理,再到通过 OLED 显示屏的用户反馈,该套件提供了一个完整的微型 ML 部署周期,反映了生产 AI 系统面临的挑战。
在这个基础已经建立之后,你现在可以应对以下章节中核心 TinyML 应用的核心挑战:
-
视觉项目:利用摄像头进行图像分类和目标检测
-
音频项目:处理音频流以进行关键词检测和语音识别
-
运动项目:使用 IMU 数据用于活动识别和异常检测
每个应用都将建立在我们所建立的硬件理解和软件基础设施之上,展示了人工智能不仅可以在数据中心部署,还可以在直接与物理世界交互的资源受限设备上部署。
在这个套件中遇到的原则——实时处理、传感器融合和边缘推理——是推动自动驾驶汽车、智能城市、医疗设备和工业自动化中 AI 部署未来的相同原则。通过成功完成此设置,你现在准备好探索嵌入式机器学习的这个激动人心的前沿领域。
资源
附录
散热片注意事项
如果您需要在没有扩展板的情况下使用 XIAO ESP32S3 Sense 进行相机应用,您可以安装散热片。
注意,如果安装了散热片,则无法将 XIAO ESP32S3 Sense 与扩展板连接。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file537.jpg
安装散热片
为了确保 XIAO ESP32S3 Sense 的最佳散热,您应在相机应用期间安装提供的散热片。其设计专门针对散热需求,尤其是在相机使用等密集操作期间。
套件中包含两个散热片,但您只能使用一个以确保能够访问电池引脚。
安装:
-
在您开始之前,请确保您的设备已关闭电源并从任何电源插座上拔下。
-
优先覆盖热垫,因为散热片直接位于 ESP32S3 芯片上方,这是热量产生的主要来源。正确的对齐确保了最佳的热量散发,并且保持 BAT 引脚尽可能无阻碍是至关重要的。
现在,让我们开始安装过程:
步骤 1. 准备散热片: 首先,从散热片上移除保护盖,露出热粘合剂。这将使散热片准备好安全地附着到 ESP32S3 芯片上。
步骤 2. 组装散热片:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file538.png
安装后,请确保所有部件都已正确固定,没有短路的风险。请核实散热片是否正确对齐并牢固固定。
如果一个散热片不够,可以安装第二个,共享热垫,但在此情况下,请注意所有引脚都将不可用。
⚠️ 注意
在再次使用 IMU 扩展板之前,请小心移除散热片。
图像分类
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file539.png
DALL·E 提示 - 基于 Marcelo Rovai 的真实图像的 1950 年代风格卡通插图
概述
我们正日益面临一场人工智能(AI)革命,正如 Gartner 所述,边缘 AI 和计算机视觉具有非常高的影响潜力,而且目前确实是如此!
当我们研究应用于视觉的机器学习(ML)时,首先遇到的概念是图像分类,这是一种 ML 的“Hello World”,既简单又深刻!
Seeed Studio XIAOML Kit 提供了一套以XIAO ESP32-S3 Sense为中心的全面硬件解决方案,集成了OV3660摄像头和 SD 卡支持。这些特性使 XIAO ESP32S3 Sense 成为探索 TinyML 视觉 AI 的绝佳起点。
在这个实验室中,我们将使用非代码工具SenseCraft AI探索图像分类,并使用Edge Impulse Studio和Arduino IDE进行更详细的发展。
学习目标
-
使用 SenseCraft AI Studio 部署预训练模型,以实现即时的计算机视觉应用
-
收集和管理图像数据集,以适当的组织方式执行自定义分类任务
-
使用 MobileNet V2 架构通过迁移学习训练自定义图像分类模型
-
通过量化内存高效的预处理优化模型,以适应边缘部署
-
实现后处理管道,包括 GPIO 控制和实时推理集成
-
比较无代码和高级 ML 平台在嵌入式应用中的开发方法
图像分类
图像分类是计算机视觉中的一个基本任务,涉及将整个图像分类到几个预定义类别之一。这个过程包括分析图像的视觉内容,并根据它所描绘的主要对象或场景,从一组固定的类别中分配一个标签。
图像分类在各种应用中至关重要,从组织和搜索数字图书馆和社交媒体平台中的大型图像数据库,到使自主系统理解其周围环境。在显著推进图像分类领域的常见架构包括卷积神经网络(CNNs),如 AlexNet、VGGNet 和 ResNet。这些模型通过学习视觉数据分层表示,在诸如 ImageNet 这样的挑战性数据集上展示了显著的准确性。
作为许多计算机视觉系统的基石,图像分类推动了创新,为更复杂任务如目标检测和图像分割奠定了基础,并促进了跨各个行业对视觉数据的更深入理解。因此,让我们开始探索 人物分类 模型(“人物 - 非人物”),这是一个在 SenseCraft AI 上可用的现成计算机视觉应用。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file540.png
在 SenseCraft AI 工作空间中进行图像分类
首先,通过 USB-C 将 XIAOML Kit(或仅将 XIAO ESP32S3 Sense 从扩展板断开)连接到电脑,然后打开 SenseCraft AI 工作空间 以连接它。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file541.png
连接后,选择 [选择模型...] 选项,并在搜索窗口中输入:“人物分类”。从可用选项中选择在 MobileNet V2 上训练的模型(将鼠标移过模型将打开一个弹出窗口,显示其主要特性)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file542.png
点击选定的模型并确认部署。模型的新固件应开始上传到我们的设备。
注意,将显示已下载的模型百分比和上传的固件。如果没有显示,请尝试断开设备,然后重新连接并按启动按钮。
模型成功上传后,我们可以在预览区域查看 XIAO 摄像头的实时视频流和分类结果(人物 或 非人物),以及 设备日志 中显示的推理细节。
注意,我们还可以选择我们的 推理帧间隔,从“实时”(默认)到 10 秒,以及 模式(UART、I2C 等),因为设备通过这些方式共享数据(默认是通过 USB 的 UART)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file543.png
在设备日志中,我们可以看到模型的前处理延迟为 52 到 78 毫秒,推理大约为 532ms,这将给我们总时间略小于 600ms,即大约 每秒 1.7 帧 (FPS)。
运行 Mobilenet V2 0.35 时,XIAO 的峰值电流为 160mA,在 5.23V 下,导致 功耗为 830mW。
后处理
在图像分类项目管道中,一个重要的步骤是定义我们想要对推理结果做什么。所以,想象一下,我们将使用 XIAO 在检测到人物时自动打开房间灯光。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file544.png
使用 SebseCraft AI,我们可以在 输出 -> GPIO 部分完成这项工作。当满足事件条件时,点击添加图标以触发动作。将打开一个弹出窗口,您可以在其中定义要采取的动作。例如,如果检测到置信度超过 60% 的人,内部 LED 应该打开。在实际场景中,可以使用 GPIO,例如 D0、D1、D2、D11 或 D12 来触发继电器打开灯光。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file545.png
确认后,创建的 触发动作 将会显示。按下 发送 按钮将命令上传到 XIAO。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file546.png
现在,将 XIAO 对准一个人,内部 LED 将会打开。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file547.png
在本实验中,我们将进一步探索更多的触发动作和后处理技术。
图像分类项目
让我们创建一个简单的图像分类项目,使用 SenseCraft AI Studio。下面,我们可以看到一个典型的机器学习流程,它将在我们的项目中使用。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file548.png
在 SenseCraft AI Studio 上:让我们打开 [训练](https://sensecraft.seeed.cc/ai/training) 选项卡:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file549.png
默认情况下,如果有网络摄像头,将训练一个 分类 模型。让我们选择 XIAOESP32S3 Sense。按下绿色按钮 [连接] 将会弹出一个窗口。选择相应的端口并按下蓝色按钮 [连接]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file550.png
从 Grove Vision AI V2 流出的图像将会显示。
目标
第一步,正如我们在机器学习流程中看到的那样,是定义一个目标。让我们想象我们有一个工业安装,它应该能够自动分类轮子和箱子。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file551.png
因此,让我们模拟它,例如,对玩具 箱子 和玩具 轮子 进行分类。我们还应该包括一个第三类图像,背景,其中场景中没有对象。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file552.png
数据收集
让我们创建类别,例如按照字母顺序:
-
第一类:背景
-
第二类:箱子
-
第三类:轮子
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file553.png
选择一个类别,并在预览区域下方的绿色按钮(按住以记录)上持续按下。收集到的图像(及其计数)将出现在图像样本屏幕上。仔细且缓慢地移动相机以捕捉物体的不同角度。要修改位置或干扰图像,释放绿色按钮,重新排列物体,然后再次按住以继续捕获。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file554.png
收集图像后,检查它们并删除任何错误的图像。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file555.png
每个类别收集大约 50 张图像 并进入训练步骤。
注意,可以将收集到的图像下载到其他应用程序中使用,例如 Edge Impulse Studio。
训练
确认是否已选择正确的设备(XIAO ESP32S3 Sense)并按下 [开始训练]
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file556.png
测试
训练完成后,可以预览推理结果。
注意,模型并未在设备上运行。实际上,我们只是在设备上捕获图像,并使用在 Studio 中运行的训练模型进行实时预览。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file557.png
现在是真正将模型部署到设备上的时候了。
部署
在“支持设备”窗口中选择已训练的模型和XIAO ESP32S3 Sense。然后点击 [部署到设备]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file558.png
SenseCraft AI 将带我们到视觉工作区选项卡。确认部署,选择端口,并连接。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file559.png
模型将被烧录到设备中。自动重置后,模型将在设备上开始运行。在设备日志中,我们可以看到推理的延迟约为 426 毫秒,加上预处理大约 110 毫秒,对应于每秒 1.8 帧(FPS)。
此外,请注意,在设置中,可以调整模型的置信度。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file560.png
要运行图像分类模型,XIAO ESP32S3 在 5.23V 下的峰值电流为 14mA,导致功耗为 730mW。
如前所述,在输出 –> GPIO中,我们可以根据检测到的类别打开 GPIO 或内部 LED。例如,当检测到轮子时,LED 将打开。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file561.png
保存模型
可以在 SenseCraft AI Studio 中保存模型。工作室将保留我们所有的模型以供以后部署。为此,返回到“训练”选项卡并选择按钮 [保存到 SenseCraft]:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file562.png
按照说明输入模型的名称、描述、图像和其他详细信息。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file563.png
注意,训练好的模型(一个大小为 320KB 的 Int8 MobileNet V2)可以下载以供进一步使用或分析,例如使用Netron。注意,该模型使用大小为 224x224x3 的图像作为其输入张量。在下一步中,我们将在 Edge Impulse Studio 上使用不同的超参数。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file564.png
此外,模型可以随时再次部署到设备上。自动地,工作区将在 SenseCraft AI 上打开。
从数据集开始的图像分类项目
我们项目的首要目标是训练一个模型并在 XIAO ESP32S3 Sense 上执行推理。为了训练,我们需要找到一些数据 (实际上,是大量的数据!)。
但我们已经知道,首先,我们需要一个目标!我们想要分类什么?
使用 TinyML,由于限制(主要是内存),我们应该将分类限制在三个或四个类别。例如,我们可以训练 SenseCraft AI Studio 中下载的 Box 与 Wheel 捕获的图像。
或者,我们可以使用一个全新的数据集,例如区分苹果、香蕉和土豆或其他类别的数据集。如果可能的话,尝试找到一个包含这些类别图像的特定数据集。Kaggle 水果和蔬菜图像识别是一个不错的起点。
让我们下载上一节中捕获的数据集。在每个捕获的类别上打开菜单(3 个点),然后选择“导出数据”。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file565.png
数据集将以.ZIP 文件的形式下载到计算机上,每个类别一个文件。将它们保存在您的工作文件夹中,并解压缩它们。您应该有三个文件夹,每个文件夹对应一个类别。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file566.png
可选地,您可以使用例如设置实验室中讨论的代码添加一些新的图片。
使用 Edge Impulse Studio 训练模型
我们将使用 Edge Impulse Studio 来训练我们的模型。Edge Impulse是边缘设备上机器学习的主要开发平台。
在 Edge Impulse 输入您的账户凭证(或创建一个免费账户)。接下来,创建一个新的项目:
数据获取
接下来,转到数据获取部分,在那里选择+ 添加数据。将弹出一个弹出窗口。选择上传数据。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file567.png
选择后,将弹出一个新的弹出窗口,要求更新数据。
-
在上传模式中:
选择一个文件夹并按[选择文件]。 -
前往包含一个类别的文件夹,并按
[上传]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file568.png
-
您将自动返回到上传数据窗口。
-
选择“自动在训练和测试之间分割”。
-
在文件夹中输入图片的标签。
-
选择
[上传数据]。 -
在这一点上,文件将开始上传,之后,将出现另一个弹出窗口询问您是否在构建一个目标检测项目。选择
[no]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file569.png
对所有类别重复此过程。不要忘记更改标签的名称。如果您忘记了,并且图像已上传,请注意它们将在工作室中混合。不要担心,您可以在之后手动在类别之间移动数据。
关闭上传数据窗口,返回到数据获取页面。我们可以看到所有数据集都已上传。注意,在上面的面板中,我们可以看到我们有 158 个条目,它们都是平衡的。此外,19%的图像被留作测试。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file570.png
脉冲设计
一个脉冲会提取原始数据(在这种情况下,图像),提取特征(调整图片大小),然后使用学习块对新数据进行分类。
图像分类是深度学习最常见应用,但完成这项任务需要大量的数据。我们每个类别大约有 50 张图像。这个数量足够吗?根本不够!我们需要数千张图像来“教学”或“建模”每个类别,以便我们能够区分它们。然而,我们可以通过使用数千张图像重新训练先前训练的模型来解决这个问题。我们称这种技术为**“迁移学习”(TL)**。使用 TL,我们可以在我们的数据上微调预训练的图像分类模型,即使是在相对较小的图像数据集上也能取得良好的性能。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file571.png
使用 TL,我们可以在我们的数据上微调预训练的图像分类模型,即使是在相对较小的图像数据集(我们的案例)上也能表现出色。
因此,从原始图像开始,我们将它们调整大小为(96×96)(96\times 96)像素,并将它们输入到我们的迁移学习模块。让我们创建一个脉冲。
在这一点上,我们也可以定义我们的目标设备以监控我们的“预算”(内存和延迟)。XIAO ESP32S3 不是 Edge Impulse 的官方支持设备,因此让我们考虑 Espressif ESP-EYE,它相似但速度较慢。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file572.png
保存上述脉冲,然后转到图像部分。
预处理(特征生成)
除了调整图像大小外,我们还可以将它们转换为灰度或保留它们的原始 RGB 颜色深度。让我们在“图像”部分选择 [RGB]。这样做后,每个数据样本将具有 27,648 个特征维度(96x96x3)。按下 [Save Parameters] 将打开一个新标签页,Generate Features。按下 [Generate Features] 按钮以生成特征。
模型设计、训练和测试
在 2007 年,谷歌推出了MobileNetV1。在 2018 年,发布了MobileNetV2: Inverted Residuals and Linear Bottlenecks,然后在 2019 年推出了 V3。MobileNet 是一系列通用计算机视觉神经网络,专门为移动设备设计,以支持分类、检测和其他应用。MobileNets 是小型、低延迟、低功耗的模型,参数化以满足各种用例的资源限制。
尽管基础 MobileNet 架构已经非常紧凑且具有低延迟,但特定的用例或应用可能经常需要模型更小、更快。MobileNets 引入了一个简单的参数,α(alpha),称为宽度乘数,以构建这些更小、计算成本更低的模型。宽度乘数α的作用是在每一层均匀地瘦化网络。
Edge Impulse Studio 提供了 MobileNet V1(96x96 图像)和 V2(96x96 和 160x160 图像),以及几个不同的α值(从 0.05 到 1.0)。例如,使用 V2,160x160 图像,α=1.0 时,你将获得最高的准确率。当然,这里有一个权衡。准确率越高,运行模型所需的内存(大约 1.3M RAM 和 2.6M ROM)就越多,这意味着更大的延迟。在另一个极端,使用 MobileNet V1 和α=0.10 时,将获得更小的占用空间(大约 53.2K RAM 和 101K ROM)。
我们将使用MobileNet V2 0.35作为我们的基础模型(但也可以使用具有更大α值的模型)。我们的模型最终层,在输出层之前,将有 16 个神经元,并具有 10%的 dropout 率以防止过拟合。
与深度学习一起使用的另一个必要技术是数据增强。数据增强是一种可以通过创建额外的合成数据来帮助提高机器学习模型准确率的方法。数据增强系统在训练过程中对训练数据进行小的、随机的更改(例如翻转、裁剪或旋转图像)。
在幕后,你可以看到 Edge Impulse 是如何在数据上实现数据增强策略的:
# Implements the data augmentation policy
def augment_image(image, label):
# Flips the image randomly
image = tf.image.random_flip_left_right(image)
# Increase the image size, then randomly crop it down to
# the original dimensions
resize_factor = random.uniform(1, 1.2)
new_height = math.floor(resize_factor * INPUT_SHAPE[0])
new_width = math.floor(resize_factor * INPUT_SHAPE[1])
image = tf.image.resize_with_crop_or_pad(image, new_height,
new_width)
image = tf.image.random_crop(image, size=INPUT_SHAPE)
# Vary the brightness of the image
image = tf.image.random_brightness(image, max_delta=0.2)
return image, label
现在,让我们定义超参数:
-
迭代次数:20
-
批处理大小:32
193



被折叠的 条评论
为什么被折叠?



