LSTM训练GE雅虎股票数据集时Loss值无变化求技术支援
LSTM训练GE股票数据时Loss值无变化问题排查
问题概述
训练GE股票收盘价预测模型时,训练与验证Loss始终维持在固定区间波动,无明显下降趋势,模型无法有效学习数据规律。训练输出如下:
Epoch 1/5
396/396 ━━━━━━━━━━━━━━━━━━━━ 23s 47ms/step - loss: 0.1633 - val_loss: 0.3750
Epoch 2/5
396/396 ━━━━━━━━━━━━━━━━━━━━ 19s 48ms/step - loss: 0.1661 - val_loss: 0.3752
Epoch 3/5
396/396 ━━━━━━━━━━━━━━━━━━━━ 18s 45ms/step - loss: 0.1681 - val_loss: 0.3578
Epoch 4/5
396/396 ━━━━━━━━━━━━━━━━━━━━ 26s 66ms/step - loss: 0.1644 - val_loss: 0.3724
Epoch 5/5
396/396 ━━━━━━━━━━━━━━━━━━━━ 21s 52ms/step - loss: 0.1663 - val_loss: 0.3817
Loss曲线特征:训练Loss在0.16上下小幅波动,验证Loss在0.35-0.38区间波动,无持续下降迹象。
核心问题分析
- 模型结构严重错位:你搭建的是序列自编码器架构(含
RepeatVector、返回序列的LSTM、TimeDistributed层),但任务是单步时间序列预测(用前30天数据预测下一天收盘价)。自编码器输出是和输入等长的序列(30个时间步),但训练标签trainY是单值,维度不匹配导致Loss计算逻辑异常,模型权重无法有效更新。 - 未定义变量隐患:代码中
model = build_model(desired_learning_rate)的desired_learning_rate未定义,若未手动补全会直接报错,实际运行时只能使用默认学习率,若学习率不合适也会阻碍Loss下降。 - 数据处理隐患:用
iloc修改train/test的Close列时,存在潜在的SettingWithCopyWarning,可能导致数据赋值未生效或异常。
修复方案及完整代码
1. 重构模型为单步预测结构
移除自编码器相关层,直接用LSTM提取特征后输出单值,匹配单步预测任务。
2. 修正数据处理与变量问题
修复后代码:
import numpy as np from keras.layers import LSTM, Input, Dropout, Dense import pandas as pd import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler from keras.models import Sequential import seaborn as sns from keras.optimizers import Adam import warnings warnings.filterwarnings("ignore") # 读取并预处理数据 dataframe = pd.read_csv("DataSets/GE.csv") df = dataframe[['Date', 'Close']] df['Date'] = pd.to_datetime(df['Date']) sns.lineplot(x=df['Date'], y=df['Close']) # 划分训练测试集(加copy避免赋值警告) train = df.loc[df['Date'] <= pd.to_datetime('2017-12-31')].copy() test = df.loc[df['Date'] > pd.to_datetime('2017-12-31')].copy() # 归一化处理 scaler = MinMaxScaler() scaler.fit(train[['Close']]) train['Close'] = scaler.transform(train[['Close']]) test['Close'] = scaler.transform(test[['Close']]) seq_size = 30 # 生成序列数据 def to_sequences(x, y, seq_size_func=1): x_values = [] y_values = [] for i in range(len(x)-seq_size_func): x_values.append(x.iloc[i:(i+seq_size_func)].values) y_values.append(y.iloc[i+seq_size_func]) return np.array(x_values), np.array(y_values) trainX, trainY = to_sequences(train[['Close']], train['Close'], seq_size) testX, testY = to_sequences(test[['Close']], test['Close'], seq_size) input_shape = (trainX.shape[1], trainX.shape[2]) # 构建单步预测LSTM模型 def build_model(learning_rate=0.001): model_f = Sequential() model_f.add(Input(shape=input_shape)) model_f.add(LSTM(128, activation='relu')) model_f.add(Dropout(rate=0.2)) # 输出单值对应下一天收盘价 model_f.add(Dense(1)) optimizer = Adam(learning_rate=learning_rate) model_f.compile(optimizer=optimizer, loss='mae') return model_f # 初始化模型(指定学习率) model = build_model(learning_rate=0.001) # 增加训练轮次,LSTM需要足够轮次学习 history = model.fit(trainX, trainY, epochs=20, batch_size=32, validation_split=0.1, verbose=1) # 绘制Loss曲线 plt.figure(figsize=(10,6)) plt.plot(history.history['loss'], label='训练Loss') plt.plot(history.history['val_loss'], label='验证Loss') plt.xlabel('训练轮次') plt.ylabel('MAE损失') plt.legend() plt.show()
额外优化建议
- 调整训练轮次:原代码仅训练5轮,LSTM通常需要20-50轮才能充分学习,可逐步增加轮次观察Loss变化。
- 调优模型参数:尝试调整LSTM单元数(64/256)、Dropout率(0.1/0.3)、学习率(0.0001/0.005),找到最优参数组合。
- 扩展输入特征:加入开盘价、最高价、最低价、成交量等特征,提升模型对市场的感知能力。
- 数据校验:检查数据集是否存在缺失值、异常值,必要时进行填充或剔除,避免数据质量问题影响模型学习。
内容的提问来源于stack exchange,提问作者PARTH PETKAR
相关产品推荐
相关产品推荐

