超级小星星:时间过得可真快ESPFriends创客沙龙已经在武汉举办了两期,在这里有行业内的工程师、高校的学生以及极客,在这里我们交流分享自己的开发心得,提出遇到的“大坑”也可以得到小伙伴们的解决方案,希望活动可以越办越好,在这里我也记录一下自己的开发历程和学习心得与大家共勉。
内容源码地址:link
本期的主题是模型的训练与部署,AI这个东西确实很神奇,我们之所以感觉这东西很“虚”,是因为我们并没有将其落到实处,这里我们就开始本期的探索之旅吧!o( ̄▽ ̄)ブ
我的的测试训练环境:
电脑系统:
软件:
参考资料:
为了避免下载到有病毒的资源,所有的链接都是出自官方网站或者国内源
俗话说的好写程序从hello_world开始,当然我们检验自己的开发环境搭建是否正确当然先编译一下啦,这里解释一下为什么没有使用最新版本的IDF,因为在使用ESP-WHO框架的话,需要使用官方建议的软件分支,不然谁知道会出现什么问题,我使用过5.1分支的去set-target,不出所料第一步就出现问题/(ㄒoㄒ)/~~,当然官方之后会更新的啦!
这里需要我们打开文件目录使用命令行的方式去编译项目工程,并烧录到ESP32-S3-EYE (感谢官方的开发板\^o^/)
当然对应的例程目录下面都有一个README文件,这里按照上面的说明操作即可:
# 设置芯片型号
idf.py set-target esp32s3
# 编译工程
idf.py build
# 烧录并打开串口监视
# 在这里使用命令行的话win平台下会自动找到设备串口并烧录
idf.py flash monitor
表示设置芯片信号成功,后面就会很顺利了
编译成功
烧录成功
查看测试程序
程序成功跑起来啦o(/ ̄▽ ̄)ブ
命令是不是很简单,当然这只是成功的一小步,后面还有更多的未知等待着我们去探索
link
这里按照官方文件夹中的README文件操作,安装了bazel,在其根目录下运行指令
bazel build tensorflow/lite/micro/examples/hello_world:evaluate
第一步都过不了,找了半天都没找到解决办法/(ㄒoㄒ)/~~,好像是因为软件源的问题,但是在linux下可以使用清华源设置,在win下目前还没有找到解决方法
这里不影响我们用它的代码做参考,接下来我们就要自己敲代码了o(* ̄▽ ̄)ブ
导入依赖项
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import math
# 生成从0到2派的数据,并将数据转换为np的float32的格式
x_values = np.random.uniform(low=0, high=2 * math.pi,
size=1000).astype(np.float32)
# 将数据随机排列
np.random.shuffle(x_values)
# 得到数据y
y_values = np.sin(x_values).astype(np.float32)
# 显示绘制数据图形
plt.plot(x_values, y_values,"b.")
plt.show()
# 添加随机噪声
y_values += 0.1 * np.random.randn(*y_values.shape)
# 绘制图形
plt.plot(x_values, y_values, "b.")
plt.show()
# 拆分数据集,将数据集分为训练集(60%)、测试集(20%)和验证集(20%)
TRAIN_SPLIT = int(0.6 * 1000)
TEST_SPLIT = int(0.2 * 1000 + TRAIN_SPLIT)
# 拆分数据集
x_train, x_validate, x_test = np.split(x_values, [TRAIN_SPLIT, TEST_SPLIT])
y_train, y_validate, y_test = np.split(y_values, [TRAIN_SPLIT, TEST_SPLIT])
# 绘制图形
plt.plot(x_train, y_train, "b.", label="Train")
plt.plot(x_validate, y_validate, "y.", label="Validate")
plt.plot(x_test, y_test, "r.", label="Test")
# 图像加图例
plt.legend()
plt.show()
# 创建模型网络
model = tf.keras.Sequential()
# First layer takes a scalar input and feeds it through 16 "neurons". The
# neurons decide whether to activate based on the 'relu' activation function.
model.add(tf.keras.layers.Dense(16, activation='relu', input_shape=(1,)))
# The new second and third layer will help the network learn more complex
# representations
model.add(tf.keras.layers.Dense(16, activation='relu'))
# Final layer is a single neuron, since we want to output a single value
model.add(tf.keras.layers.Dense(1))
# Compile the model using the standard 'adam' optimizer and the mean squared
# error or 'mse' loss function for regression.
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
# 打印模型参数
model.summary()
model.fit(x_values,
y_values,
epochs=400,
validation_split=0.2,
batch_size=64,
verbose=2)
# 保存模型
save_dir = './modes/test'
tf.saved_model.save(model, save_dir)
# 模型转换
converter = tf.lite.TFLiteConverter.from_saved_model(save_dir)
tflite_model = converter.convert()
# 模型保存
import pathlib
tflite_model_file = pathlib.Path('model.tflite')
tflite_model_file.write_bytes(tflite_model)
# 模型量化
def representative_dataset(num_samples=500):
for i in range(num_samples):
yield [x_values[i].reshape(1, 1)]
saved_model_dir = "./modes/test"
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()
open("sine_model_quantized.tflite","wb").write(tflite_quant_model)
目前我还没有从官方的脚本项目配置中找到对应的脚本转换文件,目前我是用虚拟机中的命令转换的方式,这样也很简单,一起来操作一下吧
# 安装工具
sudo apt install xxd
# 执行转换命令
xxd -i Demo_model.tflite > Demo_model.h
然后将文件内容复制进例程中的模型文件中
对应目录在 examples/hello_world/main/model.cc link
替换对应的模型文件然后重新编译烧录工程
在模型没有量化就将其转换,则会导致输出的数据全为零,这时候我们就需要改动源码中的输入变量类型,下面时我将没有量化的模型转换后修改源码输出的结果
I (224) heap_init: Initializing. RAM available for dynamic allocation:
I (232) heap_init: At 3FC935D8 len 00056138 (344 KiB): D/IRAM
I (238) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DIRAM
I (245) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (251) heap_init: At 600FE000 len 00002000 (8 KiB): RTCRAM
I (258) spi_flash: detected chip: gd
I (262) spi_flash: flash io: qio
W (265) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (279) sleep: Configure to isolate all GPIO pins in sleep state
I (285) sleep: Enable automatic switching of GPIO sleep configuration
I (293) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
x_value: 0.000000, y_value: 0.128340
x_value: 0.314159, y_value: 0.324291
x_value: 0.628319, y_value: 0.551790
x_value: 0.942478, y_value: 0.755303
x_value: 1.256637, y_value: 0.845717
x_value: 1.570796, y_value: 0.723688
x_value: 1.884956, y_value: 0.601659
x_value: 2.199115, y_value: 0.479630
x_value: 2.513274, y_value: 0.357600
x_value: 2.827433, y_value: 0.235571
x_value: 3.141593, y_value: 0.113542
x_value: 3.455752, y_value: -0.008487
x_value: 3.769912, y_value: -0.130516
x_value: 4.084070, y_value: -0.252545
x_value: 4.398230, y_value: -0.374575
x_value: 4.712389, y_value: -0.496604
x_value: 5.026548, y_value: -0.618633
x_value: 5.340708, y_value: -0.740662
x_value: 5.654867, y_value: -0.862691
x_value: 5.969026, y_value: -0.984720
x_value: 0.000000, y_value: 0.128340
x_value: 0.314159, y_value: 0.324291
x_value: 0.628319, y_value: 0.551790
x_value: 0.942478, y_value: 0.755303
x_value: 1.256637, y_value: 0.845717
x_value: 1.570796, y_value: 0.723688
x_value: 1.884956, y_value: 0.601659
x_value: 2.199115, y_value: 0.479630
x_value: 2.513274, y_value: 0.357600
x_value: 2.827433, y_value: 0.235571
x_value: 3.141593, y_value: 0.113542
x_value: 3.455752, y_value: -0.008487
x_value: 3.769912, y_value: -0.130516
x_value: 4.084070, y_value: -0.252545
x_value: 4.398230, y_value: -0.374575
x_value: 4.712389, y_value: -0.496604
x_value: 5.026548, y_value: -0.618633
x_value: 5.340708, y_value: -0.740662
x_value: 5.654867, y_value: -0.862691
x_value: 5.969026, y_value: -0.984720
x_value: 0.000000, y_value: 0.128340
x_value: 0.314159, y_value: 0.324291
x_value: 0.628319, y_value: 0.551790
x_value: 0.942478, y_value: 0.755303
x_value: 1.256637, y_value: 0.845717
x_value: 1.570796, y_value: 0.723688
x_value: 1.884956, y_value: 0.601659
x_value: 2.199115, y_value: 0.479630
x_value: 2.513274, y_value: 0.357600
x_value: 2.827433, y_value: 0.235571
x_value: 3.141593, y_value: 0.113542
x_value: 3.455752, y_value: -0.008487
x_value: 3.769912, y_value: -0.130516
x_value: 4.084070, y_value: -0.252545
x_value: 4.398230, y_value: -0.374575
x_value: 4.712389, y_value: -0.496604
x_value: 5.026548, y_value: -0.618633
x_value: 5.340708, y_value: -0.740662
x_value: 5.654867, y_value: -0.862691
x_value: 5.969026, y_value: -0.984720
x_value: 0.000000, y_value: 0.128340
x_value: 0.314159, y_value: 0.324291
x_value: 0.628319, y_value: 0.551790
x_value: 0.942478, y_value: 0.755303
x_value: 1.256637, y_value: 0.845717
x_value: 1.570796, y_value: 0.723688
x_value: 1.884956, y_value: 0.601659
x_value: 2.199115, y_value: 0.479630
x_value: 2.513274, y_value: 0.357600
x_value: 2.827433, y_value: 0.235571
x_value: 3.141593, y_value: 0.113542
x_value: 3.455752, y_value: -0.008487
x_value: 3.769912, y_value: -0.130516
x_value: 4.084070, y_value: -0.252545
x_value: 4.398230, y_value: -0.374575
x_value: 4.712389, y_value: -0.496604
x_value: 5.026548, y_value: -0.618633