LSTM与Transformer时间序列预测:原理到PyTorch实战
2026/8/27 23:42:51 网站建设 项目流程

最近在B站刷到很多关于LSTM和Transformer做时间序列预测的视频,评论区经常出现的几类问题就是:这两个模型到底解决了什么问题?它们之间是什么关系?论文里那些公式是怎么回事?为什么别人跑得通的代码,到自己电脑上就报错或者不收敛?

这篇文章会一次性把LSTM和Transformer这两大时间序列预测模型的来龙去脉讲清楚,并且用PyTorch从零到一复现完整的预测流程。不管你是刚接触机器学习的新手,还是在做电量预测、流量监控、股票价格分析等业务项目的开发者,这篇文章都能给你一份可以直接上手的参考。

文章内容分为两大块:先是论文核心思路的通俗拆解,再是完整的代码复现,包括数据构造、模型定义、训练评估和可视化对比。

1. LSTM与Transformer为什么是时序预测的“标配”

时间序列预测并不是一个新概念。传统方法里有ARIMA、移动平均、指数平滑等统计模型,它们在小规模、平稳性较强的数据上表现尚可。但一旦数据规模变大、非线性增强、存在长期依赖关系,传统模型就显得力不从心。深度学习的出现,尤其是循环神经网络(RNN)家族的崛起,让时间序列预测进入了一个新阶段。

LSTM(Long Short-Term Memory,长短期记忆网络)是RNN的一种改进结构,它通过引入门控机制,解决了RNN在长序列训练中容易出现的梯度消失和梯度爆炸问题。你可以把LSTM理解为“一个懂得什么时候记住、什么时候遗忘的神经网络”,它非常适合处理具有时间顺序、前后关联的数据。

Transformer则是2017年由Google团队在论文《Attention Is All You Need》中提出的架构。它最初用于机器翻译,但随后迅速席卷了NLP、CV、语音等多个领域。Transformer的核心是自注意力机制(Self-Attention),它可以让模型在计算某个位置的输出时,同时关注序列中所有其他位置的信息,而不是像RNN那样只能按顺序一步步向后传递。

很多初学者会问:既然LSTM已经在时序任务上表现很好,为什么还要用Transformer?

答案是:LSTM虽然能建模时间依赖,但它本质上是串行计算的,随着序列长度增加,训练效率会明显下降,而且长期依赖的建模能力依然有限。Transformer通过注意力机制实现了并行计算,并且可以捕捉更长距离的依赖关系。在数据量足够大的条件下,Transformer在很多时序任务上都能超过LSTM。

不过要注意,这并不意味着LSTM已经过时。在中小规模数据集、业务模型快速迭代、计算资源有限的情况下,LSTM依然是一个极其稳定、好用的基线模型。实际工程中,把LSTM作为baseline,再把Transformer作为进阶方案,是一种很常见的做法。

这也正是本文把两个模型放在一起讲的原因:你先理解LSTM的门控思想,再理解Transformer的注意力机制,两者对比着学,会比单独学任何一个都更深刻。

2. 环境准备与数据集构造

复现文章里的代码之前,先确认一下运行环境。本文使用PyTorch作为深度学习框架,代码在以下环境中验证通过:

依赖建议版本说明
Python3.8 及以上推荐 3.9 或 3.10
PyTorch1.9 及以上Transformer 的batch_first=True需要较新版本
NumPy1.21 及以上数据处理
Pandas1.3 及以上数据读取和预处理
scikit-learn1.0 及以上数据标准化
Matplotlib3.5 及以上可视化
pip install torch numpy pandas scikit-learn matplotlib

为了让大家能直接跑通代码,这里使用一条合成时间序列来演示,它包含多个周期性成分、一个缓慢上升的趋势项以及随机噪声,非常接近真实业务中“趋势+周期+噪声”的数据结构。

