You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于两篇论文的LSTM模型输入形状异常及精度停滞问题排查

外汇预测LSTM模型精度卡57%的修复方案

核心问题拆解与修复步骤

1. 修正LSTM输入形状(最关键问题)

LSTM标准输入格式为(样本数量, 时间步长, 特征数量),当前代码完全颠倒了时间步与特征的维度:

  • 错误逻辑:将所有特征列当作时间步,输入形状设为(ColNum, 1),相当于把每个特征单独作为一个时间步,仅用1个特征喂给模型。
  • 正确逻辑:以连续N天的完整特征数据作为一个训练样本(建议和30天预测周期匹配),输入形状应为(时间窗口大小, 特征数量)。

具体实现:

# 定义时间窗口大小(与预测周期对齐)
TIME_STEPS = 30

# 构造时间序列样本
def create_sequences(X, y, time_steps):
    X_seq, y_seq = [], []
    for i in range(len(X) - time_steps):
        X_seq.append(X[i:i+time_steps])
        y_seq.append(y[i+time_steps])  # 对应当前样本30天后的涨跌标签
    return np.array(X_seq), np.array(y_seq)

# 数据标准化(LSTM对数据尺度敏感,必须步骤)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 生成序列数据
X_seq, y_seq = create_sequences(X_scaled, y, TIME_STEPS)

2. 修正损失函数与输出层

任务为二分类(标签0/1),当前代码的损失函数与输出层完全不匹配:

  • 替换categorical_crossentropy为binary_crossentropy
  • 输出层激活函数从tanh改为sigmoid(二分类专用)
  • 若严格匹配论文的softmax层,需将标签转为one-hot编码,使用sparse_categorical_crossentropy+Dense(2, activation='softmax'),但二分类场景下sigmoid更简洁。

3. 对齐第一篇论文的模型结构

  • 给所有LSTM层添加-0.2到0.2范围的权重初始化
  • 移除冗余的InputLayer(Sequential模型中第一个LSTM层的input_shape已足够)
  • 保留论文要求的5层LSTM(每层31个单元)+Dropout+全连接层结构

4. 修正EarlyStopping参数

min_delta=1要求精度提升100%才停止,完全不合理,改为min_delta=0.001并添加patience防止过早停止:

es = EarlyStopping(monitor='val_accuracy', mode='max', min_delta=0.001, patience=10, restore_best_weights=True)

5. 实现第二篇论文的两种最优方案

  • 方案1:tanh激活+Adam优化器(匹配第一篇论文)
  • 方案2:线性激活+Adamax优化器(匹配第二篇论文)

修正后的完整代码

方案1:tanh+Adam(匹配第一篇论文)

import numpy as np
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM
from keras.optimizers import Adam, Adamax
from tensorflow.keras import initializers
from keras.callbacks import EarlyStopping
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 加载数据
df = pd.read_csv(r'C:...categorical.csv', index_col=False)
df.index = df.pop('Date')
ColNum = len(df.columns) - 1  # 特征列数量

X = df.iloc[:, :ColNum].values
y = df.iloc[:, ColNum].values

# 1. 数据标准化+构造时间序列样本
TIME_STEPS = 30
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

def create_sequences(X, y, time_steps):
    X_seq, y_seq = [], []
    for i in range(len(X) - time_steps):
        X_seq.append(X[i:i+time_steps])
        y_seq.append(y[i+time_steps])
    return np.array(X_seq), np.array(y_seq)

X_seq, y_seq = create_sequences(X_scaled, y, TIME_STEPS)

# 拆分训练集验证集(时间序列不能打乱)
X_train, X_val, y_train, y_val = train_test_split(X_seq, y_seq, test_size=0.2, shuffle=False)

# 2. 构建符合论文的模型
model = Sequential()
# 5层LSTM,每层31个单元,权重初始化-0.2到0.2
model.add(LSTM(31, return_sequences=True, input_shape=(TIME_STEPS, ColNum), 
               activation='tanh', kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='tanh', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='tanh', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='tanh', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, activation='tanh', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(Dropout(0.2))
# 二分类用sigmoid,若要严格匹配论文softmax,需将y转为one-hot编码后用Dense(2, activation='softmax')
model.add(Dense(units=1, activation='sigmoid', 
                kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))

# 3. 编译模型
model.compile(optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])

# 4. 训练模型
es = EarlyStopping(monitor='val_accuracy', mode='max', min_delta=0.001, patience=10, restore_best_weights=True)
model.fit(X_train, y_train, batch_size=32, epochs=90, validation_data=(X_val, y_val), callbacks=[es])

方案2:线性激活+Adamax(匹配第二篇论文)

只需修改模型的激活函数与优化器:

# 构建模型部分修改
model = Sequential()
model.add(LSTM(31, return_sequences=True, input_shape=(TIME_STEPS, ColNum), 
               activation='linear', kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='linear', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='linear', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, return_sequences=True, activation='linear', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(LSTM(31, activation='linear', 
               kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))
model.add(Dropout(0.2))
model.add(Dense(units=1, activation='sigmoid', 
                kernel_initializer=initializers.RandomUniform(minval=-0.2, maxval=0.2)))

# 编译部分修改
model.compile(optimizer=Adamax(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])

额外优化建议

  • 检查标签分布:如果57%是样本中多数类的占比,说明模型在随机猜测,需处理类别不平衡(用SMOTE、类别权重等)
  • 调整时间窗口大小:尝试15/60天等不同窗口,匹配数据规律
  • 基线函数适配:第一篇论文提到的基线函数b更新率0.8,若为强化学习场景可加入奖励机制,监督学习场景可忽略或转为加权损失

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 00:04:03