#1.导入库

常见库如下:

导入方式 主要作用
import tensorflow as tf TensorFlow 模型训练、推理、TFLite转换
import numpy as np NumPy 数据处理、数组运算
import matplotlib.pyplot as plt Matplotlib 数据可视化、绘图
from tensorflow.keras import layers Layers 创建神经网络层
from tensorflow.keras import models Models 创建模型结构
from tensorflow.keras import losses Losses 损失函数
from tensorflow.keras import optimizers Optimizers 优化器
from tensorflow.keras.callbacks import ... Callbacks 训练控制
import math Math 数学运算

📌其实大多数项目:这4个就够了

import tensorflow as tf               #神经网络训练

import numpy as np                    #数据处理

import matplotlib.pyplot as plt       #画图

from tensorflow.keras import layers   #搭网络层


📌 完整训练流程对应关系

导入库
   ↓
生成/读取数据        ← numpy
   ↓
画数据图            ← matplotlib
   ↓
切分训练集          ← numpy
   ↓
创建模型            ← tensorflow / layers
   ↓
compile编译         ← tensorflow
   ↓
fit训练             ← tensorflow
   ↓
画loss曲线          ← matplotlib
   ↓
转换TFLite          ← tensorflow

#2.数据集准备

本质:不同任务,不同题目+答案,分成大小不同的3份

任务类型 输入(X) 标签(y)
回归 数值/时间序列 连续数值
分类 数值/图像/音频/文本 类别编号
生成 文本/图像 下一词/像素
检测 图像/时序 位置+类别

案例一:现有数据集

#1.现有数据集(加载MNIST数据集)
(x_train,y_train),(x_test,y_test)=tf.keras.datasets.mnist.load_data()#加载MNIST数据集

案例二:制作数据集

# 生成一些随机样本
np.random.seed(1234)                                               #随机种子,不改变形状
x_values=np.random.uniform(low=0,high=(2*math.pi),size=nsamples)   #(nsamples,)

# 使用这些值创建一个带噪声的正弦波
y_values=np.sin(x_values)+(0.1*np.random.randn(x_values.shape[0])) #(nsamples,)

# 将数据集拆分为训练集、验证集和测试集
val_split=int(val_ratio*nsamples)                                  #计算验证集分割点
test_split=int(val_split+(test_ratio*nsamples))                    #计算测试集分割点

x_val,x_test,x_train=np.split(x_values,[val_split,test_split])     #(nsamples,)->(验证集,测试集,训练集)
y_val,y_test,y_train=np.split(y_values,[val_split,test_split])     #(nsamples,)->(验证集,测试集,训练集)

#3数据预处理

本质:把数据转换成该种神经网络要求的形式(不同网络吃的数据形式不同)

项目一:识别手写数字(CNN网络)

#预处理函数(对每一条数据做统一处理)
def preprocess(image,label):
    image=tf.cast(image,tf.float32)/255.0                    #(28,28)->(28,28)
    image=tf.expand_dims(image,axis=-1)                      #(28,28)->(28,28,1)
    return image,label                                       #image:(28,28,1)

#训练数据管道
train_dataset=(tf.data.Dataset.from_tensor_slices((x_train,y_train))
                                                             #(60000,28,28)->(28,28)

.map(preprocess,num_parallel_calls=tf.data.AUTOTUNE)         #(28,28)->(28,28,1)
.shuffle(1000)                                               #形状不变,顺序打乱
.batch(32)                                                   #(28,28,1)->(32,28,28,1)
.prefetch(tf.data.AUTOTUNE))                                 #形状不变

#测试数据管道
test_dataset=tf.data.Dataset.from_tensor_slices((x_test,y_test)) #(10000,28,28)->(28,28)
.map(preprocess)                                             #(28,28)->(28,28,1)
.batch(32)                                                   #(28,28,1)->(32,28,28,1)

项目二:识别手写数字(Dense网络)

