基于MobileNetV2的Keras模型预测恒定及多样性低问题咨询
问题背景与模型情况
我正在构建一个基于MobileNetV2的Keras模型,用于对6项人类能力进行帧级预测。每个输出头对应一项能力,采用100分类(分数0-99)的softmax输出。模型输入为归一化到[-1,1]的224×224 RGB帧(与MobileNetV2预处理兼容),数据集规模较小(138段5分钟视频逐帧处理)。
模型简化代码如下:
def create_model(input_shape): inputs = tf.keras.Input(shape=input_shape) base_model = MobileNetV2( input_tensor=inputs, weights='imagenet', include_top=False, pooling='avg' ) for layer in base_model.layers: layer.trainable = False for layer in base_model.layers[-20:]: layer.trainable = True x = base_model.output x = layers.BatchNormalization()(x) x = layers.Dense(256, use_bias=False)(x) x = layers.BatchNormalization()(x) x = layers.Activation('relu')(x) x = layers.Dropout(0.3)(x) x = layers.BatchNormalization()(x) outputs = [ layers.Dense( 100, activation='softmax', kernel_initializer='he_uniform', dtype='float32', name=comp )(x) for comp in LABELS ] model = tf.keras.Model(inputs=inputs, outputs=outputs) lr_schedule = tf.keras.optimizers.schedules.CosineDecay( initial_learning_rate=1e-4, decay_steps=steps_per_epoch*EPOCHS, warmup_target=5e-3, warmup_steps=steps_per_epoch ) opt = tf.keras.optimizers.Adam(lr_schedule, clipnorm=1.0) opt = tf.keras.mixed_precision.LossScaleOptimizer(opt) model.compile( optimizer=opt, loss={comp: tf.keras.losses.SparseCategoricalCrossentropy() for comp in LABELS}, metrics=['accuracy'] ) return model
模型出现异常表现:训练集上准确率极高(疑似过拟合),但训练后对不同输入(甚至随机输入)均输出相同的向量;预训练阶段的预测多样性也极低,测试代码如下:
test_input = np.random.rand(1, 224, 224, 3).astype(np.float32) predictions = model.predict(test_input) print("Pre-train prediction diversity:", [np.std(p) for p in predictions])
技术问题
- 为何训练后的模型对不同输入(包括随机输入)均输出相同的向量?
- 为何预训练阶段的输出多样性如此之低?
问题解答
1. 训练后模型输出固定向量的原因及解决思路
- 过拟合到极端样本/标签分布:小数据集下模型极易记住训练数据的统计特征,若训练集中某类标签占比过高,或存在大量重复帧,模型会直接输出该类概率分布,完全忽略输入特征。
- BatchNormalization层冗余导致特征坍缩:代码中在base_model输出后连续叠加多个BatchNormalization层,训练时BN使用当前批次的均值方差,而推理阶段依赖训练累积的统计量。小数据集下训练批次小,累积的均值方差易失真,导致BN层输出近乎固定的数值,后续全连接层也随之输出固定结果。
- 学习率与梯度裁剪设置不合理:CosineDecay的初始学习率1e-4到warmup_target5e-3跨度太大,加上clipnorm=1.0可能过度限制梯度,或warmup阶段学习率突增让模型参数更新到极端值,后续无法调整。
- 解决建议:
- 加入数据增强:对视频帧做随机裁剪、翻转、颜色扰动,扩充数据集多样性,缓解过拟合。
- 精简BatchNormalization层:base_model本身已包含BN层,后续仅保留必要的BN(比如Dense(256)后加一次即可),避免多次BN引发的特征坍缩。
- 调整学习率策略:降低warmup_target(比如设为1e-4),放宽clipnorm阈值或暂时移除,观察参数更新情况。
- 添加正则化:在Dense层加入
kernel_regularizer=tf.keras.regularizers.l2(1e-4),限制参数范围,防止过拟合到极端值。
2. 预训练阶段输出多样性低的原因及解决思路
- 测试输入预处理不匹配:测试用随机输入是
np.random.rand生成的[0,1]范围数据,但模型要求输入归一化到[-1,1],输入分布与训练数据完全不符,MobileNetV2的预训练特征无法被有效激活,导致输出方差极低。 - 初始化与未训练层的限制:虽然解冻了base_model最后20层,但其余层冻结,预训练阶段(未训练或仅少量轮次),base_model的大部分特征仍保留ImageNet通用特征,未学习到适配当前任务的特征;加上顶部Dense层初始化后未经过足够训练,输出分布自然集中。
- 解决建议:
- 对齐测试输入预处理:将随机输入归一化到[-1,1],即
test_input = (np.random.rand(1,224,224,3)*2 -1).astype(np.float32),再测试输出多样性。 - 分阶段训练:先冻结整个base_model,单独训练顶部Dense层和输出头,让模型先适配当前任务的标签分布,再解冻部分base_model层微调。
- 调整初始化方式:尝试用
glorot_uniform初始化输出层,或初始化后对输出层参数做小幅度扰动,增加初始输出的多样性。
- 对齐测试输入预处理:将随机输入归一化到[-1,1],即
内容的提问来源于stack exchange,提问作者asfa afs
相关产品推荐
相关产品推荐

