使用LSTM训练连续特征预测数值时出现NaN损失与精度问题求助
问题分析与解决方案
1. 移除错误的评估指标
你在回归任务中使用了accuracy指标,这是分类任务专属指标,完全不适用于连续值回归。因为回归的预测值和真实值几乎不可能完全相等,计算accuracy会得到0或NaN,毫无意义。应该替换为回归任务的指标,比如mean_absolute_error(MAE)、mean_squared_error(MSE)。
2. 修改输出层激活函数
输出层使用relu会导致两个问题:
- 若模型训练中输出负数,会被ReLU截断为0,破坏连续值的预测逻辑;
- 可能引发梯度消失,导致loss变为NaN。
回归任务的输出层应使用线性激活(linear),也就是不设置激活函数(Keras中Dense默认激活是linear)。
3. 强制归一化/标准化输入输出数据
你的输入特征数值范围差异极大(前三个特征是1e4级别,第四个是4e7级别),这种数据会导致模型训练时梯度爆炸,直接引发NaN。必须对输入和输出做归一化处理:
- 对X_train、X_test用同一个Scaler拟合转换;
- 对y_train、y_test用另一个Scaler拟合转换(预测后可以反转换回原始尺度)。
4. 调整LSTM层的激活函数
LSTM层默认激活是tanh,更适合循环网络的长期依赖学习。使用relu容易导致梯度消失,建议换回tanh。
完整修正代码示例
from sklearn.preprocessing import StandardScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dropout, BatchNormalization, Dense from tensorflow.keras.optimizers import Adam import numpy as np # ---------------------- 数据归一化 ---------------------- # 处理输入特征:先把(1551,4,1)转成(1551,4),拟合后再转回原形状 scaler_X = StandardScaler() X_train_reshaped = X_train.reshape(X_train.shape[0], X_train.shape[1]) X_train_scaled = scaler_X.fit_transform(X_train_reshaped).reshape(X_train.shape) X_test_reshaped = X_test.reshape(X_test.shape[0], X_test.shape[1]) X_test_scaled = scaler_X.transform(X_test_reshaped).reshape(X_test.shape) # 处理输出标签 scaler_y = StandardScaler() y_train_scaled = scaler_y.fit_transform(y_train) y_test_scaled = scaler_y.transform(y_test) # ---------------------- 构建模型 ---------------------- model = Sequential() # LSTM换回默认tanh激活,移除手动设置的relu model.add(LSTM(128, input_shape=(X_train.shape[1], X_train.shape[2]), return_sequences=False)) model.add(Dropout(0.2)) model.add(BatchNormalization()) model.add(Dense(32, activation='relu')) # 输出层用线性激活(默认,可不写) model.add(Dense(1)) # 编译时用回归指标替换accuracy,可按需降低学习率 model.compile(loss='mean_squared_error', optimizer=Adam(learning_rate=1e-4), metrics=['mean_absolute_error']) model.summary() # ---------------------- 训练模型 ---------------------- model.fit(X_train_scaled, y_train_scaled, validation_data=(X_test_scaled, y_test_scaled), epochs=100, batch_size=128) # ---------------------- 预测并反转换回原始尺度 ---------------------- y_pred_scaled = model.predict(X_test_scaled) y_pred = scaler_y.inverse_transform(y_pred_scaled)
额外注意事项
- 若归一化后仍出现NaN,可尝试减小batch_size(比如32或64);
- 提前检查数据中是否存在NaN或无穷大值,清理后再训练;
- 若梯度仍不稳定,可添加梯度裁剪(比如在Adam中设置
clipvalue=1.0)。
内容的提问来源于stack exchange,提问作者Jade D. Nightshade
相关产品推荐
相关产品推荐