import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler np.random.seed(42) torch.manual_seed(42) # 生成时间序列:两个周期性成分 + 上升趋势 + 噪声 t = np.arange(0, 1000, 0.1) season1 = np.sin(t) season2 = np.sin(0.3 * t) trend = 0.0005 * t noise = 0.1 * np.random.randn(len(t)) data = season1 + season2 + trend + noise plt.figure(figsize=(12, 4)) plt.plot(data[:500]) plt.title("示例时间序列(前500个点)") plt.show()

运行后会得到一条看起来有一定规律、又带噪声的曲线。接下来对它做标准化处理,然后构造滑动窗口样本。

3. LSTM 原理拆解与 PyTorch 实现

3.1 从RNN到LSTM:门控机制到底在解决什么

RNN(循环神经网络)的核心思想是“循环”:每一步的隐藏状态不仅由当前输入决定,还由上一步的隐藏状态决定。这样网络就有了“记忆力”。

但标准RNN在反向传播时,梯度需要沿着时间步不断连乘。如果序列较长,梯度很容易指数级缩小或增大,这就是梯度消失/梯度爆炸问题。梯度一消失,网络就无法学习到远距离的依赖关系。

LSTM的论文发表于1997年,作者是Hochreiter和Schmidhuber。它的思路是引入一条“细胞状态”(Cell State),就像一条传送带,贯穿整个序列。这条传送带上可以轻松传递信息,而门控结构决定“记住什么、遗忘什么、输出什么”。

LSTM有三个门:

  • 遗忘门:决定上一时刻的细胞状态中,哪些信息要丢弃。
  • 输入门:决定当前时刻的新信息中,哪些要写入细胞状态。
  • 输出门:决定当前时刻的细胞状态中,哪些信息要输出到隐藏状态。

每个门都是一个sigmoid函数加一个逐元素乘法。sigmoid的输出在0到1之间,相当于一个开关程度:0表示彻底关闭,1表示完全打开。

公式如下:

遗忘门: ( f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) )

输入门: ( i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) )

候选状态: ( \tilde{C}t = \tanh(W_C \cdot [h{t-1}, x_t] + b_C) )

细胞状态更新: ( C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t )

输出门: ( o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) )

隐藏状态: ( h_t = o_t \odot \tanh(C_t) )

初学者看到公式不用紧张。你只需要知道:LSTM通过“门”控制信息流通,让梯度可以沿着细胞状态这条“高速公路”传播,从而缓解了梯度消失问题。这就足够了。

3.2 PyTorch 中的 LSTM API

PyTorch对LSTM提供了非常友好的封装。核心参数有:

  • input_size:输入特征维度,单变量时序是1,多变量时序是特征数。
  • hidden_size:隐藏层神经元数量,也就是隐状态维度,越大拟合能力越强,但越容易过拟合。
  • num_layers:LSTM堆叠层数,层数越多模型越深,但训练越难。
  • batch_first=True:让输入形状为(batch, seq_len, input_size),更加直观。
  • dropout:除最后一层外,层间插入Dropout,防止过拟合。

下面定义LSTM预测模型。我们取最后一个时间步的隐藏状态,经过一个全连接层输出预测值。

class LSTMPredictor(nn.Module): def __init__(self, input_size=1, hidden_size=64, num_layers=2, output_size=1, dropout=0.2): super().__init__() self.lstm = nn.LSTM( input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, batch_first=True, dropout=dropout ) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): # x: (batch, seq_len, input_size) out, (h_n, c_n) = self.lstm(x) # 取最后一个时间步的输出 last_out = out[:, -1, :] return self.fc(last_out)

这里有个常见误区,初学者很容易把outh_n搞混:

  • out的形状是(batch, seq_len, hidden_size),保存了每个时间步的输出。
  • h_n的形状是(num_layers, batch, hidden_size),保存的是最后一层每个方向的最终隐藏状态。

在单步预测场景下,我们只需要最后一个时间步的输出out[:, -1, :],然后用一个全连接层把它映射成预测值。

3.3 LSTM的常见使用误区