# 加载内置MNIST数据集
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() 
 # x_train:(60000,28,28) y_train:(60000,) / x_test:(10000,28,28) y_test:(10000,)

# 将像素值缩放到0-1范围
x_train = x_train.astype("float32") / 255  # (60000,28,28)->(60000,28,28)
x_test = x_test.astype("float32") / 255    # (10000,28,28)->(10000,28,28)

# 将图像展平为784维向量
x_train = x_train.reshape(-1, 784)  # (60000,28,28)->(60000,784),-1表示自动计算这一维
x_test = x_test.reshape(-1, 784)    # (10000,28,28)->(10000,784)

# 标签转为one-hot编码
y_train = keras.utils.to_categorical(y_train, 10)  # (60000,)->(60000,10)
y_test = keras.utils.to_categorical(y_test, 10)    # (10000,)->(10000,10)

#3.搭建模型

本质:不同网络是为了处理不同类型的数据

常见网络 输入数据要求 用途
MLP(全连接神经网络) 一维特征向量,例如 (784,)(10,)。通常需要将数据展平。例:MNIST图片 (28,28)(784,) 数字识别、传感器数据分类、简单分类任务
CNN(卷积神经网络) 保留空间结构的多维数据,例如 (28,28,1)(96,96,3)。例:摄像头图片 (96,96,3) 图像分类、图像识别、视觉任务
LSTM(长短期记忆网络) 时序数据,格式通常为 (时间步, 特征数)。例:100个采样点的加速度数据 (100,3) 语音识别、时间序列预测、传感器时序分析
AutoEncoder(自编码器) 输入和输出数据格式相同,可以是向量、图像或时序数据。例:振动信号 (128,) → 重构 (128,) 异常检测、数据压缩、特征提取
Transformer(轻量Transformer) 序列数据,需要按时间顺序排列。例:语音特征 (50,13)(50帧MFCC,每帧13个特征) 语音处理、时序分析、轻量级自然语言处理

例一:MLP(全连接神经网络)

#搭建模型
model = keras.Sequential([
    layers.Dense(512, activation='relu', input_shape=(784,)),
    layers.Dropout(0.2),
    layers.Dense(256, activation='relu'),
    layers.Dense(10, activation='softmax')
])

例二:CNN(卷积神经网络)

model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),  
    # 卷积层:提取局部特征(32个卷积核)

    layers.MaxPooling2D((2, 2)),  # 最大池化:下采样,降低特征图尺寸

    layers.Conv2D(64, (3, 3), activation='relu'),  # 第二层卷积:提取更高层特征
    layers.MaxPooling2D((2, 2)),  # 再次池化,继续降维

    layers.Flatten(),  # 展平:把2D特征图变成1D向量

    layers.Dense(128, activation='relu'),  # 全连接层:进行特征组合与学习
    layers.Dropout(0.5),  # Dropout:随机失活一部分神经元,防止过拟合

    layers.Dense(10, activation='softmax') 
     # 输出层:10分类(数字0-9),softmax输出概率
])

常见网络层

1.Dense(全连接层)

参数

作用

常见值

units

神经元数量

32、64、128、256

activation

激活函数

relusigmoidsoftmax

use_bias

是否使用偏置

True

2.Conv2D(卷积层)

参数

作用

常见值

filters

卷积核数量

8、16、32、64

kernel_size

卷积核大小

(3,3)、(5,5)

strides

步长

(1,1)、(2,2)

padding

填充方式

"same""valid"

activation

激活函数

relu

3.MaxPooling2D(最大池化层)

参数

作用

常见值

pool_size

池化窗口大小

(2,2)

strides

步长

2

padding

填充方式

"valid"

4.Flatten(展平层)

参数

作用

常见值

多维数据转一维

-

5.Dropout(随机失活层)

参数

作用

常见值

rate 丢弃比例 0.2、0.3、0.5

#4.编译模型

📌 model.compile( )最常见写法

