我是在学习Tensorflow 2.0的时候,当然,最终还是为了跑在嵌入式设备上,因为这次疫情影响,在离住的地方比较近的办公场所办公,手头上只有一块STM32F407ZG的开发板,没错,是某点某子的开发板,想着要不在这板子上跑跑,刚好之前看到了Cube-AI,所以就进行了一波尝试。
同时感谢这个视频,可以算是个新手入门指南视频,就是画质***->新手入门视频
X-CUBE-AI是STM32Cube.AI生态系统的STM32Cube扩展软件包的一部分,通过自动转换预训练的神经网络并将生成的优化库集成到用户的项目中,扩展了STM32CubeMX功能。
官方链接在这里,从来没听说的朋友们可以先去预览一波啊:ST X-Cube-AI
我就来浓缩一下,简而言之就是通过X-Cube-AI扩展将当前比较热门的AI框架进行C代码的转化,以支持在嵌入式设备上使用,目前使用X-Cube-AI需要在STM32CubeMX版本5.0以上,STM8CubeMX没注意看,目前支持转化的模型有Keras、TF lite、ONNX、Lasagne、Caffe、ConvNetJS,还算比较牛*的,Cube-AI把模型转化为一堆数组,而后将这些数组内容解析成模型,和Tensorflow里的模型转数组后使用原理是一样的。
在PC上建立模型,我的模型是建立一个能源等级检测输出,输入电压,输出对应等级,我模型做成了分类,热乎乎热代码来啦:
'''
电源等级检测测试
训练模型阈值
一级 -> v>=8.0
二级 -> 7.8<=v<8.0
三级 -> v<7.8
输入层 -> 隐藏层 -> 输出层
'''
'''
电源等级检测测试
训练模型阈值
一级 -> v>=8.0
二级 -> 7.8<=v<8.0
三级 -> v<7.8
输入层 -> 隐藏层 -> 输出层
'''
#导入工具包
import tensorflow as tf
import pandas as pd
import numpy as np
#读取数据
data = pd.read_csv('data/voltage.csv', sep=',', header=None)
voltage = data.iloc[:,0]
level = data.iloc[:,1:]
level.astype(int)
#建立模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(units=20, activation='relu', input_shape=(1,)))
model.add(tf.keras.layers.Dense(units=10, activation='relu'))
model.add(tf.keras.layers.Dense(units=3, activation='softmax'))
model.summary()
model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
loss=tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.mse])
history = model.fit(x=voltage, y=level, epochs=40000)
print(model.evaluate(voltage, level))
#保存模型
model.save('level_check.h5')
然后再来个PC上对模型的载入与测试,并且将模型转换为TF lite格式(ps:如果直接使用.h5文件也是可以的,在CubeMX里输入模型类别选Keras),代码如下:
'''
电源等级检测测试
训练模型阈值
一级 -> v>=8.0
二级 -> 7.8<=v<8.0
三级 -> v<7.8
'''
#导入工具包
import tensorflow as tf
import numpy as np
import time
import datetime
#输出函数 输出更加直观
def level_output(level=np.zeros(3)):
for i in range(level.shape[1]):
if level[0,i] == 1.0:
return i+1
#测试电压
test_v = 7.78
t1 = time.time()
#导入模型计算
load_model = tf.keras.models.load_model('level_check.h5')
out = load_model.predict([test_v])
print(out)
cal_level = np.around(out).astype(int)
t2 = time.time()
#输出能源等级
level = level_output(cal_level)
print(level)
print((int(t2*1000)-int(t1*1000)))
#转换模型为tf lite格式 不量化
converter = tf.lite.TFLiteConverter.from_keras_model(load_model)
tflite_model = converter.convert()
#保存到磁盘
open("level_check.tflite", "wb").write(tflite_model)
训练数据不能漏呀,训练加后期测试使用哦,新建txt,然后另存为CSV就可以啦:
7.61,0,0,1
7.62,0,0,1
7.63,0,0,1
7.64,0,0,1
7.65,0,0,1
7.66,0,0,1
7.75,0,0,1
7.78,0,0,1
7.71,0,0,1
7.72,0,0,1
7.8,0,1,0
7.83,0,1,0
7.92,0,1,0
7.85,0,1,0
7.81,0,1,0
7.81,0,1,0
7.84,0,1,0
7.89,0,1,0
7.98,0,1,0
7.88,0,1,0
8.02,1,0,0
8.12,1,0,0
8.05,1,0,0
8.15,1,0,0
8.11,1,0,0
8.01,1,0,0
8.22,1,0,0
8.12,1,0,0
8.14,1,0,0
8.07,1,0,0
大家可以先跟着官方网站的使用特定模型的进行学习创建工程,当然也可以直接看我的这个步骤哦。
是不是非常的简单啊,不过比较难受的是,支持神经网络的底层代码是一个库文件,但是不影响我们使用,突发奇想,查看了代码,并没有启用STM32的专用的CRC校验,那么,是不是只要ROM和RAM足够,任何一个嵌入式设备都可以直接使用了呢?嚯嚯嚯,搞起来!!!!