CNN-LSTM时间序列模型训练时Loss及指标无变化问题求助
问题排查:CNN-LSTM训练时Loss及指标完全不变
以下是核心问题及对应的修复方案:
1. 学习率调度器逻辑错误,导致学习率快速降至0
你的decay_schedule函数每次直接减去0.0001,而Adam优化器默认初始学习率是0.001,这意味着第10轮训练后学习率就会变成0,之后模型参数完全停止更新,自然loss和指标不再变化。
修复方案:
- 给学习率设置下限,避免降到0以下;
- 改用更合理的衰减策略,或者先移除自定义调度器验证基础模型训练情况。
修改后的调度器示例:
def decay_schedule(epoch, lr): # 设置最小学习率,防止降至0 min_lr = 1e-6 lr = max(lr - 0.0001, min_lr) return lr
2. EarlyStopping的mode参数设置错误
你监控的是val_loss(损失值),回归任务中损失越小越好,但你设置了mode='max',这会让早停逻辑变成“当val_loss上升时停止”,完全不符合需求,导致早停机制失效。
修复方案:将mode改为'min':
callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min', min_delta=1e-3, patience=50)
3. 输出层激活函数选择不当
回归任务用relu激活存在风险:如果标签值包含负数,或者模型预测被relu限制在0值,会导致模型无法拟合真实分布,loss固定不变。
修复方案:将输出层激活改为linear(回归任务默认选择):
Dense(1, activation='linear')
4. 数据预处理缺失或异常
- 检查输入特征是否做了标准化/归一化:时间序列数据尺度差异过大,会导致模型难以收敛;
- 验证标签是否存在异常:比如所有标签值完全相同,这种情况下loss会固定不变;
- 确认数据维度匹配模型输入:确保训练数据形状为
(样本数, 24, 20),标签为(样本数, 1)。
5. 模型结构的潜在问题
- 可尝试移除
MaxPool1D,验证是否是池化导致信息丢失过多; - 调整dropout比例:若数据集较小,过高的dropout可能导致模型无法学习有效特征。
修复后的完整代码示例
def generate_model(): model = keras.models.Sequential([ Conv1D(64, 3, padding='causal', activation='relu', input_shape=(24, 20)), BatchNormalization(), Conv1D(64, 3, padding='causal', activation='relu'), BatchNormalization(), Conv1D(32, 3, padding='causal', activation='relu'), MaxPool1D(3), LSTM(100, dropout=0.2, return_sequences=True), LSTM(50, dropout=0.3), Dense(1, activation='linear') # 改为linear激活 ]) model.compile(optimizer=tf.keras.optimizers.Adam(), loss='mean_squared_error', metrics=[tf.keras.metrics.MeanAbsoluteError(), tf.keras.metrics.RootMeanSquaredError(), RSquare()]) return model # 修复后的回调函数 from keras.callbacks import LearningRateScheduler def decay_schedule(epoch, lr): min_lr = 1e-6 lr = max(lr - 0.0001, min_lr) return lr lr_scheduler = LearningRateScheduler(decay_schedule) # 修正mode为min callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min', min_delta=1e-3, patience=50) callbacks=[lr_scheduler, callback] # 训练模型 history1 = model1.fit(X1_train, y1_train, epochs=200, batch_size=32, validation_data=(X1_test, y1_test), verbose=2, callbacks=callbacks)
内容的提问来源于stack exchange,提问作者NavidReza Ghanbari
相关产品推荐
相关产品推荐

