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

使用GridSearchCV调优LSTM超参数时出现NaN精度问题求助

问题分析与代码修正

你的代码出现NaN精度值,主要是以下几个关键错误导致的,逐一修正如下:

1. 时间序列数据拆分错误

train_test_split会随机打乱数据,破坏时间序列的时序性,必须改用TimeSeriesSplit做时间序列的交叉验证,训练集拆分也要保持时序顺序,不能随机打乱。

2. LSTM输入形状不匹配

LSTM要求输入是三维数组:(样本数, 时间步长n_steps, 特征数n_features),但你当前的X_train是二维数组,需要先将数据转换成LSTM需要的时序格式。

3. 回归任务误用分类评分指标

你的任务是回归(预测连续值rn_val),但GridSearchCV里指定了分类任务的scoring="accuracy",这会导致评分计算错误,出现NaN。应该用回归类评分指标,比如'neg_mean_squared_error'(sklearn中回归指标常用负值,因为默认规则是分数越高模型越好)。

4. 目标变量未归一化

输入数据做了MinMaxScaler归一化,但目标变量target还是原始尺度,和输入尺度不匹配,容易导致训练不稳定,出现NaN或梯度爆炸。需要对目标变量也做归一化,后续预测时再反转换回原始尺度。


修正后的完整代码

import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import TimeSeriesSplit, GridSearchCV
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.wrappers.scikit_learn import KerasRegressor
import warnings
warnings.filterwarnings('ignore')

# Load and preprocess the dataset
data = pd.read_csv("dataset.csv")  # 替换为实际路径
target_col = 'rn_val'

# 分离特征和目标
features = data.drop(target_col, axis=1).values
target = data[target_col].values.reshape(-1, 1)  # 转成二维方便归一化

# 归一化特征和目标
scaler_features = MinMaxScaler()
scaler_target = MinMaxScaler()
features_normalized = scaler_features.fit_transform(features.astype(float))
target_normalized = scaler_target.fit_transform(target)

# 将数据转换为LSTM需要的时序格式:(样本数, n_steps, n_features)
def create_sequences(data, target, n_steps):
    X, y = [], []
    for i in range(n_steps, len(data)):
        X.append(data[i-n_steps:i, :])
        y.append(target[i, 0])
    return np.array(X), np.array(y)

n_steps = 7  # 时间步长
n_features = features_normalized.shape[1]
X, y = create_sequences(features_normalized, target_normalized, n_steps)

# 时间序列交叉验证策略
tscv = TimeSeriesSplit(n_splits=3)

# 定义LSTM模型
def create_lstm_model(neurons, optimizer, activation):
    model = Sequential()
    model.add(LSTM(units=neurons, input_shape=(n_steps, n_features)))
    model.add(Dense(1, activation=activation))
    model.compile(loss='mse', optimizer=optimizer)
    return model

# 网格搜索参数
param_grid = {
    'neurons': [8, 16, 32, 64],
    'optimizer': ['RMSprop', 'Adam'],
    'activation': ['relu', 'tanh', 'linear']
}

# 包装Keras模型为sklearn兼容的回归器
model = KerasRegressor(build_fn=create_lstm_model, epochs=10, batch_size=16, verbose=0)

# 初始化网格搜索:使用回归评分指标,时间序列交叉验证
grid = GridSearchCV(
    estimator=model,
    param_grid=param_grid,
    cv=tscv,
    refit=True,  # 训练完成后用最佳参数重新训练整个数据集
    scoring='neg_mean_squared_error',
    n_jobs=-1
)

# 执行网格搜索
grid_result = grid.fit(X, y)

# 输出结果
print(f"最佳负MSE: {grid_result.best_score_:.4f} 使用参数: {grid_result.best_params_}")

means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
    print(f"{mean:.4f} ({stdev:.4f}) 参数: {param}")

额外说明

  • 时序数据转换函数create_sequences:遍历数据,每次取前n_steps个时间步的特征作为输入,对应下一个时间步的目标值作为标签,这是时间序列预测的标准做法。
  • 目标变量归一化后,后续预测时需要用scaler_target.inverse_transform()将预测值转换回原始尺度。
  • 减少了部分参数组合(比如去掉128神经元、SGD、swish等),可以加快网格搜索速度,你可以根据需求再加回来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:45:09