使用LSTM时,最容易出问题的点包括:

  • 忘记做数据标准化。LSTM对输入数据的尺度非常敏感,不做标准化会导致loss不下降或者收敛极慢。
  • 序列长度选得太短或太长。太短学不到长期依赖,太长会导致训练成本高、信息冗余。
  • 把整个序列随机打乱。时间序列不同于普通表格数据,随机打乱会破坏时间顺序,造成数据泄漏,导致验证集效果虚高。
  • 误以为LSTM只能处理单变量。其实它天然支持多变量输入,把多个特征拼到最后一维即可。

4. Transformer 原理拆解与 PyTorch 实现

Transformer在时间序列预测中的用法,和它在NLP中不太一样。完整的Transformer包含Encoder和Decoder两部分,但在很多时序预测场景中,我们往往只需要Encoder部分,把最后一步的输出接一个全连接层,就能完成预测任务。

先来看Transformer到底在做什么。

4.1 Self-Attention:每个位置都能看到全局

自注意力机制的核心是三个向量:Query、Key、Value。

你可以这样理解:

  • Query是“我在找什么”。
  • Key是“我有什么”。
  • Value是“我能提供什么”。

对于序列中的每个位置,模型会计算它与所有其他位置的匹配程度。匹配度高的位置,其Value会被赋予更大的权重。最终输出是所有Value的加权和。

注意力权重的计算公式是:

( \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V )

其中 ( d_k ) 是Key向量的维度。除以 ( \sqrt{d_k} ) 是为了防止点积结果过大,导致softmax进入饱和区,梯度变得很小。

正是通过这种方式,Transformer可以一步看到整个序列,而不是像RNN/LSTM那样按时间步逐步传递信息。

4.2 多头注意力

多头注意力(Multi-Head Attention)就是把注意力计算并行做多次,每次使用不同的线性投影。每个“头”关注序列中不同方面的关系,最后把多个头的输出拼接起来,再通过一个线性变换得到最终结果。

举个例子:在一个句子中,一个头可能更关注相邻词的关系,另一个头可能更关注指代关系。在时间序列中,有的头可能更关注近期波动,有的头可能更关注周期性规律。

多头注意力的好处是让模型拥有多个“视角”,表达能力更强。

4.3 位置编码

Transformer没有循环结构,它天然不关心输入的顺序。如果把序列顺序打乱,Transformer看到的输入完全一样。但时间序列的顺序恰恰至关重要,所以必须显式地把位置信息注入模型。

论文中使用的是正弦余弦位置编码:

( PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d_{model}}) )

( PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d_{model}}) )

这里 ( pos ) 是位置,( i ) 是维度下标。这种编码方式的好处是:不同位置产生的编码是唯一的,而且模型容易学习到相对位置的规律。

代码实现如下:

class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len=5000, dropout=0.1): super().__init__() self.dropout = nn.Dropout(p=dropout) pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-np.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) pe = pe.unsqueeze(0) # (1, max_len, d_model) self.register_buffer('pe', pe) def forward(self, x): x = x + self.pe[:, :x.size(1), :] return self.dropout(x)

4.4 Transformer 用于时间序列预测的结构选择

在处理时间序列预测时,常见的做法有两种:

第一种是Encoder-Decoder结构,适合序列到序列的多步预测,比如输入过去60个点,预测未来30个点。

第二种是Encoder-only结构,适合单步预测或者“输入一段历史,预测一个未来值”的场景。我们先从Encoder-only开始,它更容易理解,也更容易训练。

实现代码如下:

class TransformerPredictor(nn.Module): def __init__(self, d_model=64, nhead=8, num_layers=2, dropout=0.2, output_size=1): super().__init__() self.input_proj = nn.Linear(1, d_model) self.pos_encoder = PositionalEncoding(d_model, dropout=dropout) encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, nhead=nhead, dropout=dropout, batch_first=True ) self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers) self.fc = nn.Linear(d_model, output_size) def forward(self, x): # x: (batch, seq_len, 1) x = self.input_proj(x) # (batch, seq_len, d_model) x = self.pos_encoder(x) # 加位置编码 x = self.transformer_encoder(x) # (batch, seq_len, d_model) x = x[:, -1, :] # 取最后一个位置的输出 return self.fc(x)

