这是我的第419篇原创文章。
一、引言
将LSTM与决策树结合形成“混合时间序列预测模型,可以更好地建模实际数据中的复杂性。
模型结构:
-
第一阶段:使用LSTM模型对时间序列进行主预测;
-
第二阶段:利用决策树回归器学习LSTM的残差(预测误差);
-
组合预测:最终预测值 = LSTM预测 + 决策树预测残差。
数据流流程:
-
模拟生成时间序列(含多周期、季节性和噪声);
-
将序列切片为监督学习格式;
-
使用80%的前序数据训练模型(严格时间顺序,避免数据泄露);
-
剩余20%作为测试集;
-
可视化与分析模型效果。
二、实现过程
2.1 读取时间序列数据
核心代码:
data = pd.DataFrame(pd.read_csv('data.csv'))
print(data.head())
y = data['Passengers'].values
2.2 构造监督学习问题
核心代码:
def create_sequences(data, seq_length):
X, y = [], []
for i in range(len(data) - seq_length):
X.append(data[i:i+seq_length])
y.append(data[i+seq_length])
return np.array(X), np.array(y)
seq_length = 7
X, y_target = create_sequences(y, seq_length)
# 分为训练集和测试集(避免未来信息泄露)
split_index = int(len(X) * 0.8)
X_train, y_train = X[:split_index], y_target[:split_index]
X_test, y_test = X[split_index:], y_target[split_index:]
2.3 构建LSTM模型
核心代码:
class LSTMRegressor(nn.Module):
def __init__(self, input_size=1, hidden_size=50, num_layers=1):
super(LSTMRegressor, self).__init__()
self.hidden_size = hidden_size
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, 1)
def forward(self, x):
out, _ = self.lstm(x)
out = self.fc(out[:, -1, :])
return out
2.4 模型训练
核心代码:
num_epochs = 1000
loss_list = []
for epoch in range(num_epochs):
model.train()
total_loss = 0
for seqs, targets in train_loader:
optimizer.zero_grad()
outputs = model(seqs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
total_loss += loss.item()
avg_loss = total_loss / len(train_loader)
loss_list.append(avg_loss)
if epoch % 10 == 0:
print(f"Epoch [{epoch}/{num_epochs}], Loss: {avg_loss:.4f}")
训练损失下降曲线:
可见损失逐步下降并趋于稳定,说明模型成功学习了时间序列结构,若呈震荡或上升趋势,需重新调整模型参数或学习率。
2.5 LSTM预测 + 决策树增强
核心代码:
model.eval()
X_test_tensor = torch.tensor(X_test, dtype=torch.float32).unsqueeze(-1)
lstm_preds = model(X_test_tensor).detach().numpy().flatten()
# 决策树基于LSTM残差预测
residuals = y_test - lstm_preds
# 特征扩展
X_tree_train = lstm_preds.reshape(-1, 1)
model_tree = DecisionTreeRegressor(max_depth=3)
model_tree.fit(X_tree_train, residuals)
residual_preds = model_tree.predict(X_tree_train)
final_preds = lstm_preds + residual_preds
2.6 可视化分析
图1:LSTM预测 vs 真实值。对比基本LSTM模型的预测能力与实际时间序列。
核心代码:
plt.figure(figsize=(10, 4))
plt.plot(y_test, label="True", color='blue')
plt.plot(lstm_preds, label="LSTM Prediction", color='orange')
plt.title("LSTM vs True Value")
plt.legend()
plt.grid(True)
plt.show()
结果:
蓝线表示真实测试数据;橙线表示LSTM模型的输出;曲线整体趋势相似,但在局部波动、高频变化点存在一定误差。可以看到,LSTM能捕捉主要趋势,但对复杂结构建模仍有欠缺。
图2:混合模型预测 vs 真实值:展示LSTM+决策树混合模型的预测结果与真实值对比。
核心代码:
plt.figure(figsize=(10, 4))
plt.plot(y_test, label="True", color='blue')
plt.plot(final_preds, label="LSTM + Tree Hybrid", color='green')
plt.title("Hybrid Model vs True Value")
plt.legend()
plt.grid(True)
plt.show()
结果:
绿色曲线为混合模型预测,显著比单一LSTM更贴合真实值,尤其是在转折点、局部波动处。可以看到,混合模型能有效纠正LSTM预测误差,增强模型表达能力。
图3:残差分布对比:对比LSTM与混合模型的预测残差分布,分析误差收敛情况。
核心代码:
plt.figure(figsize=(10, 4))
sns.histplot(y_test - lstm_preds, color='red', label='LSTM Residuals', kde=True)
sns.histplot(y_test - final_preds, color='green', label='Hybrid Residuals', kde=True)
plt.title("Residual Distribution: LSTM vs Hybrid")
plt.legend()
plt.grid(True)
plt.show()
结果:
红色直方图为LSTM残差,绿色直方图为混合模型残差;可以看到混合模型的残差更集中于0附近,分布更窄。可以看到,决策树成功捕捉了LSTM无法建模的残差模式。
作者简介:
读研期间发表6篇SCI数据挖掘相关论文,现在某研究院从事数据算法相关科研工作,结合自身科研实践经历不定期分享关于Python、机器学习、深度学习、人工智能系列基础知识与应用案例。致力于只做原创,以最简单的方式理解和学习,关注我一起交流成长。需要数据集和源码的小伙伴可以关注底部公众号添加作者微信。