基于AGDO算法优化CNN-LSTM的多变量时序预测与模型对比实践

📅 发布时间:2026/9/1 17:45:08
基于AGDO算法优化CNN-LSTM的多变量时序预测与模型对比实践 时序预测领域每隔一段时间就会冒出一个更“卷”的模型结构但真正在业务落地时我们遇到的核心问题往往不是模型不够新而是超参数怎么定、特征怎么选、怎么在多个候选模型里挑出一个真正能用的。这次我们来看一个直接面向这个痛点的项目基于 2025 年 Nature 子刊上提出的 AGDO 优化算法对 CNN-LSTM 多变量时序预测模型做自动化寻优并给出四模型对比验证方案的完整实现思路。这个项目最有价值的地方在于它不是一个孤立的“新模型”而是一条完整的技术链路用 AGDO 算法自动搜索 CNN-LSTM 的关键超参数再通过与普通 CNN、LSTM、未优化 CNN-LSTM 的纵向对比量化说明优化算法的增益到底在哪里。从材料来看这套方案特别适合电力负荷预测、气象预报、交通流量预测、金融多因子时序建模等场景。读者不需要从零推导优化算法的数学定理也不需要自己拍脑袋定学习率、卷积核尺寸、LSTM 隐藏层数量而是可以把 AGDO 当作一个超参数搜索器让模型自己找到相对合理的配置区间。本文会带读者完成四件事第一理解 AGDO 优化 CNN-LSTM 的总体思路和模型结构第二搭好环境、准备多变量时序数据集第三完成 AGDO-CNN-LSTM 的训练、评估和可视化第四设计一个可复用的四模型对比实验并整理常见的坑和排查方法。硬件方面CNN-LSTM 这类模型对 GPU 要求不高常见的 6G 以上显存都能跑纯 CPU 环境下做小规模数据集验证也可行显存占用主要取决于序列长度、批大小和隐藏层单元数具体数值需要按实际模型和参数测试不能一概而论。1. 核心能力速览能力项说明项目类型多变量时序预测 超参数自动优化 模型对比实验核心算法2025 年 Nature 子刊提出的 AGDO 优化算法基础模型CNN-LSTM卷积提取局部特征 循环网络捕捉长期依赖对比方案四种模型CNN、LSTM、CNN-LSTM、AGDO-CNN-LSTM输入数据类型多变量数值序列典型如电力负荷、气象、交通、金融等输出形式单步或多步预测值、损失曲线、预测效果对比图、误差指标推荐硬件NVIDIA GPU 6G 以上显存CPU 可跑小规模数据依赖框架Python、PyTorch、NumPy、Pandas、Matplotlib、scikit-learn支持平台Windows / Linux / macOSmacOS 需注意 MPS 或 CPU 模式启动方式命令行运行 Python 脚本支持 Jupyter Notebook 分步执行是否支持 API从材料看未涉及可自行封装为 Flask/FastAPI 推理服务是否支持批量任务支持多变量批量预测可在推理阶段循环多个预测窗口适合场景时间序列预测技术验证、算法对比研究、业务预测模型选型从材料看这个项目走的是“研究基线 实测算例”的路线并没有吹嘘单模型精度而是强调用优化算法替人工调参这对长期做时序项目的人来说是一个值得关注的方向。2. 适用场景与使用边界2.1 适用场景多变量时序预测是一个非常宽泛的领域。AGDO-CNN-LSTM 这套方案比较适合以下几类情况电力负荷预测输入温度、湿度、历史负荷、节假日标记等多个变量预测未来 1 到 24 小时的负荷值。气象与环境预测输入气压、风速、湿度、污染物浓度等预测未来多个时间步的空气质量或天气状态。交通流量预测输入车流量、天气、时间戳、路段编号等预测下一时段拥堵指数。金融多因子建模输入多种技术指标和宏观因子预测收盘价或波动率。需要注意金融预测的噪声大、可解释性要求高模型输出只能作为辅助参考。工业设备状态预测输入振动、温度、电流等多通道传感器数据预测设备剩余寿命或故障概率。这套框架的特点是先通过 CNN 捕获多个变量之间的局部耦合关系再用 LSTM 建模时间维度的长期依赖最后通过 AGDO 自动搜索超参数降低手动调参成本。2.2 使用边界与限制任何模型都有适用边界AGDO-CNN-LSTM 也一样小样本场景效果有限多变量时序模型需要足够的历史数据支撑训练如果样本量只有几百条模型很容易过拟合此时更适合用传统统计方法或轻量级机器学习模型。黑盒优化的收益不是恒定值AGDO 能帮助找到更合理的超参数组合但不代表每次都能碾压手工调参尤其是当数据本身噪声很大时优化收益可能不明显。长期预测误差会累积多步预测往往采用递归方式生成未来值误差会随预测步数增加而累积建议根据业务需求设计合适的预测窗口。计算资源与收益需要权衡AGDO 是在多组不同超参数候选上反复训练模型整体训练成本是基线的数倍适合离线训练场景。实时推理时直接用训练好的模型即可成本不高。2.3 合规与安全提醒本项目中使用的数据可能涉及电力数据、交通数据、金融数据等使用时必须注意以下几点使用公开数据集时要确认数据授权协议注明数据来源。涉及用户隐私或企业内部数据时必须先完成脱敏处理并获得明确授权。金融预测模型只能作为研究参考不能直接构成投资建议。如果后续把模型封装成 API 服务要限制访问范围避免接口被滥用。3. 环境准备与前置条件3.1 硬件与操作系统从模型规模看CNN-LSTM 属于轻量到中等规模的深度学习模型不像大语言模型那样需要夸张的显存。推荐配置如下环境项建议配置操作系统Windows 10/11、Ubuntu 20.04、macOS 12GPUNVIDIA 显卡6G 以上显存支持 CUDA 11.8 或更新版本CPU普通多核处理器即可小数据量纯 CPU 可跑内存16G 及以上磁盘预留 10G 以上空间用于存储数据、模型权重和日志如果只有 CPU 环境建议把序列长度、批大小和隐藏层单元数调小训练时间会明显增加但小数据集仍然可以完成验证。3.2 Python 环境与依赖建议使用 Conda 或 venv 创建一个独立的虚拟环境避免依赖冲突。conda create -n timeseries python3.10 -y conda activate timeseries核心依赖安装命令pip install torch numpy pandas matplotlib scikit-learn如果使用 GPU 版本 PyTorch需要根据自身 CUDA 版本选择合适的安装指令。例如pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118如果只是 CPU 推理pip install torch --index-url https://download.pytorch.org/whl/cpu3.3 数据集准备多变量时序预测的数据格式一般是一个二维表格每一列是一个特征变量每一行是某个时间点的观测值。典型结构如下timefeature_1feature_2feature_3target2024-01-01 00:0012.530.20.851024.32024-01-01 01:0012.830.50.881031.5...............训练前需要将原始数据转换为「滑动窗口」样本。例如使用过去 24 个时间步的多变量数据预测未来 1 个时间步的目标值就得到形状为(样本数, 24, 特征数)的输入矩阵。这里给出一个通用的数据加载和窗口化代码模板import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler def create_sequences(data, seq_len24, pred_len1): 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, -1]) # 假设最后一列是目标 return np.array(X), np.array(y) # 示例读取数据 df pd.read_csv(multivariate_data.csv, parse_dates[time], index_coltime) # 特征列和目标列 feature_cols [feature_1, feature_2, feature_3, target] scaler MinMaxScaler() scaled_data scaler.fit_transform(df[feature_cols]) # 生成序列 SEQ_LEN 24 PRED_LEN 1 X, y create_sequences(scaled_data, seq_lenSEQ_LEN, pred_lenPRED_LEN) # 划分训练集、验证集、测试集 train_size int(len(X) * 0.7) val_size int(len(X) * 0.15) 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})注意create_sequences中的索引逻辑需要根据实际数据结构调整尤其是当pred_len大于 1 时标签形状会变成(样本数, pred_len)。4. CNN-LSTM 模型结构与 AGDO 优化思路4.1 CNN-LSTM 整体结构CNN-LSTM 组合模型是时序预测里非常经典的架构。它的设计思路很直接先用 CNN 提取局部特征再用 LSTM 捕捉长期依赖。具体来说输入层接收(batch_size, seq_len, n_features)的多变量序列。Conv1D 层在时间维度上做卷积每个卷积核相当于一个局部模式探测器可以捕获相邻时间步之间、不同变量之间的耦合特征。池化层缩减时间维度降低计算量同时增强平移不变性。经过展平或保留序列维度后送入 LSTM 层。LSTM 层对序列进行循环建模捕获长距离依赖。最后一层通过全连接将 LSTM 输出映射为预测值。4.2 AGDO 在框架中扮演的角色AGDO 在这个项目里的作用并不是替换 CNN-LSTM 的内部结构而是在模型外部做超参数自动搜索。需要优化的超参数一般包括Conv1D 的卷积核数量卷积核大小LSTM 隐藏层单元数LSTM 层数Dropout 比例学习率批大小训练轮数。AGDO 算法通过迭代式地评估若干组超参数候选在验证集误差的引导下更新搜索策略最终返回一组相对最优的超参数组合。这也是为什么项目标题强调的是“四模型对比”——因为只有通过 AGDO 优化后的模型与原始基线做同样的训练和评估才能看出优化算法是否真正带来增益。4.3 PyTorch 中的 CNN-LSTM 模型定义下面给出一个通用的 PyTorch 模型实现读者可以按自己的数据和超参数进行调整。import torch import torch.nn as nn class CNNLSTMModel(nn.Module): def __init__(self, n_features, seq_len, hidden_size64, num_layers2, dropout0.2, kernel_size3, conv_filters32): super().__init__() self.conv1 nn.Conv1d( in_channelsn_features, out_channelsconv_filters, kernel_sizekernel_size, paddingkernel_size // 2 ) self.relu nn.ReLU() self.lstm nn.LSTM( input_sizeconv_filters, hidden_sizehidden_size, num_layersnum_layers, batch_firstTrue, dropoutdropout ) self.fc nn.Linear(hidden_size, 1) def forward(self, x): # x shape: (batch_size, seq_len, n_features) x x.permute(0, 2, 1) # (batch_size, n_features, seq_len) x self.conv1(x) # (batch_size, conv_filters, seq_len) x self.relu(x) x x.permute(0, 2, 1) # (batch_size, seq_len, conv_filters) out, _ self.lstm(x) # (batch_size, seq_len, hidden_size) out self.fc(out[:, -1, :]) # 取最后一个时间步 return out这个实现比较简洁适合作为基线。实际项目中可能需要加入 BatchNorm、残差连接、Attention 层等进一步丰富特征表达能力。5. 四模型对比实验设计5.1 为什么是四模型对比单跑一个 AGDO-CNN-LSTM 并不能说明问题。没有对照组我们无法判断效果提升是来自模型结构、数据预处理还是 AGDO 超参数优化本身。因此这个项目设计了四模型对比模型说明作用CNN 单模型只有卷积层 全连接不引入循环结构验证纯局部特征提取能力LSTM 单模型只有 LSTM 层 全连接不引入卷积验证纯序列建模能力CNN-LSTM 基线CNN LSTM 组合采用默认或手工设定超参数验证组合结构的基线水平AGDO-CNN-LSTMCNN-LSTM 组合超参数由 AGDO 搜索得到验证优化算法的增益通过这四组实验可以回答三个问题CNN-LSTM 组合是否优于单独的 CNN 或 LSTM 模型在同样的 CNN-LSTM 结构下AGDO 搜索的超参数是否优于手工设定性能提升是来自结构还是来自超参数5.2 固定随机种子与公平评估做对比实验时一定要保证公平性。建议统一以下条件所有模型使用相同的数据划分。所有模型使用相同的归一化策略。所有模型使用相同的损失函数和评估指标。所有模型在相同设备上训练。统计多次运行的平均结果避免随机种子造成的偏差。训练脚本中建议设置固定随机种子import random import numpy as np import torch def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False set_seed(42)5.3 评估指标多变量时序预测常用的评价指标包括 MAE、RMSE、MAPE。下面给出计算函数from sklearn.metrics import mean_absolute_error, mean_squared_error def evaluate_metrics(y_true, y_pred): y_true np.array(y_true).reshape(-1) y_pred np.array(y_pred).reshape(-1) mae mean_absolute_error(y_true, y_pred) rmse np.sqrt(mean_squared_error(y_true, y_pred)) mape np.mean(np.abs((y_true - y_pred) / (y_true 1e-8))) * 100 return {MAE: mae, RMSE: rmse, MAPE %: mape}不同数据集的量纲差异很大MAE 和 RMSE 只能在同数据集内对比跨数据集比较没有意义。MAPE 也需要注意目标值不能接近 0否则会出现异常大值。5.4 AGDO 超参数搜索框架通用示例由于 AGDO 算法的具体实现细节需要参考原文的伪代码和开源实现这里给出一个通用的黑盒超参数搜索循环框架帮助读者理解搜索流程。实际使用时需要把agdo_suggest_params替换为 AGDO 算法提供的建议函数。import itertools # 定义超参数候选范围示例 SEARCH_SPACE { conv_filters: [16, 32, 64], kernel_size: [3, 5], hidden_size: [32, 64, 128], num_layers: [1, 2], dropout: [0.1, 0.2, 0.3], learning_rate: [1e-3, 5e-4, 1e-4], batch_size: [32, 64] } def run_trial(params, X_train, y_train, X_val, y_val): # 构造模型、训练、在验证集上返回误差 model CNNLSTMModel( n_featuresX_train.shape[2], seq_lenX_train.shape[1], conv_filtersparams[conv_filters], kernel_sizeparams[kernel_size], hidden_sizeparams[hidden_size], num_layersparams[num_layers], dropoutparams[dropout] ) # 此处省略训练代码返回验证集 RMSE val_rmse 0.0 return val_rmse # 实际使用 AGDO 时这里会由算法自动推荐下一组参数 # 以下是示意不代表 AGDO 的真实接口 best_rmse float(inf) best_params None for trial in range(30): # 伪代码params agdo_suggest_params(history, search_space) params None # 需要替换为 AGDO 的输出 val_rmse run_trial(params, X_train, y_train, X_val, y_val) if val_rmse best_rmse: best_rmse val_rmse best_params params print(fTrial {trial}: param{params}, val_rmse{val_rmse:.4f})如果读者拿不到 AGDO 的开源实现也可以用 Optuna、GridSearchCV 或随机搜索做对照思路完全一致只是搜索策略不同。6. 训练流程与效果验证6.1 训练循环训练部分直接使用 PyTorch 常规的批训练流程。这里重点说明几个容易影响结果的地方数据加载器建议使用DataLoader而不是手动循环能够自动处理 batch 和 shuffle。损失函数回归任务默认用MSELoss如果对异常值敏感可以尝试HuberLoss。优化器Adam 是默认选择学习率通常设在1e-4到1e-3之间。学习率调度建议使用ReduceLROnPlateau在验证集指标不再下降时自动降低学习率。一个简化训练循环如下import torch.optim as optim from torch.utils.data import TensorDataset, DataLoader def train_model(model, X_train, y_train, X_val, y_val, epochs50, batch_size64, learning_rate1e-3, devicecuda): model model.to(device) train_dataset TensorDataset( torch.FloatTensor(X_train), torch.FloatTensor(y_train) ) train_loader DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue) criterion nn.MSELoss() optimizer optim.Adam(model.parameters(), lrlearning_rate) scheduler optim.lr_scheduler.ReduceLROnPlateau(optimizer, modemin, factor0.5, patience5) X_val_tensor torch.FloatTensor(X_val).to(device) y_val_tensor torch.FloatTensor(y_val).to(device) for epoch in range(epochs): model.train() train_loss 0.0 for x_batch, y_batch in train_loader: x_batch x_batch.to(device) y_batch y_batch.to(device) optimizer.zero_grad() pred model(x_batch) loss criterion(pred, y_batch) loss.backward() optimizer.step() train_loss loss.item() * x_batch.size(0) train_loss / len(train_dataset) model.eval() with torch.no_grad(): val_pred model(X_val_tensor) val_loss criterion(val_pred, y_val_tensor).item() scheduler.step(val_loss) if (epoch 1) % 10 0: print(fEpoch {epoch 1}: train_loss{train_loss:.6f}, val_loss{val_loss:.6f}) return model6.2 预测反归一化训练之前的归一化操作会让预测结果处于 0 到 1 之间的量纲需要在评估和可视化之前做反归一化才能得到真实量纲的预测值。def inverse_scale(y_scaled, target_index-1, scalerNone): # 构造一个与特征维度相同的零矩阵再替换目标列 dummy np.zeros((len(y_scaled), scaler.scale_.shape[0])) dummy[:, target_index] y_scaled.reshape(-1) inv scaler.inverse_transform(dummy)[:, target_index] return inv注意MinMaxScaler的inverse_transform需要与原始特征维度完全一致所以这里用零矩阵填充其他特征列。6.3 可视化对比训练结束后把四种模型在测试集上的预测曲线画到同一张图中通常可以非常直观地看到差距。建议至少输出三组图训练集、验证集、测试集上的损失曲线真实值和各模型预测值的全局对比曲线某个局部时间窗口内的预测值放大图。import matplotlib.pyplot as plt def plot_prediction(y_true, predictions, labels, save_pathcomparison.png): plt.figure(figsize(12, 5)) plt.plot(y_true, labelTrue, colorblack, linewidth2) for pred, label in zip(predictions, labels): plt.plot(pred, labellabel, linestyle--) plt.legend() plt.xlabel(Time Step) plt.ylabel(Target Value) plt.title(Multi-model Prediction Comparison) plt.tight_layout() plt.savefig(save_path, dpi150) plt.show()6.4 判断实验是否成功一个成功的四模型对比实验通常能观察到以下现象测试集上CNN-LSTM 基线总体优于单个 CNN 或 LSTM。AGDO-CNN-LSTM 在验证集和测试集上的误差至少不差于手工设定基线更多情况下会有一定幅度的下降。预测曲线在趋势和数值两个维度都更贴近真实值而不是仅仅降低总误差。训练过程的损失曲线平滑收敛没有明显震荡。如果 AGDO-CNN-LSTM 的表现反而不如基线需要先检查超参数搜索范围是否合理、每组的训练轮数是否足够、数据划分是否存在泄漏而不是急着否定算法。7. 资源占用与性能观察7.1 显存占用观察CNN-LSTM 的显存占用主要来自三个部分模型参数、中间激活值和优化器状态。其中中间激活值会随seq_len和batch_size的增大快速增加。在训练脚本中可以在每个 epoch 后输出当前显存占用if torch.cuda.is_available(): allocated torch.cuda.memory_allocated() / 1024**2 reserved torch.cuda.memory_reserved() / 1024**2 print(fGPU memory allocated: {allocated:.2f} MB, reserved: {reserved:.2f} MB)从经验上看序列长度在 24 到 96、隐藏层单元在 32 到 128、批大小在 32 到 128 之间时显存占用通常不会太高但具体数值需要以本机实验为准。如果显存不足优先减小batch_size其次是减小隐藏层单元数或序列长度。7.2 CPU 与 GPU 训练差异CPU 训练小规模数据是可行的但训练速度会慢很多。如果X_train只有几千个样本、序列长度几十CPU 训练一套模型可能只需要几分钟到十几分钟。但是如果样本量达到几万或者需要用 AGDO 搜索 30 组超参数CPU 的时间成本会非常可观。建议流程先用小数据集、低 epoch 数跑通代码再用完整数据训练一组基线模型最后启动 AGDO 搜索。7.3 如何降低显存与内存占用减小batch_size这是最直接的手段。减小seq_len例如从 96 降到 48。使用torch.utils.data.DataLoader的pin_memoryTrue在 GPU 环境下加快数据搬运。使用梯度累积在显存不足时模拟更大批大小。训练过程中定期清理中间变量避免无关张量占住显存。多轮搜索 AGDO 超参数时每轮结束及时删除旧模型和旧优化器释放显存。8. 常见问题与排查方法问题现象可能原因排查方式解决方案安装 PyTorch 后 CUDA 不可用CUDA 版本与 PyTorch 版本不匹配运行torch.cuda.is_available()检查安装与本地驱动匹配的 PyTorch 版本或改用 CPU 版本数据归一化后预测值偏低忘记反归一化检查输出是否在 0 到 1 区间使用scaler.inverse_transform还原模型训练不收敛学习率过大或过小观察训练集 loss 变化降低学习率、使用学习率调度器验证集误差小于训练集误差Dropout 在训练时生效、验证时不生效检查模型是否调用了model.eval()推理和评估时务必调用model.eval()AGDO 搜索时间过长训练轮数过多、超参数组合过多观察每组试运行时间减少搜索轮数、降低训练 epoch、先在小数据上筛选GPU 显存不足batch_size 或隐藏层单元过大观察错误信息和显存占用降低 batch_size、降低 hidden_size预测曲线滞后真实值一个时间步模型倾向于复制上一步输入属于常见时序预测问题可尝试差分处理、增加输入窗口长度、加入外生特征四模型对比结果差异不稳定随机种子未固定多次训练看标准差固定随机种子多跑几次取平均数据泄漏导致测试集效果异常好归一化时用全量数据统计检查是否先归一化再划分数据应只使用训练集统计量测试集和验证集用相同统计量转换9. 最佳实践与使用建议9.1 第一次跑先小后大不要一上来就启动 30 轮 AGDO 搜索很容易因为代码 bug 或数据问题浪费时间。先把epochs降到 5batch_size降小用几百条数据跑通整个流程确认模型输出形状、损失函数、反归一化和可视化都没有问题再逐步加大规模。9.2 保留一套最小可运行配置在一个单独的config.py或 YAML 文件中维护最小可运行配置包括数据路径、序列长度、预测长度、特征列、归一化方式、模型结构、训练轮数等。这样无论怎么调参都有一份可以快速回到正常状态的配置。data: path: ./data/multivariate_data.csv seq_len: 24 pred_len: 1 feature_cols: [feature_1, feature_2, feature_3, target] target_col: target model: name: cnn_lstm conv_filters: 32 kernel_size: 3 hidden_size: 64 num_layers: 2 dropout: 0.2 train: epochs: 50 batch_size: 64 learning_rate: 0.001 seed: 429.3 管理好模型文件经过 AGDO 搜索得到最优模型后保存完整模型和训练参数torch.save({ model_state_dict: best_model.state_dict(), config: best_params, scaler: scaler, }, best_model.pth)推理时再加载checkpoint torch.load(best_model.pth, map_locationcpu) model CNNLSTMModel(**checkpoint[config]) model.load_state_dict(checkpoint[model_state_dict])需要提醒的是直接torch.savescaler 对象在不同版本的 scikit-learn 之间可能不兼容更稳妥的做法是保存scaler.mean_、scaler.scale_或scaler.data_min_、scaler.data_max_等数组。9.4 接口服务与批量预测虽然材料里没有提供 AGDO-CNN-LSTM 的 API 细节但在实际工程化时把训练好的模型封装成一个推理服务是很常见的需求。下面给出一个基于 Flask 的通用接口示例实际使用时需要根据模型输入输出结构调整from flask import Flask, request, jsonify import numpy as np import torch app Flask(__name__) model None scaler None def load_inference_model(model_pathbest_model.pth): global model, scaler checkpoint torch.load(model_path, map_locationcpu) model CNNLSTMModel(**checkpoint[config]) model.load_state_dict(checkpoint[model_state_dict]) model.eval() app.route(/predict, methods[POST]) def predict(): data request.get_json() input_seq np.array(data[input_seq], dtypenp.float32) # 需要对 input_seq 做同样的归一化处理 with torch.no_grad(): pred model(torch.FloatTensor(input_seq).unsqueeze(0)) pred_value pred.item() return jsonify({prediction: pred_value}) if __name__ __main__: load_inference_model() app.run(host127.0.0.1, port8000)批量预测时可以循环多个窗口分别请求也可以一次传入(batch_size, seq_len, n_features)的张量在内部一次性推理。批量推理比逐个窗口推理更快因为减少了 Python 与 PyTorch 之间的调度开销。9.5 日志和失败重试在 AGDO 搜索超参数时建议记录每一组参数的训练结果方便回溯。将每次试验的参数、验证集误差、训练时间写入 CSV 文件import csv with open(search_log.csv, w, newline) as f: writer csv.DictWriter(f, fieldnames[trial, val_rmse, training_time, params]) writer.writeheader() for trial in range(total_trials): params agdo_suggest_params(history) start_time time.time() # 训练并评估 val_rmse run_trial(params) training_time time.time() - start_time with open(search_log.csv, a, newline) as f: writer csv.DictWriter(f, fieldnames[trial, val_rmse, training_time, params]) writer.writerow({ trial: trial, val_rmse: val_rmse, training_time: training_time, params: str(params) })如果搜索过程中断可以根据 CSV 日志跳过已完成的组合实现断点续跑。10. 总结与下一步这个项目最值得尝试的点不在于 AGDO 这个算法本身有多强的数学背景而在于它提供了一条完整的多变量时序预测建模闭环数据准备、CNN-LSTM 结构设计、超参数自动优化、四模型效果对比、指标评估和可视化。拿到项目后最先应该验证的功能是数据是否能正确生成窗口样本模型能否在训练集上收敛。之后跑通一个最小规模的 CNN-LSTM 基线再引入 AGDO 超参数搜索最后实现四模型对比。最容易踩的坑有两个一是归一化和反归一化不对称导致预测结果无法还原到真实量纲二是超参数搜索时每组训练不充分导致对比结论不稳定。先把这两个问题解决整个流程就会顺畅很多。后续可以考虑的扩展方向包括把 AGDO 搜索范围扩展到更多超参数比如优化器类型、卷积层数、是否引入注意力机制在 CNN-LSTM 之外对比 TCN、Transformer、KAN 等新架构把单步预测扩展为多步预测并设计递归预测或直接预测两种策略也可以把模型封装成 API 服务接入实际的业务预警或报表系统。如果正在做多变量时序预测相关的工作手头又有一个不错的数据集建议收藏备用从这套四模型对比框架开始跑一遍大概率能提前避开调参和对比实验中的不少坑。