win8式网站后台模板,摄影旅游网站源码,网站asp木马删除,网站布局优化怎么做IDE#xff1a; CLion
MCU#xff1a; STM32F407VET6 一、导向 以求知为导向#xff0c;从问题到寻求问题解决的方法#xff0c;以兴趣驱动学习。 虽从0#xff0c;但不到1#xff0c;剩下的那一小步将由你迈出。本篇主要目的是体验完整的一次简单AI模型部署流程#x…IDE CLion
MCU STM32F407VET6 一、导向 以求知为导向从问题到寻求问题解决的方法以兴趣驱动学习。 虽从0但不到1剩下的那一小步将由你迈出。本篇主要目的是体验完整的一次简单AI模型部署流程从数据采集到模型创建与训练再到部署单片机上。选定的训练方向也非常简单既不是手势识别、语音识别等这些较为复杂的模型也不是使用一些第三方的预训练模型而是简简单单地“调包”搭建一个判断输入数字大小的小模型比如在判断输入数据是否小于24。最终生成的C代码其内存、存储占用均为10KB也可缩减至不到1KB 既然是“从零开始”那么就不需要介绍太多复杂的术语解释但一些基本的概念还是需要了解的。该篇最主要的目的就是体验不需要知道太多为什么真正上手实践后再自行学习。 此处所指的单片机是STM32系列stm32f407vet6 二、流程
1STM32CubeMX的AI插件 想要触碰一个未曾熟知的领域最重要的是要搜集信息了解要干什么、怎么干然后简单体验一番。那么第一步来了我们的问题很简单stm32单片机上怎么跑AI。带着这个问题我们使用搜索引擎可以得到一些博客什么模型搭建、部署什么的可能也听不大懂。 但从这些博客里我们可以找到一个共同点那就是都使用到了STM32CubeMX虽然AI模型相关的不太懂但这个工具软件可太熟了。 从这里我们可以获取另一个关键点就目前所获取的信息来看stm32单片机上跑AI应是依赖STM32CubeMX的AI插件的。至于怎么配置这个AI插件相关的博客有很多 2AI模型 当你兴冲冲地使用CubeMX上的AI插件时你可能会发现缺少一件东西——AI模型 回想到前面回答中通义通义千问说过导入模型 虽然网上相关博客有不少什么手势识别、神经网络算法等等但几乎没有几个是直接给你一个AI模型的要么是到官网的github上找要么是什么云盘。总之对于初学者而言是有一些麻烦的 接下来继续发挥“不会就问”的精神 通义给了我们四个方案但无论是官方给的还是用什么第三方的亦或者使用预训练模型的总之都是有一些难度的。四种方案你可以逐一尝试尝试下来后你可能会发现预训练、官方模型库、第三方库这些方案太难了因为涉及到大量陌生知识。 自己训练模型看着比较可行因为从下面可以看到自己训练一个简单模型就两步收集数据和python编程来训练模型。无论是收集数据还是编程似乎都是非常清晰的过程。 当然上面的结论也是问出来的。当通义给你一个问题的回答而你对其中的一些概念又含混不清的时候你可以把自己的猜测反问给通义且不必担心通义出言不逊。 反问后无论你的猜测是否正确你最终都会被指导一个正确的方向。 既然确定了步骤不妨问问更细节的一些东西这里需要自行提问下面提供一个简单的示例 3数据采集 前面说过既然是初学者那么一切从简怎么简单怎么来。这里先说一个前置信息AI模型训练需要的数据集一般是保存在.csv文件里的打开后你会发现这跟Excel表格大差不差。 使用记事本打开后你会发现头部会有一些标签数据是按照列来排布的 左边那一列是输入的数据右边那一列是输出的结果当然也可以称为类别 训练AI模型时会用你收集到的这个数据集训练以图中这个数据为例二分类问题给它左边的输入数据让AI模型输出然后与数据集中的右边的输出对比来判断AI预测的结果之后AI再不断调整权重、参数什么的让预测更加精准。 这些前置信息你自己也是可以收集的。这里我们是需要一个数据集来帮我们训练也知道数据集长成什么样子。从一些博客或者AI我们可以了解到一般的数据集都是什么图像相关的什么矩阵、像素、灰度之类的那显然还是有些难度的。 所以接下来我们讨论更简单的情况就是给AI一个数据让它判断是不是小于一个数小于就输出1大于就输出0。是不是简单很多了 4、训练模型 我们首先要清楚STM32上跑的这个AI模型其实是神经网络模型它们之间的关系是这样的 AI人工智能 机器学习 深度学习 神经网络模型非传统神经网络 总之经过一系列问询之后我们可以选择Keras 和TensorFlow Lite。这是一个神经网络框架不要害怕陌生的术语名称它只是用于训练AI的工具你也可以理解为库或包。 这里我补充一点就是STM32CubeMX其实对Keras的支持其实并不算好我们后续真正使用的是后者。 三、采集数据 正如前面所言为了简单体验这个流程我们就以那个判断数字是否小于某个数为训练目的。当体验过这个简单流程后你可以放飞自我去训练了。 这里不说怎么安装Pycharm什么的因为这是最基本的能力。 现在我们把训练目的具体化在0-100内判断出这个数据是否小于24。那么我们就需要生成这样的数据为了保真还得让数据随机起来且小于24的和大于24的概率还不同以增加些许难度。 这个数据可以使用python生成那么怎么写python脚本呢从变量命名、标识符开始学一遍python那是大可不必的不需要掌握python因为你至少已掌握了C语言只需要知道怎么让通义生成正确的代码就行了 通义生成的代码不一定可用你把报错信息或者调试信息给它提供给它需求让它不断更新代码直至生成可用的代码。这里不展开细节了下面就是可用的python代码如果你是新安装的pycharm那么可能会提示安装一些库安装软件包的过程可能会有些漫长这都是正常现象。有时间了可以自行查资料解决 import numpy as np
import pandas as pd# 参数设置
filename simulated_data.csv
num_points 100000
threshold 24 # 触发阈值
low_value_frequency 0.33 # 低于24的值的概率# 生成数据
np.random.seed(0)
data np.random.randint(0, 101, num_points) # 生成0到100的整型数据# 生成低于24的值
low_values np.random.binomial(1, low_value_frequency, num_points)
data[low_values 1] np.random.randint(0, 24, np.sum(low_values))# 标记是否触发阈值
labels (data threshold).astype(int)# 创建DataFrame
df pd.DataFrame({value: data, label: labels})# 保存到CSV文件
df.to_csv(filename, indexFalse)print(f数据已生成并保存到 {filename}) 正确执行完后当前目录下就会有一个simulated_data.csv文件。 四、训练模型 虽然听着不明觉厉其实这里我们只用非常简单有限的步骤因为框架已经帮我们做好了绝大部分工作了。 问询你可以描述得更加具体 总之多次让AI改进后可以得到了一份可以训练刚才数据的代码 import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from keras.src.callbacks import ModelCheckpoint
from keras.src.layers import GRU
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import save_model
import tensorflow as tf
import subprocess# 数据加载
df pd.read_csv(simulated_data.csv)
X df[value].values.reshape(-1, 1) # 特征值需要reshape为2D数组
y df[label].values# 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42)# 创建模型
model Sequential([Dense(10, input_shape(1,), activationrelu), # 输入层同时也是隐藏层# Dense(1, activationsigmoid) # 输出层# GRU(16, input_shape(1, 1), return_sequencesFalse), # 添加GRU层32个单元输入形状为 (1, 1)不返回序列Dense(18, activationrelu), # 添加一个全连接层32个神经元使用ReLU激活函数Dense(1, activationsigmoid) # 添加全连接层输出1个节点使用sigmoid激活函数
])# 编译模型
model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy])# 设置 ModelCheckpoint 回调函数
checkpoint ModelCheckpoint(best_model.keras, monitorval_accuracy, save_best_onlyTrue, modemax)# 训练模型
history model.fit(X_train, y_train, validation_data(X_test, y_test), epochs78, batch_size60)# 绘制训练过程中的损失
plt.figure(figsize(12, 6))
plt.plot(history.history[loss], labelTraining Loss)
plt.plot(history.history[val_loss], labelValidation Loss)
plt.title(Model Loss)
plt.xlabel(Epochs)
plt.ylabel(Loss)
plt.legend()
plt.show()# 绘制训练过程中的准确率
plt.figure(figsize(12, 6))
plt.plot(history.history[accuracy], labelTraining Accuracy)
plt.plot(history.history[val_accuracy], labelValidation Accuracy)
plt.title(Model Accuracy)
plt.xlabel(Epochs)
plt.ylabel(Accuracy)
plt.legend()
plt.show()# 模型保存
save_model(model, model/stm32_model.keras)
# 将 .keras 模型转换为 .tflite 格式
converter tf.lite.TFLiteConverter.from_keras_model(model)# # 使用 Select TF Ops虽然允许把Keras转为TFLite模型但是CubeMX的AI插件不支持
# converter.target_spec.supported_ops [
# tf.lite.OpsSet.TFLITE_BUILTINS, # 支持 TFLite 内置操作
# tf.lite.OpsSet.SELECT_TF_OPS # 支持 TensorFlow 原生操作
# ]
# # 禁用实验性降低张量列表操作
# converter._experimental_lower_tensor_list_ops Falsetflite_model converter.convert()# 保存 TFLite 模型
with open(model/stm32_model.tflite, wb) as f:f.write(tflite_model)
print(TFLite 模型已保存)# # 下面出了问题
# # 加载最佳模型
# best_model tf.keras.models.load_model(best_model.keras)
#
# # 保存最佳模型
# save_model(best_model, model/stm32_best_model.keras)
#
# # 将 .keras 模型转换为 .tflite 格式
# # 转换模型
# tflite_model converter.convert()
#
# # 保存 TFLite 模型
# with open(model/stm32_best_model.tflite, wb) as f:
# f.write(tflite_model)
#
# print(TFLite best模型已保存)这个代码即便你安装了所有软件包可能还会报错这都是正常现象可以不用管它 训练模型这一步步骤非常清晰明了 ①加载数据 ②创建模型 这里面可以看到三个函数也就是三层神经网络你想要增加就再添加一个函数即可。只不过经过我的测试和官方文档说明无法使用更加复杂的层比如GRU层陌生术语稍微过一下就行暂时可以不必深究 ③编译模型 回调函数先不用管它可加可不加 ④训练模型 这里只要注意这两个参数即可一个是epochs另一个是batch_size。前者是训练轮数后者是每批次训练的数据量 ⑤评估模型 这里其实就是图形化显示训练的结果什么准确率、损失什么的 ⑥保存模型 这里可以看到一开始模型格式为.keras后面就编程了.tflite。原因就是前者格式STM32CubeMX的AI插件经常无法正常加载报一些奇奇怪怪的错。 既然这样我们看看运行之后是什么样子的 如果这是你的第一个AI模型成就感满满了不是 右边的第二张图还有一张在小窗口里可以看到随着训练轮次增加准确率也逐渐增加 我们单看某一次的可以发现正确率已经达到0.9988了因为问题比较简单嘛。有时会达到1.00 五、部署推理 既然模型已经训练完毕接下来我们就可以在本地部署然后进行推理看看效果怎么样。加载训练好的模型然后输入数据看看AI的输出是什么样的 不过在此之前我们还要生成100个模拟数据当做实际中的数据用于验证模型的推理效果。 import numpy as np
import pandas as pd# 参数设置
filename simulated_data1.csv
num_points 100
threshold 24 # 触发阈值
low_value_frequency 0.33 # 低于24的值的概率# 生成数据
np.random.seed(0)
data np.random.randint(0, 101, num_points) # 生成0到100的整型数据# 生成低于24的值
low_values np.random.binomial(1, low_value_frequency, num_points)
data[low_values 1] np.random.randint(0, 24, np.sum(low_values))# 标记是否触发阈值
labels (data threshold).astype(int)# 创建DataFrame
df pd.DataFrame({value: data, label: labels})# 保存到CSV文件
df.to_csv(filename, indexFalse)print(f数据已生成并保存到 {filename})然后就是推理预测了 import numpy as np
from tensorflow.keras.models import load_model
import pandas as pd
import matplotlib.pyplot as plt# 设置 matplotlib 使用的字体
plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签
plt.rcParams[axes.unicode_minus] False # 用来正常显示负号# 加载模型
model load_model(model/stm32_model.keras)# 加载验证数据集
df pd.read_csv(simulated_data1.csv)
X_test df[value].values.reshape(-1, 1, 1)
y_test df[label].values# 进行推理
predictions model.predict(X_test)
predicted_labels (predictions 0.5).astype(int)# 输出详细结果
for i, value in enumerate(df[value]):print(f输入数据: {value:.2f}, 预测结果: {predicted_labels[i][0]}, 实际标签: {y_test[i]})# 计算准确率
accuracy np.mean(predicted_labels.squeeze() y_test)
print(f模型准确率: {accuracy * 100:.2f}%)# 可视化预测结果和真实标签的对比
plt.figure(figsize(12, 6))
plt.plot(y_test, label真实标签, markero)
plt.plot(predicted_labels.squeeze(), label预测结果, markerx)
plt.title(真实标签 vs 预测结果)
plt.xlabel(样本索引)
plt.ylabel(标签)
plt.legend()
plt.show()我们可以看到推理后的结果这根本就难不倒它嘛 六、加载模型 既然前面已经把模型训练了出来接下来就可以把模型部署到单片机上了。下面先介绍一些分析模型时的问题 遇到这个提示后 在注册表编辑器中找到路径 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem。 修改或添加 LongPathsEnabled 值 在 FileSystem 文件夹中查找名为 LongPathsEnabled 的DWORD (32-bit) 值。如果存在双击它并将其值设置为 1。如果不存在右键点击 FileSystem 文件夹选择 新建 - DWORD (32-bit) 值命名为 LongPathsEnabled然后将其值设置为 1。然后重启 发生下面这个问题比较奇葩虽然提示说我们引入了batch_shape但实际上我们没有显式引用。但只要把模型转为TFLite格式同时不能直接使用GRU等高级层。 即便……你使用Select TF Ops虽然可以转为TFLite模型但是Cube的AI插件不能转换
# 模型保存
save_model(model, model/stm32_model.keras)
# 将 .keras 模型转换为 .tflite 格式
converter tf.lite.TFLiteConverter.from_keras_model(model)
# 使用 Select TF Ops
converter.target_spec.supported_ops [tf.lite.OpsSet.TFLITE_BUILTINS, # 支持 TFLite 内置操作tf.lite.OpsSet.SELECT_TF_OPS # 支持 TensorFlow 原生操作
]# 禁用实验性降低张量列表操作
converter._experimental_lower_tensor_list_ops False
tflite_model converter.convert() 每次加载模型都要重新分析一遍 1生成C代码 ①添加AI插件 这一步有太多博客介绍了我就说一点把下面那个Device也勾选上选择最后一个应用模板即可。官方文档里也很详细 ②添加模型 ③分析模型 点击分析即可分析成功后应如下 我们可以看到最后一句由于前面训练模型时也是这样输入和输出只有一个这里输入和输出也是一个4字节实际为float32 如果你想要知道模型的详细情况可以选择这个选项当然这都是后面了可以自己尝试 ④生成的文件 生成的模型代码就是这个文件夹了 以及Middlewares下面的这个AI库 2移植库 如果你移植很熟练的话这一步也没什么难度。不过要说明的是我的工程是cmake工程移动文件后只需要修改CMakelists就行了。如果是Keil或者IAR的话需要手动图形化添加。 不管是哪种目的都一样先把官方提供的AI库是整个AI目录而不仅仅是Lib目录添加到工程里就是下面这个静态库.a 在CMakelists里就是这样前面是什么不重要重要的是这个库前面要加上“:”为什么呢我从CubeMX生成工程的CMakelists里扒出来的就是这样疑惑的话可以多问问通义等 target_link_libraries(libai INTERFACE :NetworkRuntime910_CM4_GCC.a)
target_link_libraries(libai PRIVATE libdrivers) 移植后这个库的头文件也要包含进来ST/AI/Inc 然后是这个X-CUBE-AI具体过程我不描述了移植需要多尝试、去练讲求的是经验 总之就两个东西一个是官方的库另一个是资源文件 3使用 前面选择软件包时由于勾选了应用模板所以会给我们生成。这些文件中我们只要考虑这两个文件即可 从这个头文件里可以看到它提供了两个接口一个是初始化另一个是AI处理。 到资源文件中我们可以看到这两个函数是空的我们先补充初始化函数直接这样添加就行了不用管什么错误判断因为实际上这个ai_boostrap接口就已经做好了 void MX_X_CUBE_AI_Init(void)
{ai_boostrap(data_activations0);
}至于函数处理我们可以不用void MX_X_CUBE_AI_Process(void); 我们自己编写一个简单的接口输入数据然后返回数据。为什么前面要加上float强制转换呢因为这个指针类型其实就是void* float process_data_float(float input)
{*(float *)data_ins[0]input;ai_run();return *(float *)data_outs[0];
} 从这个函数可以清晰地看出把接收的数据存放进data_ins[0]指向的缓冲区然后调用ai_run进行AI推理之后返回data_outs[0]得到推理的结果。无论是data_ins[0]还是data_outs[0]其实都是指针所以前面要用“*”把指针指向的缓冲区的值取出来或者修改。 接着我们在某个按键处理中调用这个函数输入的是从0累加到150的数据供它验证 input 0;for (int i 0; i 500; i){result process_data_float(input);printf(index:%f result:%f\r\n, input, result);input 0.3;} 按下按键后串口打印的结果也符合推理结果小于24的为1大于24的为0。在24附近出现波动的原因也很简单因为我提供的数据集里并没有出现浮点数全是0-100的整数并且模型训练轮次和数据量都比较小。 Tips 这三行代码我想了好久才想出来前面定义data_ins和data_outs时不是有个int8_t这个东西把我误导了许久问通义它说什么标准化、偏移量、量化之类的总之告诉我输入数据和输出数据就是一个字节(int8_t)。后来我使用CubeMX另几个选项生成模板并查看官方手册 最终才确定转换的模型输入数据和输出数据确实是float32而不是量化后的int8_t然后大胆尝试强制把ai_input[0].data也就是data_ins[0]转换为float32才得到正确的结果 七、跨越 AI模型转为C代码可以不使用CubeMX的这个插件但那样占用可能会很高对于STM32平台无论是操作的便捷性还是针对STM32的性能优化都是使用官方的比较合适。如果是其他单片机那么直接使用由TensorFlow Lite训练的模型转换的C代码占用也不会很高因为它专门用于嵌入式平台。 至于神经网络、CNN、LVTM、图像识别什么的从0.9到∞需要靠自己主动学习了。