基于LSTM的NDVI时间序列预测:如何实现超测试集未来值预测?
LSTM时间序列未来值预测解决方案(NDVI数据集)
问题背景
基于LSTM搭建的NDVI时间序列模型,在历史数据的训练、验证和测试环节表现正常,但无法实现测试集之外的多步未来值预测。
核心思路
未来预测的关键是滚动迭代:用模型预测出的下一个值,补充到输入序列中,再用新序列预测下一个时间步,循环往复得到多步结果。另外必须补充数据归一化步骤,避免数值分布偏差导致预测失真。
代码优化与预测实现
第一步:补充数据归一化
原代码未做归一化,这会导致未来预测时数值分布偏离训练数据,先修改数据预处理部分:
import tensorflow as tf import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler import matplotlib.pyplot as plt df = pd.read_csv(r'NDVI.csv') df.index = pd.to_datetime(df['Date time'], format='%m/%d/%Y') NDVI = df['NDVI'] # 数据归一化(必须用训练数据拟合scaler) scaler = MinMaxScaler(feature_range=(0,1)) NDVI_scaled = scaler.fit_transform(NDVI.values.reshape(-1,1)).flatten() def df_to_X_y(df, window_size=3): df_as_np = df X = [] y = [] for i in range(len(df_as_np)-window_size): row = [[a] for a in df_as_np[i:i+window_size]] X.append(row) label = df_as_np[i+window_size] y.append(label) return np.array(X), np.array(y) WINDOW_SIZE=3 X,y= df_to_X_y(NDVI_scaled, WINDOW_SIZE) # 划分数据集 X_train, y_train = X[:410], y[:410] X_val, y_val= X[410:456], y[410:456] X_test, y_test = X[456:], y[456:]
第二步:训练模型(保留原模型结构,复用即可)
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import * from tensorflow.keras.callbacks import ModelCheckpoint from tensorflow.keras.losses import MeanSquaredError from tensorflow.keras.metrics import RootMeanSquaredError from tensorflow.keras.optimizers import Adam model1 = Sequential() model1.add(InputLayer((WINDOW_SIZE, 1))) model1.add(LSTM(64)) model1.add(Dense(8, 'relu')) model1.add(Dense(1, 'linear')) cp = ModelCheckpoint('NDVImodel/', save_best_only=True) model1.compile(loss=MeanSquaredError(), optimizer=Adam(learning_rate=0.01), metrics=[RootMeanSquaredError()]) model1.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=20, callbacks=[cp])
第三步:实现未来滚动预测
def predict_future(model, last_sequence, steps, window_size): predictions = [] current_sequence = last_sequence.copy() for _ in range(steps): # 预测单步值 next_val = model.predict(current_sequence.reshape(1, window_size, 1), verbose=0)[0][0] predictions.append(next_val) # 更新序列:丢弃最旧值,加入新预测值 current_sequence = np.roll(current_sequence, -1) current_sequence[-1] = next_val # 反归一化还原真实NDVI值 return scaler.inverse_transform(np.array(predictions).reshape(-1,1)).flatten() # 获取历史数据最后一个窗口的序列(作为预测起点) last_history_sequence = NDVI_scaled[-WINDOW_SIZE:] # 设定要预测的未来步数 future_steps = 10 # 执行预测 future_predictions = predict_future(model1, last_history_sequence, future_steps, WINDOW_SIZE) # 可视化结果 plt.figure(figsize=(12,6)) # 绘制历史NDVI数据 plt.plot(df.index, NDVI, label='历史NDVI') # 生成未来日期序列(假设原数据是日频,可根据实际调整freq参数) future_dates = pd.date_range(start=df.index[-1], periods=future_steps+1, freq='D')[1:] # 绘制未来预测值 plt.plot(future_dates, future_predictions, label='未来预测', linestyle='--', color='#ff4444') plt.legend() plt.title('NDVI历史数据与未来预测') plt.show()
关键注意事项
- 归一化必须用训练数据拟合的scaler,不能对测试集或未来数据重新拟合,否则会引入数据泄露
- 多步预测的误差会随步数增加累积,建议控制预测步数(比如10-30步),或改用Seq2Seq结构的LSTM模型优化长序列预测
- 可尝试调整窗口大小(比如增大到7、14),让模型捕获更长时间的时序规律,提升预测稳定性
内容的提问来源于stack exchange,提问作者FF123456
相关产品推荐
相关产品推荐