注意,nn.TransformerEncoderLayer(batch_first=True)需要 PyTorch 1.9 及以上版本,如果你的版本较旧,需要把输入维度调整为(seq_len, batch, d_model),去掉batch_first=True

5. 完整代码复现:从数据处理到模型对比

到这里,原理部分基本讲完了。接下来进入完整实战环节。

5.1 滑动窗口数据集构造

时间序列预测最关键的一步是把原始序列转成监督学习样本。我们使用60个历史点预测未来1个点。

def create_sequences(data, seq_len=60, pred_len=1): X, y = [], [] for i in range(len(data) - seq_len - pred_len + 1): X.append(data[i:i + seq_len]) y.append(data[i + seq_len:i + seq_len + pred_len]) return np.array(X), np.array(y) # 标准化 scaler = StandardScaler() data_scaled = scaler.fit_transform(data.reshape(-1, 1)).flatten() seq_len = 60 pred_len = 1 X, y = create_sequences(data_scaled, seq_len, pred_len) # 按照8:1:1切分训练集、验证集、测试集 total = len(X) train_size = int(total * 0.8) val_size = int(total * 0.1) X_train, y_train = X[:train_size], y[:train_size] X_val, y_val = X[train_size:train_size + val_size], y[train_size:train_size + val_size] X_test, y_test = X[train_size + val_size:], y[train_size + val_size:] print(f"训练集: {X_train.shape}, 验证集: {X_val.shape}, 测试集: {X_test.shape}")

5.2 转换为PyTorch张量

def to_tensor(X, y): X_t = torch.tensor(X, dtype=torch.float32).unsqueeze(-1) y_t = torch.tensor(y, dtype=torch.float32) return X_t, y_t X_train, y_train = to_tensor(X_train, y_train) X_val, y_val = to_tensor(X_val, y_val) X_test, y_test = to_tensor(X_test, y_test) batch_size = 64 train_dataset = TensorDataset(X_train, y_train) val_dataset = TensorDataset(X_val, y_val) test_dataset = TensorDataset(X_test, y_test) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=False) val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

这里使用了shuffle=False,因为时间序列的前后顺序不能被打破。

5.3 通用训练函数

为了方便对比两个模型,写一个通用的训练函数。它接收模型对象,返回训练和验证阶段的loss记录。

def train_model(model, train_loader, val_loader, epochs=25, lr=0.001, device='cpu'): criterion = nn.MSELoss() optimizer = optim.Adam(model.parameters(), lr=lr) scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5) train_losses, val_losses = [], [] for epoch in range(epochs): model.train() epoch_loss = 0 for xb, yb in train_loader: xb, yb = xb.to(device), yb.to(device) optimizer.zero_grad() pred = model(xb) loss = criterion(pred, yb) loss.backward() optimizer.step() epoch_loss += loss.item() * len(xb) train_loss = epoch_loss / len(train_loader.dataset) train_losses.append(train_loss) model.eval() val_loss = 0 with torch.no_grad(): for xb, yb in val_loader: xb, yb = xb.to(device), yb.to(device) pred = model(xb) loss = criterion(pred, yb) val_loss += loss.item() * len(xb) val_loss = val_loss / len(val_loader.dataset) val_losses.append(val_loss) if (epoch + 1) % 5 == 0: print(f"Epoch {epoch + 1:3d}/{epochs} | Train Loss: {train_loss:.6f} | Val Loss: {val_loss:.6f}") scheduler.step() return train_losses, val_losses

这里加入了一个学习率调度器,每10个epoch将学习率缩小为原来的0.5倍,有助于模型在训练后期收敛得更稳定。

5.4 训练LSTM模型

device = torch.device("cuda" if torch.cuda.is_available() else "cpu") lstm_model = LSTMPredictor( input_size=1, hidden_size=64, num_layers=2, output_size=1, dropout=0.2 ).to(device) lstm_train_loss, lstm_val_loss = train_model( lstm_model, train_loader, val_loader, epochs=25, lr=0.001, device=device )

训练完成后,用测试集评估:

def evaluate_model(model, test_loader, scaler, device='cpu'): model.eval() preds, trues = [], [] with torch.no_grad(): for xb, yb in test_loader: xb, yb = xb.to(device), yb.to(device) pred = model(xb) preds.append(pred.cpu().numpy()) trues.append(yb.cpu().numpy()) preds = np.concatenate(preds, axis=0) trues = np.concatenate(trues, axis=0) preds_inv = scaler.inverse_transform(preds.reshape(-1, 1)).flatten() trues_inv = scaler.inverse_transform(trues.reshape(-1, 1)).flatten() mse = np.mean((preds_inv - trues_inv) ** 2) rmse = np.sqrt(mse) mae = np.mean(np.abs(preds_inv - trues_inv)) return preds_inv, trues_inv, mse, rmse, mae lstm_preds, lstm_trues, lstm_mse, lstm_rmse, lstm_mae = evaluate_model( lstm_model, test_loader, scaler, device ) print(f"LSTM -> MSE: {lstm_mse:.4f}, RMSE: {lstm_rmse:.4f}, MAE: {lstm_mae:.4f}")

5.5 训练Transformer模型

Transformer的训练逻辑完全一样,只需替换模型类:

transformer_model = TransformerPredictor( d_model=64, nhead=8, num_layers=2, dropout=0.2, output_size=1 ).to(device) transformer_train_loss, transformer_val_loss = train_model( transformer_model, train_loader, val_loader, epochs=25, lr=0.001, device=device ) transformer_preds, transformer_trues, transformer_mse, transformer_rmse, transformer_mae = evaluate_model( transformer_model, test_loader, scaler, device ) print(f"Transformer -> MSE: {transformer_mse:.4f}, RMSE: {transformer_rmse:.4f}, MAE: {transformer_mae:.4f}")

这里有个经验需要说明:Transformer在小数据集上的表现不一定比LSTM好,这是正常的。因为注意力机制的参数量更大,需要更多数据才能发挥优势。如果你在业务场景中发现Transformer效果不如LSTM,不必惊讶,这恰恰说明模型选型不能盲目追新。

5.6 可视化对比

为了直观对比两个模型的预测效果,在测试集上取前300个点绘图。

plt.figure(figsize=(14, 6)) plt.subplot(1, 2, 1) plt.plot(lstm_trues[:300], label="真实值", linewidth=1.5) plt.plot(lstm_preds[:300], label="LSTM预测", linewidth=1.5, alpha=0.8) plt.title("LSTM 预测效果") plt.legend() plt.subplot(1, 2, 2) plt.plot(transformer_trues[:300], label="真实值", linewidth=1.5) plt.plot(transformer_preds[:300], label="Transformer预测", linewidth=1.5, alpha=0.8) plt.title("Transformer 预测效果") plt.legend() plt.tight_layout() plt.show()

如果一切顺利,你会看到两条预测曲线都和真实曲线非常接近。比较突出的一个现象是:在序列的波峰和波谷附近,预测往往会“钝化”一点,也就是峰谷处的拟合不如平滑段好。这是单步预测模型常见的问题,因为损失函数是均方误差,模型倾向于预测条件均值,难免会把尖峰“抹平”。

6. 常见问题与排查思路

在实际复现过程中,你可能会遇到下面这些问题。我整理成一张表格,方便快速查阅:

问题现象常见原因解决思路
loss出现NaN学习率过大、数据未标准化、梯度爆炸减小学习率,检查数据是否标准化,必要时使用梯度裁剪
训练loss下降但验证loss不降过拟合增加Dropout,减小hidden_size或num_layers,引入早停
预测曲线明显滞后单步预测的累积误差,或序列长度不足增加seq_len,或改用多步预测结构
Transformer训练非常慢序列过长、batch过大、模型维度太高缩短seq_len,降低d_model,使用GPU
训练集效果很好但测试集差距大数据泄漏检查是否在切分前做了标准化,是否随机打乱了序列
LSTM比Transformer效果好小数据集下注意力机制优势不明显先用LSTM做基线,再逐步增大Transformer规模
程序报错batch_first参数无效PyTorch版本过低升级PyTorch或去掉batch_first并调整输入维度
预测值几乎等于某个常数模型退化,学习率过低或特征尺度不一致重新初始化模型,适当调大学习率,检查数据分布