model.compile(                                #告诉TensorFlow:
    optimizer='adam',                         # 1.怎么学习
    loss='sparse_categorical_crossentropy',   # 2.怎么判断错误
    metrics=['accuracy']                      # 3.训练时显示什么
)

参数

作用

optimizer

优化器(根据 loss 来修改模型参数)

loss

损失函数(衡量模型“错了多少”)

metrics

训练过程中的“成绩显示器”

📌 1. optimizer(优化器)

optimizer='adam'        #根据损失,调整神经网络的权重

优化器

什么时候用

adam

大部分任务直接用,通用性最强

rmsprop

时间序列、RNN、小数据训练时常见

sgd

想手动精细控制训练过程时用,研究和经典模型常见


📌 2. loss(损失函数)

loss='mae'        #衡量模型“错了多少”

loss

什么时候用

mae

预测连续数值时用,例如温度、房价、sin曲线

mse

也是预测连续数值时用,常用于回归任务

sparse_categorical_crossentropy

多分类任务,标签是数字时用,例如MNIST的0~9

binary_crossentropy

双分类任务,例如“猫/狗”、“有病/没病”


📌 3. metrics(指标)

metrics=['accuracy']        #训练时显示什么结果

metrics

什么时候用

accuracy

分类任务时用,查看预测正确率

mae

回归任务时用,查看预测值平均误差大小


#5.训练模型

history = model.fit(
    train_dataset,          # 训练数据集
    epochs=10,              # 最多训练 10 轮
    validation_data=test_dataset,  # 用测试集评估验证效果


    callbacks=[
        tf.keras.callbacks.EarlyStopping(
            patience=3,                  # 验证集性能连续 3 轮无提升则停止训练
            restore_best_weights=True    # 停止时自动恢复最佳权重
        ),
        tf.keras.callbacks.ModelCheckpoint(
            'best_model.h5',             # 模型保存路径
            save_best_only=True          # 只保存验证集表现最好的那一轮
        )
    ]
)

📌batch_size

假设:

训练集一共有1000张图片
batch_size=100
第1批:学习1~100
第2批:学习101~200
...
第10批:学习901~1000

这10批学完,才算1个epoch

📌callbacks

Callback

作用

EarlyStopping

效果不再提升时提前停止训练

ModelCheckpoint

自动保存训练效果最好的模型

ReduceLROnPlateau

效果变差时自动降低学习率

TensorBoard

可视化查看训练过程

#6.显示训练记录

本质:绘制Epoch-Accuracy 和 Epoch-Loss两个图,不同任务类型关注点不同

显示的整体流程:

plt.plot(epochs,val_loss,'b',label='验证损失') #画验证损失曲线
plt.title('训练损失和验证损失')                 #设置标题
plt.legend()                                   #显示图例
plt.show()                                     #显示图像

项目一:分类任务(更关注Accuracy)

# 5. 评估模型
test_loss, test_acc = model.evaluate(test_dataset)  # 在测试集上计算损失和准确率
print(f'测试集准确率: {test_acc:.4f}')               # 打印准确率,保留4位小数

# 6. 可视化训练过程
plt.plot(history.history['accuracy'], label='Training Accuracy')      # 训练集准确率曲线
plt.plot(history.history['val_accuracy'], label='Validation Accuracy') # 验证集准确率曲线
plt.xlabel('Epoch')    # x 轴:训练轮次
plt.ylabel('Accuracy') # y 轴:准确率
plt.legend()           # 显示图例
plt.show()             # 渲染并展示图表

项目二:sin回归任务(更关注Loss)

# 绘制训练过程中的损失曲线

loss = history.history['loss']          # 每轮训练集损失值
val_loss = history.history['val_loss']  # 每轮验证集损失值

epochs = range(1, len(loss) + 1)        # 生成轮次序号 [1, 2, ..., n]

plt.plot(epochs, loss, 'bo', label='Training loss')    # 训练损失,蓝色圆点
plt.plot(epochs, val_loss, 'b', label='Validation loss')  # 验证损失,蓝色实线
plt.title('Training and validation loss')  # 图表标题
plt.legend()   # 显示图例
plt.show()     # 渲染并展示图表

