摘要
本文档描述了如何使用Python和TensorFlow训练一个简单的神经网络模型来预测正弦函数,并将其部署到ESP32微控制器上。
参考文章
使用Python和Arduino在ESP32上预测正弦函数 - Dapenson - 博客园 (cnblogs.com)
最简单体验TinyML、TensorFlow Lite——ESP32跑机器学习(全代码)-优快云博客
安装tensorflow
在windows上安装python3.8
在cmd中输入
pip install tensorflow
安装图形显示库,方便直观观察数据
pip install matplotlib
编写训练脚本
首先准备数据的python代码
import math
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
# Matplotlib is a graphing library
import matplotlib.pyplot as plt
def get_model():
SAMPLES = 1000
np.random.seed(1337)
x_values = np.random.uniform(low=0, high=2 * math.pi, size=SAMPLES)
# shuffle and add noise
np.random.shuffle(x_values)
y_values = np.sin(x_values)
y_values += 0.1 * np.random.randn(*y_values.shape)
# Plot our data
plt.plot(x_values, y_values, 'b.')
plt.show()
# split into train, validation, test
TRAIN_SPLIT = int(0.6 * SAMPLES)
TEST_SPLIT = int(0.2 * SAMPLES + TRAIN_SPLIT)
x_train, x_test, x_validate = np.split(x_values, [TRAIN_SPLIT, TEST_SPLIT])
y_train, y_test, y_validate = np.split(y_values, [TRAIN_SPLIT, TEST_SPLIT])
# create a NN with 2 layers of 16 neurons
model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(1, )))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
model.fit(x_train,
y_train,
epochs=200,
batch_size=16,
validation_data=(x_validate, y_validate))
return model
if __name__ == '__main__':
model = get_model()
定义了一个名为get_model的函数,用于创建一个神经网络模型。以下是代码的详细解释:
首先,导入了所需的库和模块,如numpy、math、matplotlib.pyplot和tensorflow。
定义了一个名为SAMPLES的常量,表示数据集的大小。
使用numpy的random.seed函数设置随机数种子,以便结果可重复。
生成一个包含SAMPLES个均匀分布的随机数的数组x_values,范围在0到2π之间。
对x_values数组进行洗牌和添加噪声,使其更接近实际数据。
使用matplotlib.pyplot的plot函数绘制x_values和y_values的关系图。
将数据集划分为训练集、验证集和测试集。
创建一个具有两个隐藏层(每层16个神经元)的神经网络模型。
使用tensorflow的Sequential类创建一个神经网络模型。
添加两个全连接层,分别具有16个神经元和激活函数relu。
添加一个输出层,具有1个神经元和线性激活函数。
使用compile方法编译模型,指定优化器为rmsprop,损失函数为mse(均方误差),评估指标为mae(平均绝对误差)。
使用fit方法训练模型,传入训练数据x_train和y_train,以及训练参数,如迭代次数(epochs)、批次大小(batch_size)和验证数据(x_validate和y_validate)。
返回训练好的模型。
# create a NN with 2 layers of 16 neurons
model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(1, )))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1))
这段代码是使用TensorFlow框架构建一个简单的全连接神经网络模型。以下是模型的详细信息:
model = tf.keras.Sequential():创建一个空的序列模型对象。Sequential是TensorFlow中用于构建神经网络的简单接口,可以堆叠多个层以创建神经网络模型。
model.add(layers.Dense(16, activation='relu', input_shape=(1, ))):向模型中添加第一个全连接层。layers.Dense表示全连接层,16表示该层的神经元数量,activation='relu'表示使用ReLU激活函数。input_shape=(1,)表示该层的输入维度为(1,),即每个输入样本只有一个特征。
model.add(layers.Dense(16, activation='relu')):向模型中添加第二个全连接层。该层的参数与第一个全连接层相同。
model.add(layers.Dense(1)):向模型中添加输出层。layers.Dense表示全连接层,1表示该层的神经元数量,即输出结果的维度为1。
model.fit(x_train,
y_train,
epochs=200,
batch_size=16,
validation_data=(x_validate, y_validate))
一旦我们定义了模型,我们就可以使用数据来训练它。训练包括向神经网络传递一个x值,检查网络的输出与期望的y值偏离多少,调整神经元的权值和偏差,以便下次输出更有可能是正确的。训练在完整数据集上多次运行这个过程,每次完整的运行都被称为一个epoch。训练中要运行的epoch数是我们可以设置的参数。在每个epoch期间,数据在网络中以多个批次运行。每个批处理,几个数据片段被传递到网络,产生输出值。这些输出的正确性是整体衡量的,网络的权重和偏差是相应调整的,每批一次。批处理大小也是我们可以设置的参数。下面单元格中的代码使用来自训练数据的x和y值来训练模型。它运行200个epoch,每个批处理中有16条数据。我们还传入一些用于验证的数据。
生成随机数据的直观样式
下面通过模型生成tflite
if __name__ == '__main__':
model = get_model()
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_model = converter.convert()
这段代码是将一个TensorFlow模型转换为TensorFlow Lite格式。TensorFlow Lite是一种轻量级的TensorFlow库,专为移动和嵌入式设备优化。将TensorFlow模型转换为TensorFlow Lite格式可以使模型在移动和嵌入式设备上运行得更快。
tf.lite.TFLiteConverter 是 TensorFlow Lite 中的一个类,用于将 TensorFlow 模型转换为 TensorFlow Lite 格式。from_keras_model 方法将一个 TensorFlow 模型作为输入,并返回一个 TFLiteConverter 对象。这个对象可以用来将模型转换为 TensorFlow Lite 格式。
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]:设置优化选项,以便在转换过程中减小模型大小。OPTIMIZE_FOR_SIZE表示在保持模型准确性的同时尽可能减小模型大小。
tflite_model = converter.convert():使用convert()方法将TensorFlow模型转换为TensorFlow Lite模型,并将结果存储在tflite_model变量中。
Epoch 195/200
38/38 [==============================] - 0s 1ms/step - loss: 0.0149 - mae: 0.0969 - val_loss: 0.0127 - val_mae: 0.0886
Epoch 196/200
38/38 [==============================] - 0s 1ms/step - loss: 0.0151 - mae: 0.0985 - val_loss: 0.0144 - val_ma