如果你遇到“预测未来很多步时,误差越滚越大”的问题,这里单独说两句。单步预测模型训练时每一步都使用真实历史值作为输入,但推理时会用模型预测值作为下一步输入,误差会累积。解决办法有几种:

  • 在训练时使用教师强制(Teacher Forcing)的变体,随机混合真实值和预测值作为输入。
  • 改为多步预测模型,直接输出未来N个时间步。
  • 使用序列到序列结构,Encoder输入历史序列,Decoder逐步生成未来序列。

7. 工程实践建议

下面这些建议来自我在实际项目中使用LSTM和Transformer做时序预测的经验,希望对你有帮助。

7.1 数据标准化是第一步,也是最重要的一步

LSTM和Transformer都对输入尺度非常敏感。如果不做标准化,模型很容易在训练初期就发散。推荐使用StandardScaler,它会把数据变换为均值为0、标准差为1的分布。

注意:只能使用训练集的部分进行fit,然后transform训练集、验证集和测试集。不能把整个数据集一起fit,否则验证集和测试集的信息会在训练阶段就被模型“看到”,造成数据泄漏。

7.2 先跑通最小案例,再上复杂度

很多同学一上来就用几十万条数据、几百维特征训练一个大模型,结果不仅慢,还很难调试。正确做法是先在5000条数据、单变量、小模型上跑通完整流程,确认代码逻辑正确,再逐步扩大数据规模、增加特征维度、调大模型容量。

7.3 关于超参数,不必过度纠结

在时间序列预测中,下面这几个超参数的影响最大:

  • 序列长度seq_len:50到200是常见范围。可以结合业务周期来定,比如预测日用电量时,可以尝试按7天、30天的历史窗口输入。
  • 隐藏层维度hidden_size/d_model:32到128是常见区间,维度太大会显著增加训练时间和过拟合风险。
  • 层数num_layers:1到3层足够了,盲目加深对效果提升有限。
  • 学习率lr:1e-3是常见的初始值,如果loss不降,可以考虑降到1e-4或使用学习率预热。

7.4 多步预测策略要提前想清楚

如果业务需要预测未来多个时间点,一定要在建模前想好策略:

  • 递推预测:用单步模型循环预测,实现简单,但误差会累积。
  • 直接多输出:模型最后输出N个值,训练时用真实值计算每个时间步的loss,实现简单,但各预测时刻之间缺少依赖建模。
  • Seq2Seq:Encoder-Decoder结构,建模能力最强,训练和推理也最复杂。

建议先在单步预测上把效果做到位,再根据业务需求升级为多步预测。

7.5 保存模型并记录训练参数

训练结束后,用torch.save保存模型参数,同时建议把超参数、数据切分方式、标准化器等全部保存下来,方便后续复现。

# 保存模型 torch.save(lstm_model.state_dict(), "lstm_model.pth") torch.save(transformer_model.state_dict(), "transformer_model.pth") # 保存标准化器 import joblib joblib.dump(scaler, "scaler.pkl")

8. 总结

到这里,LSTM和Transformer从论文原理到代码复现的完整流程就讲完了。这篇文章需要掌握的核心内容有三个:一是LSTM的门控机制和它在长序列建模中的价值;二是Transformer的自注意力机制、多头注意力和位置编码;三是用PyTorch构建完整的时间序列预测流程,包括数据处理、模型训练、评估和可视化。

接下来的学习路线,我的建议是:先在你自己业务的数据集上跑通LSTM和Transformer,记录它们的表现差异;然后尝试多步预测,结合更多特征构造多变量输入;最后可以继续了解Informer、Autoformer等专门为长时间序列设计的Transformer变体。

如果你在复现过程中遇到问题,欢迎在评论区留言,也欢迎把文章收藏起来备用。动手跑通一遍,比看十遍视频更有效。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询