4. 模型训练基础:数据集准备与标注、数据增强策略、模型训练流程、模型保存与导出
好,咱们进入第四章。这一章可以说是整个嵌入式AI部署的「地基」。你想想看,模型训练不好,后面部署再牛也是白搭。我个人习惯把这一套流程叫做「从原材料到半成品」的加工线。今天我就带你走一遍,把每个环节的坑都踩一遍。
4.1 数据集准备与标注:别让数据成为短板
做嵌入式AI,数据集的准备往往比调模型参数更花时间。我见过太多团队,模型结构设计得漂漂亮亮,结果训练出来一跑,准确率惨不忍睹。为什么?数据没弄好。
4.1.1 数据采集:先想清楚场景
嵌入式设备的数据,跟云端数据不一样。云端可以随便拍,但嵌入式设备的数据往往受限于传感器、光照、角度。比如你要做一个智能门锁的人脸识别,数据就得在门锁的摄像头角度下采集,而不是拿手机自拍。
我在项目中遇到过,客户给了几万张高清图片,结果部署到低分辨率摄像头上,模型直接「瞎了」。所以,数据采集一定要贴近真实部署环境。
4.1.2 数据标注:精细活,别偷懒
标注是体力活,但也是技术活。常用的标注工具有LabelImg(目标检测)、Labelme(语义分割)、CVAT(通用)。我个人习惯用LabelImg,轻量、上手快。
标注时要注意几点:
- 边界框要贴合物体:别留太多背景,也别切掉物体关键部分。
- 类别平衡:比如你检测猫和狗,猫有1000张,狗只有50张,模型肯定偏向猫。我曾经吃过这个亏,后来用数据增强和重采样才扳回来。
- 多人标注要统一标准:比如「人」这个类别,是只标全身,还是半身也算?提前定好规则。
4.2 数据增强策略:让模型见多识广
数据增强,说白了就是「无中生有」。嵌入式设备的数据往往不够,或者场景单一。数据增强能帮你把1张图变成10张,而且让模型更鲁棒。
4.2.1 常用增强方法
| 方法 | 说明 | 适用场景 |
|---|---|---|
| 随机翻转 | 水平或垂直翻转 | 物体方向不敏感的任务 |
| 随机旋转 | ±15°以内旋转 | 角度变化大的场景 |
| 亮度/对比度调整 | 模拟不同光照 | 户外、光照变化大的设备 |
| 高斯噪声 | 添加随机噪声 | 传感器噪声大的场景 |
| 随机裁剪 | 随机切出一部分 | 目标可能被遮挡的场景 |
嗯,这里要注意:增强不是越多越好。比如你做数字识别,翻转一下「6」就变成「9」了,那模型就学错了。所以增强策略要跟任务匹配。
4.2.2 实战中的增强策略
我一般会分两步走:
- 离线增强:在训练前,把数据集扩充到原来的5-10倍。适合小数据集。
- 在线增强:训练时实时做增强,每个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不降就停。省时间,防过拟合。
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 | 支持定义输入输出签名,方便服务化 |
好了,这一章的内容就到这里。数据集准备、数据增强、训练流程、模型保存,每一步都是实战中踩过的坑。下一章我们会讲模型压缩与量化,那才是嵌入式部署的重头戏。到时候见。