4. 模型训练基础:数据集准备与标注、数据增强策略、模型训练流程、模型保存与导出

好,咱们进入第四章。这一章可以说是整个嵌入式AI部署的「地基」。你想想看,模型训练不好,后面部署再牛也是白搭。我个人习惯把这一套流程叫做「从原材料到半成品」的加工线。今天我就带你走一遍,把每个环节的坑都踩一遍。

4.1 数据集准备与标注:别让数据成为短板

做嵌入式AI,数据集的准备往往比调模型参数更花时间。我见过太多团队,模型结构设计得漂漂亮亮,结果训练出来一跑,准确率惨不忍睹。为什么?数据没弄好。

4.1.1 数据采集:先想清楚场景

嵌入式设备的数据,跟云端数据不一样。云端可以随便拍,但嵌入式设备的数据往往受限于传感器、光照、角度。比如你要做一个智能门锁的人脸识别,数据就得在门锁的摄像头角度下采集,而不是拿手机自拍。

我在项目中遇到过,客户给了几万张高清图片,结果部署到低分辨率摄像头上,模型直接「瞎了」。所以,数据采集一定要贴近真实部署环境。

我的建议: 先花一周时间,用目标设备采集一小批数据,跑通整个流程,再大规模采集。别一上来就搞几万张,万一方向错了,全白干。

4.1.2 数据标注:精细活,别偷懒

标注是体力活,但也是技术活。常用的标注工具有LabelImg(目标检测)、Labelme(语义分割)、CVAT(通用)。我个人习惯用LabelImg,轻量、上手快。

标注时要注意几点:

  • 边界框要贴合物体:别留太多背景,也别切掉物体关键部分。
  • 类别平衡:比如你检测猫和狗,猫有1000张,狗只有50张,模型肯定偏向猫。我曾经吃过这个亏,后来用数据增强和重采样才扳回来。
  • 多人标注要统一标准:比如「人」这个类别,是只标全身,还是半身也算?提前定好规则。
避坑指南: 我曾经让实习生标注一批数据,结果他标了三天,我检查发现一半的框都歪了。后来我定了个规矩:标注完必须抽检10%,不合格就返工。别嫌麻烦,数据质量直接决定模型上限。

4.2 数据增强策略:让模型见多识广

数据增强,说白了就是「无中生有」。嵌入式设备的数据往往不够,或者场景单一。数据增强能帮你把1张图变成10张,而且让模型更鲁棒。

4.2.1 常用增强方法

方法 说明 适用场景
随机翻转 水平或垂直翻转 物体方向不敏感的任务
随机旋转 ±15°以内旋转 角度变化大的场景
亮度/对比度调整 模拟不同光照 户外、光照变化大的设备
高斯噪声 添加随机噪声 传感器噪声大的场景
随机裁剪 随机切出一部分 目标可能被遮挡的场景

嗯,这里要注意:增强不是越多越好。比如你做数字识别,翻转一下「6」就变成「9」了,那模型就学错了。所以增强策略要跟任务匹配。

4.2.2 实战中的增强策略

我一般会分两步走:

  1. 离线增强:在训练前,把数据集扩充到原来的5-10倍。适合小数据集。
  2. 在线增强:训练时实时做增强,每个epoch看到的图都不一样。适合大数据集。

代码示例(Keras的ImageDataGenerator):

from tensorflow.keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(
    rotation_range=15,
    width_shift_range=0.1,
    height_shift_range=0.1,
    brightness_range=[0.8, 1.2],
    horizontal_flip=True,
    fill_mode='nearest'
)

# 生成增强后的图片
datagen.flow(x_train, y_train, batch_size=32)
我的经验: 对于嵌入式模型,我建议多加点噪声和亮度变化。因为嵌入式设备的摄像头质量一般,光照条件也差。你想想看,模型在实验室的完美光线下训练,到了实际场景肯定水土不服。

4.3 模型训练流程:从零到一

训练流程其实就那几步:加载数据、定义模型、编译、训练、评估。但每一步都有讲究。

4.3.1 训练流程概览

我习惯用Keras,因为它对嵌入式部署友好。流程如下:

# 1. 加载数据
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    'data/train',
    image_size=(224, 224),
    batch_size=32
)

# 2. 定义模型(以MobileNetV2为例)
base_model = tf.keras.applications.MobileNetV2(
    input_shape=(224, 224, 3),
    include_top=False,
    weights='imagenet'
)
base_model.trainable = False  # 先冻结,只训练分类头

model = tf.keras.Sequential([
    base_model,
    tf.keras.layers.GlobalAveragePooling2D(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(num_classes, activation='softmax')
])

# 3. 编译
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

# 4. 训练
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=20,
    callbacks=[
        tf.keras.callbacks.EarlyStopping(patience=3),
        tf.keras.callbacks.ModelCheckpoint('best_model.h5', save_best_only=True)
    ]
)

4.3.2 训练中的关键点

  • 学习率:我一般从0.001开始,如果loss不降,就调低到0.0001。别一上来就调太大,容易震荡。
  • Batch Size:嵌入式模型通常不大,32或64就够了。太大容易显存溢出,太小训练不稳定。
  • 早停(EarlyStopping):我必用。设个patience=3,连续3个epoch验证集loss不降就停。省时间,防过拟合。
避坑指南: 我曾经训练一个模型,跑了50个epoch,loss一直在降,但验证集准确率纹丝不动。后来发现是数据泄露——验证集里混了训练集的图片。所以,数据划分一定要严格,别偷懒。

4.4 模型保存与导出:SavedModel vs HDF5

训练完了,模型得保存下来。嵌入式部署常用的格式有两种:SavedModel和HDF5。嗯,这里要注意,选哪个直接影响后续的转换和部署。

4.4.1 HDF5格式(.h5)

这是Keras的默认格式,把模型结构、权重、训练配置都打包成一个文件。优点是简单,一个文件搞定。缺点是文件较大,而且只支持Keras模型。

# 保存
model.save('my_model.h5')

# 加载
from tensorflow.keras.models import load_model
model = load_model('my_model.h5')

4.4.2 SavedModel格式

这是TensorFlow的推荐格式。它是一个文件夹,里面包含模型结构、权重、签名等。优点是跨平台兼容性好,可以用于TensorFlow Serving、TensorFlow Lite等。我个人习惯用这个,因为后续转TFLite更方便。

# 保存
model.save('my_model_savedmodel', save_format='tf')

# 加载
model = tf.keras.models.load_model('my_model_savedmodel')

4.4.3 怎么选?

场景 推荐格式 原因
快速实验、调试 HDF5 一个文件,方便拷贝和分享
生产部署、跨平台 SavedModel 兼容性好,后续转TFLite、ONNX都方便
需要自定义签名 SavedModel 支持定义输入输出签名,方便服务化
我的建议: 如果你只是做实验,用HDF5就够了。但如果你打算把模型部署到嵌入式设备上,我强烈建议用SavedModel。因为后续转TFLite时,SavedModel可以直接用,而HDF5还得先转成Keras模型再转,多一步就多一个坑。

好了,这一章的内容就到这里。数据集准备、数据增强、训练流程、模型保存,每一步都是实战中踩过的坑。下一章我们会讲模型压缩与量化,那才是嵌入式部署的重头戏。到时候见。