📌plt.plot()

参数 说明 常用值示例
x x 轴数据 [1,2,3]range(10)
y y 轴数据 [0.8, 0.85, 0.9]
color 线条颜色 'red''b''#ff0000'
linewidth 线条宽度 122.5
linestyle 线型 '-' 实线、'--' 虚线、':' 点线
marker 标记形状 'o' 圆、's' 方、'^' 三角
label 图例名称 'Training Accuracy'
alpha 透明度 0.30.51.0

#7.模型转为tflite格式

本质:Keras 模型 (float32)  →  量化压缩  →  TFLite 模型 (int8)

# 1. 创建转换器
converter = lite.TFLiteConverter.from_keras_model(model)

# 2. 定义校准数据集(取 100 条训练数据,用于统计每层数值范围)
def representative_dataset():
    for i in range(100):
        yield [x_train[i:i+1]]

# 3. 开启完全 INT8 量化
converter.optimizations = [lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset        # 指定校准数据
converter.target_spec.supported_ops = [lite.OpsSet.TFLITE_BUILTINS_INT8]  
                                                                 # 强制所有算子使用 int8

converter.inference_input_type = tf.int8                         # 输入改为 int8
converter.inference_output_type = tf.int8                        # 输出改为 int8

# 4. 执行转换
tflite_model = converter.convert()

# 5. 保存为 .tflite 文件
open(tflite_model_name + '.tflite', 'wb').write(tflite_model)

converter.optimizations可选项

选项 说明
OPTIMIZE_FOR_SIZE 将模型权重从 float32 压缩为 int8,体积缩小约 75%
OPTIMIZE_FOR_LATENCY 对运算做优化,减少推理时的计算量
DEFAULT 同时对权重和运算做优化,体积和速度都有提升

实际上 TensorFlow 后续版本中这三个选项效果已基本相同,官方推荐统一使用 DEFAUL

#8.模型转为C数组

# 函数:将十六进制值转换为 C 编程所需的数组
def hex_to_c_array ( hex_data, var_name ):

  c_str = ''

  # 创建头部守卫
  c_str += '#ifndef ' + var_name.upper() + '_H\n'
  c_str += '#define ' + var_name.upper() + '_H\n\n'

  # 在文件顶部添加数组长度
  c_str += '\nunsigned int ' + var_name + '_len = ' + str(len(hex_data)) + ';\n'

  # 声明 C 变量
  c_str += 'unsigned char ' + var_name + '[] = {'
  hex_array = []
  for i, val in  enumerate ( hex_data ) :

    #从十六进制构造字符串
    hex_str = format(val, '#04x' )

    # 添加格式,使每行长度不超过 80 个字符
    if (i + 1 ) < len(hex_data):
      hex_str += ','
    if (i + 1 ) % 12 == 0 :
      hex_str += '\n'
    hex_array.append(hex_str)

  # 添加右大括号
  c_str += '\n' + format( ' ' .join (hex_array)) + '\n};\n\n'

  # 关闭头部 guard
  c_str += '#endif //' + var_name.upper() + '_H'

  return c_str

#使用 open (c_model_name + '.h' , 'w' ) as  file将 TFLite 模型写入 C 源文件(或头文件):
with open(c_model_name + ".h", "w") as file:
    file.write(
        hex_to_c_array(
            tflite_model,
            c_model_name
        )
    )

本质上就是:将二进制文件逐字节转成十六进制写进 C 头文件

.tflite 二进制文件  →  unsigned char model[] = {0x1c, 0x00, ...}

只要满足以下两点,任何模型都适用:

条件 说明
已转换为 .tflite 格式 这段代码的输入是 tflite_model 二进制数据
已完成 int8 量化 保证 MCU 能正常推理

模型是 CNN、RNN 还是全连接网络,对这段代码来说没有任何影响。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