在这个项目中,我将展示一种开始使用 TinyML 的简单方法:在Arduino板上实现机器学习模型,同时创建一些很酷的东西:基于加速度计的手势识别系统。
为了使实验更简单,该系统设计为仅识别两种手势:出拳和弯曲动作(在数据科学领域,二元分类)。
这个实验的最大挑战是试图在一个非常小的设备上运行预测模型:一个 8 位微控制器。为此,您可以使用Neuton。
Neuton是一个 TinyML 框架。它允许在没有任何编码和一点机器学习经验的情况下自动构建神经网络,并将它们嵌入到小型计算设备中。它支持8位、16位和32 位微控制器。
实验分为三个步骤:
手势识别系统由以下部分组成:
GY-521 由Arduino Mega 电源部分的5V和GND引脚供电,而对于数据通信,则使用I2C引脚(引脚 20 和引脚 21)。其余引脚是可选的,对于此应用无用。
要验证 GY-521 模块是否正确供电,请连接Arduino板的 USB 电缆并检查安装在传感器板上的 LED 是否亮起。
验证传感器电源后,通过下载Adafruit MPU6050 Arduino 库并打开“绘图仪”示例检查I2C通信是否正常工作。
将示例草图上传到Arduino板上,打开Tools菜单中的“ Serial Plotter ” ,在baud下拉菜单中设置115200 ,然后“摇动”sensor板。预期结果如下:
现在,系统已准备好收集加速度计和陀螺仪数据。
构建预测模型的第一步是收集足够的运动测量值。这组测量值称为训练数据集,它将用于训练Neuton神经网络构建器。
实现这一点的最简单方法是通过捕获加速度和陀螺仪测量并将结果存储在文件中来重复多次相同的两个动作(冲压和弯曲)。为此,您创建一个专用于传感器数据采集的Arduino草图。该程序将获取每个运动的测量值,并将在串行端口控制台上打印传感器测量值输出。
您将执行至少 60 个动作:第一个动作 ( punch ) 30 个,第二个动作 ( flex ) 30 个。对于每个动作,您将在 1 秒的时间窗口内获得 50 个加速度和 50 个陀螺仪测量值(采样时间:20ms —50Hz )。在这个实验中,60 个动作就足够了。通过增加运动测量的数量,您可以提高模型的预测能力。但是,大型数据集可能会导致模型过拟合。没有“正确”的数据集大小,但建议采用“反复试验”的方法。
Arduino草图的串行端口输出将根据Neutontraining 数据集要求进行格式化。
下面,用于创建数据集的Arduino程序:
#define NUM_SAMPLES 50
Adafruit_MPU6050 mpu;
void setup() {
// init serial port
Serial.begin(115200);
while (!Serial) {
delay(10);
}
// init IMU sensor
if (!mpu.begin()) {
while (1) {
delay(10);
}
}
// configure IMU sensor
// [...]
// print the CSV header (ax0,ay0,az0,...,gx49,gy49,gz49,target)
for (int i=0; i
Serial.print("aX");
Serial.print(i);
Serial.print(",aY");
Serial.print(i);
Serial.print(",aZ");
Serial.print(i);
Serial.print(",gX");
Serial.print(i);
Serial.print(",gY");
Serial.print(i);
Serial.print(",gZ");
Serial.print(i);
Serial.print(",");
}
Serial.println("target");
}
#define NUM_GESTURES 30
#define GESTURE_0 0
#define GESTURE_1 1
#define GESTURE_TARGET GESTURE_0
//#define GESTURE_TARGET GESTURE_1
void loop() {
sensors_event_t a, g, temp;
while(gesturesRead < NUM_GESTURES) {
// wait for significant motion
while (samplesRead == NUM_SAMPLES) {
// read the acceleration data
mpu.getEvent(&a, &g, &temp);
// sum up the absolutes
float aSum = fabs(a.acceleration.x) +
fabs(a.acceleration.y) +
fabs(a.acceleration.z);
// check if it's above the threshold
if (aSum >= ACC_THRESHOLD) {
// reset the sample read count
samplesRead = 0;
break;
}
}
// read samples of the detected motion
while (samplesRead < NUM_SAMPLES) {
// read the acceleration and gyroscope data
mpu.getEvent(&a, &g, &temp);
samplesRead++;
// print the sensor data in CSV format
Serial.print(a.acceleration.x, 3);
Serial.print(',');
Serial.print(a.acceleration.y, 3);
Serial.print(',');
Serial.print(a.acceleration.z, 3);
Serial.print(',');
Serial.print(g.gyro.x, 3);
Serial.print(',');
Serial.print(g.gyro.y, 3);
Serial.print(',');
Serial.print(g.gyro.z, 3);
Serial.print(',');
// print target at the end of samples acquisition
if (samplesRead == NUM_SAMPLES) {
Serial.println(GESTURE_TARGET);
}
delay(10);
}
gesturesRead++;
}
}
首先,在打开串行监视器并将GESTURE_TARGET设置为GESTURE_0的情况下运行上述草图。然后,将GESTURE_TARGET设置为GESTURE_1运行。对于每次执行,执行相同的动作 30 次,尽可能确保以相同的方式执行动作。
将两个运动的串行监视器输出复制到一个文本文件中,并将其重命名为“trainingdata.txt”。.csv ”。
Neuton自动执行训练,无需任何用户交互。使用Neuton训练神经网络既快速又简单,分为三个阶段:
现在,让我们进入训练的核心!
训练过程完成后,您将被重定向到«预测»部分。在本次实验中,模型的准确率达到了98% 。这意味着从 100 条预测记录中,有 98 条被分配到了正确的类别……这令人印象深刻!
此外,要嵌入的模型大小小于3KB 。这是一个非常小的尺寸,考虑到使用的Arduino板的内存大小为256KB ,而 8 位微控制器的典型内存大小为64KB÷256KB 。
要下载模型存档,请单击“下载”按钮。
从Neuton下载的模型存档包括以下文件和文件夹:
首先,修改user_app.c文件,添加函数以初始化模型并运行推理。
/*
* Function: model_init
* ----------------------------
*
* returns: result of initialization (bool)
*/
uint8_t model_init() {
uint8_t res;
res = CalculatorInit(&neuralNet, NULL);
return (ERR_NO_ERROR == res);
}
/*
* Function: model_run_inference
* ----------------------------
*
* sample: input array to make prediction
* size_in: size of input array
* size_out: size of result array
*
* returns: result of prediction
*/
float* model_run_inference(float* sample,
uint32_t size_in,
uint32_t *size_out) {
if (!sample || !size_out)
return NULL;
if (size_in != neuralNet.inputsDim)
return NULL;
*size_out = neuralNet.outputsDim;
return CalculatorRunInference(&neuralNet, sample);
}
之后,您创建user_app.h头文件以允许主应用程序使用用户函数。
uint8_t model_init();
float* model_run_inference(float* sample,
uint32_t size_in,
uint32_t* size_out);
下面是主要应用程序的Arduino草图:
#include "src/Gesture Recognition_v1/user_app.h"
void setup() {
// init serial port and IMU sensor
// [...]
// init Neuton neural network model
if (!model_init()) {
Serial.print("Failed to initialize Neuton model!");
while (1) {
delay(10);
}
}
}
#define GESTURE_ARRAY_SIZE (6*NUM_SAMPLES+1)
void loop() {
sensors_event_t a, g, temp;
float gestureArray[GESTURE_ARRAY_SIZE] = {0};
// wait for significant motion
// [...]
// read samples of the detected motion
while (samplesRead < NUM_SAMPLES) {
// read the acceleration and gyroscope data
mpu.getEvent(&a, &g, &temp);
// fill gesture array (model input)
gestureArray[samplesRead*6 + 0] = a.acceleration.x;
gestureArray[samplesRead*6 + 1] = a.acceleration.y;
gestureArray[samplesRead*6 + 2] = a.acceleration.z;
gestureArray[samplesRead*6 + 3] = g.gyro.x;
gestureArray[samplesRead*6 + 4] = g.gyro.y;
gestureArray[samplesRead*6 + 5] = g.gyro.z;
samplesRead++;
delay(10);
// check the end of gesture acquisition
if (samplesRead == NUM_SAMPLES) {
uint32_t size_out = 0;
// run model inference
float* result = model_run_inference(gestureArray,
GESTURE_ARRAY_SIZE,
&size_out);
// check if model inference result is valid
if (result && size_out) {
// check if problem is binary classification
if (size_out >= 2) {
// check if one of the result has >50% of accuracy
if (result[0] > 0.5) {
Serial.print("Detected gesture: 0");
// [...]
} else if (result[1] > 0.5) {
Serial.print("Detected gesture: 1");
// [...]
} else {
// solution is not reliable
Serial.println("Detected gesture: NONE");
}
}
}
}
}
}
/neuton_gesturerecognition
|- /src
| |- /Gesture Recognition_v1
| |- /model
| |- /neuton
| |- user_app.c
| |- user_app.h
|- neuton_gesturerecognition.ino
现在,是时候看看预测模型的实际应用了!
对于每个检测到的运动,模型将尝试猜测运动是什么类型(0 -punch或 1 -flex )以及预测的准确度。如果预测的准确度较低(0.5 ),则模型不会做出决定。
下面是模型推理执行的示例:
而且..仅此而已!
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !