TensorFlow/Keras数字识别任务训练与验证指标差距过大是什么原因?
问题原因
1. 预训练模型预处理不匹配
你使用的MobileNetV2是在像素值归一化到[-1, 1]范围的数据集上预训练的,当前你直接将像素除以255得到[0,1]范围的输入,和预训练时的输入分布差异极大,直接导致模型中BatchNormalization层在训练阶段统计的批量均值、方差,和验证阶段使用的滑动平均均值、方差严重不匹配,这是相同数据集下验证指标远差于训练指标的最核心原因。
2. BatchNormalization滑动平均未收敛
MobileNetV2的BatchNormalization层默认动量为0.99,滑动平均更新速度很慢,你仅训练15个epoch,滑动平均参数还没拟合到当前数据集的真实分布,验证阶段使用未收敛的滑动平均参数做归一化,输出结果自然偏差极大。
3. 超参数设置错误
如果steps_per_epoch设置值大于总样本数/batch_size,训练阶段会重复采样部分样本,相当于模型在训练时见过更多次当前这批数据,而验证阶段是全量跑一次,也会出现同数据集下的指标差异。
4. 预训练层训练策略不合理
没有冻结MobileNetV2的底层权重的情况下,小数据集训练时更新预训练权重会导致BatchNormalization层的统计值波动极大,进一步放大训练和验证阶段的差异。
解决方法
- 替换输入预处理逻辑,使用MobileNetV2配套的预处理函数,将
train_x=train_x/255改为:
train_x = tf.keras.applications.mobilenet_v2.preprocess_input(train_x)
- 调低BatchNormalization层的动量,加快滑动平均收敛速度,初始化基模型时添加参数:
tf.keras.applications.MobileNetV2(include_top=False, input_shape=(224, 224, 3), momentum=0.9)
- 移除
steps_per_epoch参数,Keras会自动根据样本数和batch_size计算正确的训练步数 - 初期训练先冻结MobileNetV2的权重,只训练顶部的全连接层,等顶部层收敛后再解冻部分底层微调:
base_model = tf.keras.applications.MobileNetV2(include_top=False, input_shape=(224, 224, 3)) base_model.trainable = False # 先冻结基模型 model = Sequential([ base_model, Flatten(), Dense(128), LeakyReLU(alpha=.3), Dense(128), LeakyReLU(alpha=.3), Dense(128), LeakyReLU(alpha=.3), Dense(128), LeakyReLU(alpha=.3), Dense(10, activation='softmax') ])
- 将训练epoch数提升到30以上,保证BatchNormalization层的滑动平均参数充分收敛
内容的提问来源于stack exchange,提问作者bdvr
相关产品推荐
相关产品推荐

