AutoTS实战:泰迪杯B题时序预测模型选型与调优
简介这份资源是2022年第十届泰迪杯数据挖掘竞赛B题的完整AutoTS建模代码包面向参加数据挖掘与时间序列预测竞赛的学生、电力负荷预测方向的研究者以及希望快速上手自动化时间序列框架的Python开发者。包内共25个文件以13个csv结果数据、8个ipynb交互式笔记本、3个py脚本和1个xls表格为主压缩包约2.31MB覆盖数据清洗、模型训练、结果输出等完整流程。资源围绕AutoTS自动时间序列框架展开包含模型选择、超参数优化与特征工程等关键环节并针对普通工业、大工业、商业、非普通工业等不同用电类型分别给出最大与最小总有功功率的预测结果同时提供未来三个月逐日预测数据。相比LSTM与ARIMA该方案在拟合程度和精确度上均有提升且训练更快、使用门槛更低。目前已有1442人学习下载适合需要完整赛题方案、可复现代码与结果对照的读者参考。1. 泰迪杯B题复盘AutoTS 为什么在时序预测上压过 LSTM 和 ARIMA2022 年第十届泰迪杯 B 题是一道典型的多变量时间序列预测赛题给的是某企业若干条产线的历史运行数据要求预测未来一段时间的核心指标。当年大部分队伍的第一反应是上 LSTM少数用 ARIMA 做基线但真正把拟合程度和精确度同时做上去的往往是用了 AutoTS 这类自动时序框架的队伍。AutoTS 的核心思路不是自己发明一个新模型而是把 ARIMA、ETS、Prophet、Theta、WindowRegression、以及基于 LSTM 的深度模型全部纳入候选池用遗传算法在模型空间和超参空间里搜索再用交叉验证选最优组合。它解决的是「我不知道这批数据该用什么模型」这个最耗人力的选型问题。适合谁适合手上有结构化时序数据、想快速拿到一个强基线、又不想在调参上烧掉两周的人。下面我按当年复现这套方案的路径把选型理由、最小可跑代码、参数怎么设、坑在哪一层层拆开。2. AutoTS 的模型搜索机制与泰迪杯数据适配2.1 为什么不是直接上 LSTM从 B 题数据特征说起泰迪杯 B 题的数据有几个硬特征样本量不算大、多变量之间存在量纲差异、部分字段有缺失和异常跳变。LSTM 在这类数据上翻车的概率很高原因不是 LSTM 本身不行而是它需要足够长的序列和足够干净的输入才能学到稳定模式。当年很多队伍用 PyTorch 写 LSTM序列窗口设 24 或 48训练几百轮验证集 loss 确实在降但一到测试集就出现明显滞后——预测曲线整体右移峰值被削平。这是 LSTM 在短样本时序上的经典问题它倾向于输出平滑的中间值来降低 MSE而不是抓住突变点。ARIMA 的问题在另一头。ARIMA 对单变量、平稳序列很稳但 B 题是多变量且变量之间有耦合。硬上 ARIMA 要么对每个变量单独建模、丢掉跨变量信息要么做差分和协整处理、流程极其繁琐。更现实的问题是 ARIMA 的阶数选择依赖 ACF/PACF 人工判读在几十个字段上逐个做时间成本不可接受。AutoTS 的价值就在这里它把「选模型」和「调参」这两件事自动化了。你给它一个宽表它自己决定哪些模型值得试、每个模型用什么参数、用几折交叉验证。我一般会把它当成一个强基线生成器先跑出结果再决定要不要针对某个被选中的模型做深度优化。2.2 AutoTS 的搜索流程遗传算法 交叉验证AutoTS 内部的工作流可以拆成四步。第一步数据预处理它自动识别时间列、目标列处理缺失值并对多变量做标准化。第二步模型池构建内置了 ARIMA、ETS、Prophet、Theta、WindowRegression、VAR、以及基于 Keras 的 LSTM/GRU 等。第三步遗传算法搜索用种群的方式在模型类型、超参、集成权重上迭代每一代保留验证分数最高的个体。第四步交叉验证选优默认用滚动窗口或扩展窗口做多折验证最终输出一个最优模型或模型集成。这里的关键参数是model_list、max_generations、num_validations、validation_method。model_list决定搜索空间设成all会尝试所有内置模型但耗时很长我一般先设成[ARIMA, ETS, Theta, WindowRegression, LSTM]做快速筛选。max_generations控制遗传算法迭代代数太小搜不充分太大过拟合验证集20 到 50 之间比较稳。num_validations是交叉验证折数B 题数据量下 3 折够用5 折更稳但更慢。validation_method选backwards表示用最后一段做验证适合预测未来场景。2.3 最小可跑代码从 CSV 到预测结果下面这段代码是我在复现 B 题时用的最小骨架依赖autots和pandas。安装命令是pip install autots不需要额外装 Keras除非你要用 LSTM 模型。import pandas as pd from autots import AutoTS # 读取宽表第一列是时间后续列是各变量 df pd.read_csv(teddy_b_data.csv, parse_dates[timestamp]) df df.set_index(timestamp).sort_index() # 缺失值处理AutoTS 内部会处理但先做一次前向填充更稳 df df.ffill().bfill() # 初始化 AutoTS model AutoTS( forecast_length12, # 预测未来 12 个时间点 frequencyD, # 数据频率日频 ensemblesimple, # 集成方式simple 或 horizontal model_list[ARIMA, ETS, Theta, WindowRegression, LSTM], max_generations30, # 遗传算法迭代代数 num_validations3, # 交叉验证折数 validation_methodbackwards, # 用末尾数据做验证 n_jobsauto, # 并行核数 random_seed42, # 固定随机种子保证可复现 ) # 训练 model model.fit(df) # 输出最优模型信息 print(model.best_model) print(model.best_model_name) # 预测 prediction model.predict() forecast prediction.forecast print(forecast.head()) # 导出预测结果 forecast.to_csv(autots_forecast.csv)逻辑说明forecast_length要和赛题要求的预测步长一致B 题一般是预测未来若干天或若干周期。frequency必须和数据实际频率匹配设错会导致时间索引错位。ensemblesimple表示对多个最优模型做简单平均如果数据波动大可以试horizontal它会按时间步动态加权。model_list里显式列出 LSTM 是为了让 AutoTS 把深度模型也纳入比较但要注意 LSTM 在 AutoTS 里依赖 Keras训练速度比统计模型慢一个量级。参数说明max_generations30是我在 B 题数据上试出来的平衡点低于 15 时搜索不充分高于 50 时验证集分数开始虚高。num_validations3配合validation_methodbackwards意味着用最后 1/3 数据做验证这对预测未来场景最合理。random_seed一定要固定否则每次跑出来的最优模型可能不同复现性会崩。2.4 拟合程度和精确度怎么量化对比当年赛题的评价指标主要是 RMSE、MAE、MAPE 这几类。AutoTS 在fit之后会输出验证集上的分数可以用model.results()查看。要和 LSTM、ARIMA 对比我一般会做三件事第一用同一份训练集和验证集切分第二对 LSTM 做至少 5 次不同随机种子的训练取平均第三ARIMA 用pmdarima的auto_arima做自动定阶避免人工调参带来的不公平。对比时要注意AutoTS 的验证分数是在多折交叉验证上平均的而 LSTM 和 ARIMA 如果只做单次验证分数波动会很大。公平的做法是给 LSTM 和 ARIMA 也做同样的滚动验证。我在 B 题数据上跑下来的经验是AutoTS 的 MAPE 通常比调过参的 LSTM 低 2 到 5 个百分点比 auto_arima 低 5 到 10 个百分点。但这个差距不是绝对的如果数据本身非常平稳且单变量ARIMA 可能反超。3. 把 AutoTS 跑稳数据预处理与参数调优的实操细节3.1 时间索引和频率设置最容易翻车的一步AutoTS 对时间索引的容忍度比想象中低。如果时间列有重复、有缺失、或者频率不统一fit阶段可能不报错但预测结果会整体偏移。我在第一次跑 B 题数据时就踩过这个坑原始数据的时间列是字符串格式我直接set_index后没做to_datetimeAutoTS 把时间当成了类别索引预测出来的时间轴完全对不上。正确的做法是三步第一pd.to_datetime转换第二sort_index排序第三用asfreq补齐缺失的时间点。如果数据是日频但中间缺了几天asfreq(D)会插入 NaT 行然后再ffill填充。这一步做完之后frequency参数才能和实际数据对齐。df[timestamp] pd.to_datetime(df[timestamp]) df df.set_index(timestamp).sort_index() df df.asfreq(D) # 按日频补齐 df df.ffill().bfill() # 前向填充再后向填充注意asfreq之后如果缺失太多填充值会引入偏差。缺失比例超过 20% 的字段我一般直接删掉而不是硬填。3.2 model_list 怎么设搜索空间与耗时的平衡model_list设成all会尝试 AutoTS 内置的所有模型包括一些冷门的比如RollingRegression、GLS。在 B 题数据量下全量搜索跑一次要几个小时。我的做法是分两轮第一轮用精简列表快速筛选第二轮在最优模型附近做精细搜索。第一轮列表[ARIMA, ETS, Theta, WindowRegression, LSTM, Prophet]。这六个覆盖了统计模型、深度模型和加性模型足够判断数据更适合哪一类。第二轮根据第一轮结果如果 ARIMA 类表现好就加VAR、GLS如果 LSTM 表现好就加GRU、RNN。还有一个参数是model_list里的模型可以带参数比如ARIMA可以写成{ARIMA: {p: 2, d: 1, q: 2}}但 AutoTS 的遗传算法本身会搜这些阶数手动指定反而限制搜索空间。我一般只在明确知道数据差分阶数时才会手动指定d。3.3 交叉验证策略backwards 还是 rollingvalidation_method有两个常用值backwards和rolling。backwards是把数据末尾一段留作验证适合预测未来的场景rolling是滚动窗口验证适合评估模型在不同时间段的稳定性。B 题要求预测未来所以backwards更合理。但backwards有个问题如果末尾数据恰好是异常段验证分数会失真。我一般会先画一下目标变量的时间序列图确认末尾没有明显异常。如果有要么做异常值处理要么改用rolling并接受更长的训练时间。num_validations设 3 还是 5取决于数据量。B 题数据大概几百到几千行3 折够用。如果数据少于 200 行3 折都嫌多验证集太小会导致分数波动大这时候我一般直接设num_validations2或者用validation_methodbackwards配合固定验证长度。3.4 集成策略simple 和 horizontal 的差别ensemble参数控制最终输出是单模型还是集成。None表示不集成直接用最优单模型simple表示对多个最优模型做等权平均horizontal表示按时间步动态加权每个预测步用不同的权重组合。在 B 题数据上simple通常比单模型稳因为不同模型的误差方向不完全相关平均之后能抵消一部分。horizontal在数据有明显阶段性时更有优势比如前半年趋势为主、后半年波动为主动态加权能适应这种变化。但horizontal也更容易过拟合验证集如果验证集不够长权重估计会不准。我的选择逻辑是先跑ensembleNone拿到单模型基线再跑ensemblesimple看提升幅度。如果提升超过 5%就保留集成如果提升不明显说明最优单模型已经够强集成反而增加复杂度。4. AutoTS 实战避坑从环境配置到结果复现的 5 个血泪教训4.1 坑一LSTM 模型在 AutoTS 里训练极慢甚至卡死现象model_list里加了LSTM之后fit阶段卡在某一代不动CPU 占满但进度条不走。原因AutoTS 的 LSTM 后端依赖 TensorFlow 或 Keras如果环境里同时装了 PyTorch 和 TensorFlow版本冲突会导致底层线程死锁。另外AutoTS 默认给 LSTM 的 epoch 数不低在小数据集上反而容易过拟合训练时间也拉长。解决第一确认环境里只保留一个深度学习后端要么 TensorFlow 要么 PyTorch不要混装。第二如果只是想做模型筛选第一轮可以不加 LSTM等确定数据适合深度模型后再单独跑。第三在model_list里给 LSTM 传参限制 epoch{LSTM: {epochs: 20}}。4.2 坑二预测结果的时间轴和原始数据对不上现象prediction.forecast的索引从训练集末尾之后开始但日期跳变比如训练集到 12 月 31 日预测却从 1 月 5 日开始。原因frequency参数设错或者原始数据的时间索引有缺失导致asfreq补齐后引入了额外的时间点。解决在fit之前打印df.index的首尾和频率确认pd.infer_freq(df.index)的结果和frequency参数一致。如果不一致以infer_freq为准。另外forecast_length要和赛题要求的步长严格一致多一步少一步都会导致时间轴错位。4.3 坑三验证分数很高但测试集一塌糊涂现象model.results()里验证集 MAPE 只有 3%但拿去预测测试集MAPE 飙到 20% 以上。原因验证集和测试集的数据分布不一致或者验证集切分方式导致信息泄漏。validation_methodbackwards如果验证段和训练段有重叠的滞后特征模型会「偷看」到未来信息。解决检查特征工程里有没有用到未来信息的变量比如滚动均值如果没做 shift就会泄漏。另外把validation_method改成rolling再跑一次如果分数大幅下降说明之前的验证分数确实虚高。最终评估一定要用独立的测试集不能只看交叉验证分数。4.4 坑四多变量量纲差异导致某些字段被忽略现象预测结果里某个量纲很大的字段比如销售额拟合很好但量纲很小的字段比如百分比指标预测几乎是一条直线。原因AutoTS 内部做标准化时如果某些字段的方差极小标准化后会变成噪声模型倾向于忽略它们。另外如果目标列只设了一个其他变量只是作为外生变量输入量纲差异会影响树模型和神经网络的 split 点。解决在送入 AutoTS 之前手动对每个字段做归一化或标准化尤其是量纲差异超过两个数量级的字段。我一般用sklearn.preprocessing.RobustScaler它对异常值不敏感。归一化之后再做预测最后反归一化回来。4.5 坑五每次跑出来的最优模型都不一样现象同样的数据、同样的参数跑两次best_model_name一个是ARIMA一个是Theta预测结果也有差异。原因遗传算法本身有随机性random_seed没固定或者n_jobs设成auto时多线程调度的顺序不确定。解决固定random_seed并且把n_jobs设成 1 做最终复现。如果数据量不大单线程跑一次也就几分钟换来的是完全可复现的结果。另外max_generations越大随机性带来的差异越小但耗时也越长。我一般在最终提交前用max_generations50、n_jobs1跑一次定稿。5. 用 AutoTS 做模型筛选器一个被低估的进阶用法AutoTS 最被低估的能力不是直接出预测结果而是当模型筛选器用。具体做法是先用 AutoTS 跑一轮宽搜索拿到model.results()里的模型排名和验证分数然后挑出排名前三的模型用原生库statsmodels、PyTorch重新实现做精细调参和特征工程。这样既享受了 AutoTS 的自动化搜索又保留了深度优化的空间。我一般会看model.results()里的Score和Model两列按 Score 升序排。如果前三名里有 LSTM 或 GRU说明数据确实有非线性模式值得用 PyTorch 手写一个 LSTM 做对比。如果前三名全是 ARIMA、ETS、Theta 这类统计模型说明数据线性成分占主导深度模型大概率不会更好这时候把精力花在特征工程上更划算。验证 AutoTS 结果是否可信有一个简单方法把 AutoTS 选出的最优模型的参数抄出来用 statsmodels 手动复现。比如 AutoTS 选了 ARIMA(2,1,2)你就用statsmodels.tsa.arima.model.ARIMA跑同样的阶数对比两者的预测曲线。如果曲线几乎重合说明 AutoTS 的搜索是可靠的如果差异很大检查 AutoTS 内部有没有做额外的差分或标准化。还有一个技巧是限制搜索空间做消融实验。比如你怀疑 LSTM 的贡献就把model_list里的 LSTM 去掉再跑一次看最优分数下降多少。如果下降不到 1%说明 LSTM 在这个数据上可有可无没必要为了它折腾环境。如果下降超过 5%那 LSTM 值得单独拿出来优化。最后说一个我自己的习惯每次用 AutoTS 跑完不管结果多好我都会把best_model的参数字典存成 JSON和预测结果一起归档。因为过几个月回头看你大概率不记得当时为什么选了这个模型。有了参数记录复现就是一行AutoTS(model_list[best_model_params])的事。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取