使用LSTM做回归训练遇耗时久、Loss变为NaN问题求助
LSTM回归任务:解决训练耗时久、Loss变为NaN的问题
核心问题拆解
- 输入维度不匹配:LSTM要求输入格式为
(样本数, 时间步长, 特征数),你的X_train是(m,1280),但模型定义的input_shape=(1280,1)需要每个样本是1280个时间步、单特征的结构,输入维度不匹配直接导致计算逻辑异常。 - 样本量与Batch Size严重不合理:仅10个训练样本完全不足以支撑LSTM的训练;同时
batch_size=32大于样本数,训练时用全样本做单次更新,梯度波动极大,极易触发NaN。 - 数据未归一化:输入X范围0-3.5,输出Y范围70-150,数值跨度差异悬殊,初始Loss(约12701)远高于正常范围,训练中极易引发梯度爆炸,最终导致Loss变为NaN。
- 模型结构冗余:1280个时间步搭配两层128单元的LSTM,计算量巨大,直接造成每个epoch耗时过长。
针对性解决方案
1. 修正输入维度
将输入reshape为LSTM要求的格式:
X_train = np.random.uniform(0, 3.5,(m,1280)) # 新增特征维度,转为(m, 1280, 1) X_train = X_train.reshape(m, 1280, 1)
2. 调整样本量与Batch Size
- 至少将训练样本数提升至1000+(模拟数据可直接设
m=1000); - 设置合理Batch Size,比如
batch_size=16或32,必须小于样本总数。
3. 数据归一化
对输入输出做归一化,压缩数值范围避免梯度爆炸:
from sklearn.preprocessing import MinMaxScaler # 归一化X到0-1区间 scaler_X = MinMaxScaler(feature_range=(0,1)) X_train = scaler_X.fit_transform(X_train.reshape(m, 1280)).reshape(m, 1280, 1) # 归一化Y到0-1区间 scaler_Y = MinMaxScaler(feature_range=(0,1)) Y_train = scaler_Y.fit_transform(Y_train)
预测时需用scaler_Y.inverse_transform()将结果还原回70-150的原始范围。
4. 简化模型结构
减少LSTM单元数或层数,降低计算负载:
model = Sequential() # 单层LSTM,单元数降至32 model.add(LSTM(units=32, activation='relu', input_shape=(1280, 1))) model.add(Dropout(0.3)) model.add(Dense(1)) # 回归任务用线性激活,避免relu截断输出 model.add(Activation('linear'))
5. 梯度稳定优化
- 降低学习率至
0.0001,减缓梯度更新速度; - 添加梯度裁剪,限制梯度范围防止爆炸:
optimizer = tensorflow.keras.optimizers.Adam(learning_rate=0.0001, clipnorm=1.0) model.compile(loss='mean_squared_error', optimizer=optimizer)
完整修正代码示例
import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dropout, Dense, Activation from sklearn.preprocessing import MinMaxScaler # 提升样本量 m = 1000 X_train = np.random.uniform(0, 3.5,(m,1280)) Y_train = np.random.uniform(70, 150,(m,1)) # 数据归一化 scaler_X = MinMaxScaler(feature_range=(0,1)) X_train = scaler_X.fit_transform(X_train).reshape(m, 1280, 1) scaler_Y = MinMaxScaler(feature_range=(0,1)) Y_train = scaler_Y.fit_transform(Y_train) # 构建简化模型 model = Sequential() model.add(LSTM(units=32, activation='relu', input_shape=(1280, 1))) model.add(Dropout(0.3)) model.add(Dense(1)) model.add(Activation('linear')) # 带梯度裁剪的优化器 optimizer = tensorflow.keras.optimizers.Adam(learning_rate=0.0001, clipnorm=1.0) model.compile(loss='mean_squared_error', optimizer=optimizer) # 启动训练 model.fit(X_train, Y_train, epochs=100, batch_size=32, shuffle=True, verbose=1)
内容的提问来源于stack exchange,提问作者Mohadeseh
相关产品推荐
相关产品推荐

