流感时间序列预测:ARIMA-LSTM-Transformer组合与集成实战

发布时间:2026/10/11 21:23:44

流感时间序列预测:ARIMA-LSTM-Transformer组合与集成实战 简介基于ARIMA、LSTM与Transformer等模型的流感时间序列预测Python源码是一份面向计算机相关专业课程设计与期末大作业的高分实操项目特别适合需要完成多模型对比实验、时序预测实战的学生或学习者。资源包共25个文件容量约4.93MB包含7个CSV数据文件如ILINet及流感历史数据、7个Python脚本、2个Jupyter Notebook、4个Excel表格及若干辅助压缩包覆盖数据加载、平稳性检验、ADF检验、ACF/PACF定阶、ARIMA建模与残差分析、LSTM/SARIMA训练以及多模型预测对比和未来走势预测等完整流程目录划分清晰便于按步骤复现代码。目前已有387人学习下载。通过该资源可系统掌握流感时序数据的预处理方法、SARIMA与Transformer等模型构建及评估思路获得从数据清洗到预测出图的整套可运行代码并能在课程设计、毕业设计或项目实战中直接参考、改造与扩展。1. 流感时间序列预测为什么单模型不够ARIMA-LSTM-Transformer组合才敢拿高分流感预测最常踩的坑不是模型不会跑而是数据一换模型就失效。单独用ARIMA它能抓住平稳趋势却抓不住暴发期的突然抬升单独用LSTM它能记住序列的周期却容易在样本量只有几百周的时候过拟合单独用Transformer理论上表达能力强但训练数据太少时反而比LSTM更飘。所谓高分项目本质上不是把三个模型各跑一遍而是把同一份流感数据清洗、建模、评估、集成的完整过程跑通并给出可信的误差对比。这篇文章会从数据准备讲到ARIMA基线、LSTM神经网络、Transformer最后用加权集成交付一套能直接交差的时间序列预测方案。适合正在做课程设计、毕业设计以及想认真做时序预测的Python开发者。2. 数据准备与评估口径把流感周报变成能喂给ARIMA、LSTM、Transformer的样本流感监测数据是典型周频序列一年约52个点做得好的项目通常会拿三年以上数据也就是150到200个点。这个体量对ARIMA很友好但对LSTM和Transformer来说偏小所以本章所有处理都围绕“小样本下怎么保证稳定”。2.1 数据源与字段选择ILI%周序列怎么整理最省事常见的数据源是各地疾控中心公开的流感监测周报字段经常包括“监测周、ILI%、流感病毒阳性率、暴发疫情起数”。做时间序列预测我们只需要日期和ILI%两列其他字段可以作为附加特征但第一版不建议一上来就堆特征因为周报越杂缺测和口径变更带来的坑越多。ILI%就是流感样病例占门急诊就诊数的百分比数值相对稳定适合建模。我习惯把数据整理成只有两列的CSVdate和ili。下面这段代码演示读取、解析和排序import pandas as pd # 列名统一成 date 和 ili周报通常给的是周起始日期 df pd.read_csv(flu_data.csv, parse_dates[date]) df df.set_index(date).sort_index() print(df.head()) print(df.tail()) print(df.info())逻辑说明parse_dates把date列解析成时间类型set_index把date设成索引sort_index保证序列按时间正序。流感数据只要时间顺序一乱后面所有滑窗和train/test切分都会错位所以这步是底线。如果暂时没有真实数据可以先用合成数据跑通流程但报告里要明确标注是模拟数据。我常用下面的方式生成260周左右的合成序列方便本地调试import numpy as np np.random.seed(42) dates pd.date_range(2019-01-01, periods260, freqW) trend np.linspace(2.0, 3.0, len(dates)) season 0.6 * np.sin(2 * np.pi * np.arange(len(dates)) / 52) ili np.round(trend season np.random.normal(0, 0.2, len(dates)), 2) df pd.DataFrame({date: dates, ili: ili}) df.to_csv(flu_data.csv, indexFalse)参数说明freqW按周生成日期/52表示以年为周期叠加季节性。真实项目里不建议用这种手工合成数据做训练它只适合验证代码路径能跑通。数据量方面想要拿高分训练样本尽量不要少于150周否则深度学习基本学不到周期。如果不到100周我一般只做ARIMA和LSTM放弃Transformer因为后者在极小样本上几乎没有优势。2.2 清洗与归一化缺失值插补、MinMaxScaler和节假日噪声流感周报的缺失值很典型跨年时周次合并、部分地区春节休假不报导致某几周连续为NaN。处理原则是先看缺失长度缺1到2周用线性插值缺太多周要考虑是不是报告口径变了机械填充等于编数据。有时候原始数据不是标准自然周可能是“2023-01-02至2023-01-08”这种先重采样成自然周再插值# 先重采样成自然周缺失的周会自动变成NaN df df.set_index(date).resample(W).first() # 缺失值用线性插值补上流感占比通常是渐变 df[ili] df[ili].interpolate(methodlinear, limit_directionboth) print(df.isnull().sum())逻辑说明resample(W).first()会把同一周的多行合并取第一条记录并补出没有数据的周。interpolate(methodlinear)对流感这种缓慢变化的占比指标是安全的因为暴发期也是连续爬坡很少直接跳变。节假日噪声需要单独处理。春节前后门急诊量明显下降ILI%会出现非流感因素的尖刺。常见做法是把春节前后两周生成哑变量特征# 假设春节近似在每年第4-6周这里按周序号标记 week_of_year df.index.isocalendar().week df[spring_festival] week_of_year.isin([4, 5, 6]).astype(float)参数说明isocalendar().week返回ISO周序号春节一般落在第4到6周用这种简单规则可以避免查每年农历日期。后面LSTM/Transformer把spring_festival列当作额外输入特征ARIMA则可以直接忽略因为它本质上是线性模型学了也白学。归一化这步只给深度学习模型用ARIMA继续用原始数值from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler(feature_range(0, 1)) df[ili_scaled] scaler.fit_transform(df[[ili]]) train_size int(len(df) * 0.8) train df.iloc[:train_size] test df.iloc[train_size:]参数说明feature_range(0, 1)是默认范围LSTM和Transformer对量纲敏感把ILI%从3.0这种小数值缩放到0到1能明显加速收敛。注意fit_transform只需要在训练集上fit测试集应该用同一个scaler去transform避免测试集信息泄漏进归一化参数。这里简单写法是整体fit实际项目中要在切分之后对训练集fit。2.3 评估指标与验证方式RMSE、MAPE和walk-forward窗口怎么切评估流感预测不能只看一个指标。RMSE对大误差敏感适合衡量谁在暴发期更离谱MAPE是百分比误差报告里容易解释但真实值接近0时会爆炸R²在时间序列上天然虚高因为序列自相关太强不建议单独使用。下面这两个指标足够用了from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error def evaluate(y_true, y_pred): rmse float(np.sqrt(mean_squared_error(y_true, y_pred))) mape float(mean_absolute_percentage_error(y_true, y_pred)) return {RMSE: rmse, MAPE: mape}逻辑说明evaluate返回字典方便汇总多个模型。这里y_true和y_pred都要用原始尺度不能用归一化后的值否则RMSE看起来很小换数据后完全不可比。验证方式上时间序列最忌讳随机划分。train_test_split(random_state42)会把未来数据塞进训练集评估结果虚高评审一质疑就翻车。正确的做法是按时间顺序切分from sklearn.model_selection import TimeSeriesSplit tscv TimeSeriesSplit(n_splits5) for train_idx, val_idx in tscv.split(df): train_data df.iloc[train_idx] val_data df.iloc[val_idx]参数说明TimeSeriesSplit(n_splits5)按时间递增切5折每一折的训练集都严格在验证集之前。小样本数据我通常取n_splits3或4保证每折训练集不少于100周。切完之后先跑ARIMA基线如果基线RMSE都超过你心中的容忍值后续深度学习也不用继续了。最后补一个针对暴发的指标峰值时刻偏差。流感预测的核心是暴发预警如果模型把峰值预测偏了两周RMSE再低也白搭。常见做法是取真实峰值前后4周看预测峰是否落在窗口内。下面这个函数统计峰值位置的平均偏差def peak_time_error(y_true, y_pred, top_k4): idx_true np.argsort(np.array(y_true))[-top_k:] idx_pred np.argsort(np.array(y_pred))[-top_k:] return float(np.mean([abs(float(np.min(abs(p - idx_true))) for p in idx_pred]))逻辑说明np.argsort取最大的top_k个位置然后对每个预测峰值找它离某个真实峰值最近的距离再取平均。这个指标不会写进主损失函数但会写进项目报告的对比表里专门给评委看“你的模型有没有预警价值”。到这里数据已经能被三个模型共用。下一步先把ARIMA基线跑通用它给LSTM和Transformer立一个必须超过的分数基准。3. ARIMA基线用pmdarima跑通统计模型先给深度学习立一个分数深度学习模型不是上来就训练。先跑ARIMA有两个好处一是代码量小能快速暴露数据预处理的问题二是得到一个最低线后面LSTM和Transformer必须在这个RMSE基础上再降否则没有存在意义。3.1 为什么ARIMA适合做基线平稳性、ACF/PACF与差分ARIMA全称差分自回归移动平均模型三个参数分别叫p、d、q。p是自回归阶数表示用最近p个时刻的值来预测当前值d是差分阶数用来消除趋势q是移动平均阶数用来拟合噪声。流感ILI%序列通常不平稳因为每年有季节性抬升所以差分是必须的。可以用ADF检验看平稳性from statsmodels.tsa.stattools import adfuller result adfuller(df[ili].dropna()) print(ADF统计量:, result[0]) print(p值:, result[1])逻辑说明p值小于0.05说明序列平稳。如果p值很大就做一次差分再检验。对流感数据d1通常就够了差分一次后季节性会保留但整体趋势被抹平。这里不展开SARIMA是因为项目题目点名了ARIMA、LSTM、Transformer先用非季节性ARIMA当基线是常规做法拿了SARIMA反而让对比变量不干净。ACF和PACF图能帮助定p、q但实际项目里大部分人不会看图直接交给auto_arima自动搜索。如果评审老师问起来能说出“ACF拖尾、PACF截尾所以p取1到2、q取0到1”这种话就行不必真的纠结。3.2 pmdarima自动定阶与滚动预测代码、参数与输出pmdarima是Python里最省心的ARIMA工具。我一般在训练集上跑自动定阶然后对测试集做滚动预测。所谓滚动预测就是每预测完一周把真实值补充进历史再预测下一周。这样不会让误差像雪球一样越滚越大。from pmdarima import auto_arima y_train df[ili].iloc[:train_size] model auto_arima( y_train, start_p0, max_p7, start_q0, max_q7, dNone, seasonalFalse, stepwiseTrue, traceTrue, error_actionignore, suppress_warningsTrue ) print(model.order)参数说明dNone表示让pmdarima自己用KPSS或ADF判断差分阶数seasonalFalse是因为另一路人马做深度学习ARIMA这里刻意不用季节性差分。stepwiseTrue会启用启发式搜索避免遍历所有组合260周数据上基本几秒钟就出结果。error_actionignore的作用是某一组p、q不收敛时不直接报错中断。定完阶之后滚动预测的代码是项目里的核心history list(y_train.values) preds [] for t in range(len(test)): # 用当前模型预测下周 pred model.predict(n_periods1)[0] preds.append(pred) # 把测试集真实值喂给模型而不是喂预测值 history.append(test[ili].iloc[t]) model.update(history[-1])逻辑说明model.update(history[-1])是增量更新不是重新fit。你拿到新一周的真实ILI%后更新模型状态预测下个月时模型始终处于“见过最新真实数据”的状态。这个策略叫expanding window样本量小的时候比纯滚动预测稳定。model.predict(n_periods1)返回一个数组这里[0]取第一个值。如果要做未来4周预测改成n_periods4但流感项目里最常见的是1步预测加滚动更新因为周报每周都出没有必要牺牲精度预测整月。3.3 ARIMA的典型失败样子它在暴发期为什么容易滞后ARIMA在流感项目里一定会被问到一个问题为什么预测曲线比真实数据滞后一两周原因是ARIMA本质是线性自回归它对“尖峰”能做的只是用前几周的趋势外推一旦暴发是突然抬升自回归项只能把预测值往上周的真实值方向拉于是看起来像把真实曲线平移了一周。这种滞后在RMSE里会被重重惩罚因为暴发期误差很大。我见过不少项目为了压RMSE给ARIMA堆了不少假特征比如把时间戳的sin/cos加进去结果只是让滞后变成抖动并没有解决根本问题。所以ARIMA的定位就是基线它必须能抓住趋势但允许在暴发期系统性滞后。后面LSTM和Transformer能不能在暴发期做到“拐头快”才是拿分的关键。4. LSTM神经网络把流感序列改造成监督学习再训练LSTM需要对数据做滑窗把原始序列改造成“过去8周预测下周”的监督学习格式。这一步不做好模型结构再复杂也没用。4.1 滑窗构建数据集seq_len、stride怎么设滑窗长度seq_len是三模型共用的超参数。流感周期是年52周但暴发持续时间通常4到6周所以窗口太长会引入无关信息太短又学不到暴发前兆。我一般从8周起步因为流感暴发前一个月往往有低位徘徊8周足够看到完整的前兆。def create_sequences(data, feature_cols, seq_len8): X, y [], [] for i in range(len(data) - seq_len): X.append(data.iloc[i:iseq_len][feature_cols].values) y.append(data.iloc[iseq_len][ili]) return np.array(X), np.array(y) feature_cols [ili_scaled, spring_festival] X, y create_sequences(train, feature_cols, seq_len8) print(X shape:, X.shape) print(y shape:, y.shape)逻辑说明create_sequences返回的X形状是(样本数, 8, 特征数)。i从0取到len(data)-seq_len-1每次取连续8周作为输入第9周作为标签。spring_festival列在这里当作外部特征拼进每一步这样LSTM可以“看到”春节前后几周的输入。注意stride1也就是窗口每次滑动一周。流感周报本身样本就少stride大于1等于人为丢弃数据除非是数据量过万的长序列否则不建议。测试集同样要转成序列但有个差别测试集滑窗不能跨训练集。应该在完整训练测试序列上重建并在构建时记录原始索引full_df df.iloc[train_size - seq_len:] X_test, y_test create_sequences(full_df, feature_cols, seq_len8)逻辑说明为了让测试集第一个窗口能看到训练集最后8周的信息从train_size - seq_len处开始截取。这样既没有数据泄漏又能让模型基于最新历史做预测。很多踩坑项目直接把测试集单独滑窗结果第一个窗口全是NaN或随机值预测惨不忍睹。4.2 LSTM模型定义与训练hidden_size、num_layers、dropout怎么选PyTorch里写一个面向小样本的LSTM模型核心是别堆太大。流感数据只有一两百个训练样本hidden_size取32已经足够取128大概率过拟合。num_layers取1到2层再多就没有足够数据约束。dropout取0.2到0.3给序列加一点随机失活。import torch import torch.nn as nn class LSTMForecast(nn.Module): def __init__(self, input_size, hidden_size32, num_layers2, output_size1, dropout0.2): super().__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout) self.fc nn.Linear(hidden_size, output_size) def forward(self, x): out, (h, c) self.lstm(x) # out形状: (batch, seq_len, hidden_size) return self.fc(out[:, -1, :])逻辑说明batch_firstTrue让输入形状变成(批次, 时间步, 特征数)和create_sequences返回的X直接对齐。取out[:, -1, :]表示只要最后一个时间步的hidden state再接一个线性层输出下周ILI%。注意输入的input_size是特征数这里是2ili_scaled和spring_festival。训练循环里学习率、batch_size、梯度裁剪和早停比模型结构更容易影响结果。下面这段是标准的训练代码from torch.utils.data import DataLoader, TensorDataset train_dataset TensorDataset(torch.FloatTensor(X_train), torch.FloatTensor(y_train)) train_loader DataLoader(train_dataset, batch_size16, shuffleTrue) model LSTMForecast(input_sizeX_train.shape[2], hidden_size32) optimizer torch.optim.Adam(model.parameters(), lr1e-3) loss_fn nn.MSELoss() for epoch in range(60): model.train() for batch_X, batch_y in train_loader: optimizer.zero_grad() loss loss_fn(model(batch_X), batch_y.unsqueeze(1)) loss.backward() # 梯度裁剪防止小样本下梯度爆炸 torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) optimizer.step()参数说明shuffleTrue在训练时可以打乱样本顺序因为滑窗样本本身已经包含时间信息打乱不影响LSTM的内部时序反而有助于收敛。clip_grad_norm_(..., 1.0)把梯度范数限制在1.0Transformer和LSTM都建议加流感数据一旦出现一两周的异常尖峰梯度很容易翻车。关键的是不要对测试集shuffle测试时用完整序列按时间顺序逐周预测。4.3 LSTM训练监控学习率、batch_size和早停学习率是LSTM训练里最需要手动盯的参数。流感数据量小lr1e-3是安全起点如果损失曲线震荡得厉害直接降到3e-4。batch_size可以选8或1626个样本的小序列用32会导致一个batch几乎覆盖全部样本梯度更新太“猛烈”。早停要小心验证集只有三四十个点不能像CV数据集那样等验证loss连续3轮不降就停。我一般只看训练loss走势加上固定epoch数双保险best_loss float(inf) best_state None for epoch in range(60): model.train() for batch_X, batch_y in train_loader: optimizer.zero_grad() loss loss_fn(model(batch_X), batch_y.unsqueeze(1)) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) optimizer.step() # 每个epoch结束在验证集上测一次保存最佳权重 model.eval() with torch.no_grad(): val_pred model(torch.FloatTensor(X_val)) val_loss loss_fn(val_pred, torch.FloatTensor(y_val).unsqueeze(1)) if val_loss best_loss: best_loss val_loss best_state {k: v.clone() for k, v in model.state_dict().items()} # 恢复最佳权重 model.load_state_dict(best_state)逻辑说明验证集也要从训练集末尾往前回退8周来构建不能跳过。保存最佳权重的目的是防止最后几个epoch噪声导致测试集成绩变差。小样本项目里早停的意义不是节省时间而是防止验证集上的偶然性波动毁掉模型。5. Transformer模型实战与避坑指南Transformer在时间序列预测里不是天生就能拿高分的它最大的优势是能直接建模长距离依赖比如暴发前12周的细微走势。但流感数据只有几百点如果直接套用NLP里的经典配置几乎必翻车。所以这一章先讲怎么把Transformer吃下时间序列再给出一组适合小样本的配置和踩坑记录。5.1 Transformer输入构造线性embedding与位置编码Transformer没有循环结构必须显式告诉它每个时间步的先后顺序所以位置编码是刚需。流感序列长度只有几十到上百用最经典的sin/cos位置编码就够了不需要学出来的位置嵌入。下面这段代码是标准实现也是项目里最容易复制错的地方。import math import torch import torch.nn as nn class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len100): super().__init__() pe torch.zeros(max_len, d_model) position torch.arange(0, max_len, dtypetorch.float).unsqueeze(1) div_term torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] torch.sin(position * div_term) pe[:, 1::2] torch.cos(position * div_term) self.register_buffer(pe, pe.unsqueeze(0)) def forward(self, x): # x: (batch, seq_len, d_model) return x self.pe[:, :x.size(1)]参数说明d_model是Transformer的embedding维度max_len要大于最大序列长度。0::2取偶数位置1::2取奇数位置分别用sin和cos编码。register_buffer的好处是位置编码会跟着模型转到GPU或CPU不需要手动move。在时间序列Transformer里输入通常先用一个线性层把原始特征映射到d_model再加位置编码class TransformerForecast(nn.Module): def __init__(self, input_size, d_model16, nhead4, num_layers2, dropout0.1): super().__init__() self.embed nn.Linear(input_size, d_model) self.pos PositionalEncoding(d_model) encoder_layer nn.TransformerEncoderLayer( d_model, nhead, dim_feedforward64, dropoutdropout, batch_firstTrue ) self.encoder nn.TransformerEncoder(encoder_layer, num_layers) self.fc nn.Linear(d_model, 1) def forward(self, x): x self.embed(x) x self.pos(x) x self.encoder(x) # 预测时取最后一个时间步 return self.fc(x[:, -1, :])逻辑说明self.embed把2维特征扩到16维然后加位置编码送入TransformerEncoder。x[:, -1, :]和LSTM取最后时间步是对齐的操作。dim_feedforward64比NLP里的2048小得多这是刻意为之流感数据扛不住超大前馈网络。5.2 小数据训练的Transformer配置d_model、nhead、深度怎么选Transformer在小数据上的核心矛盾是参数太多、数据太少。按照我的经验整组配置从下面这个表起步最稳妥参数推荐值说明seq_len12到16周比LSTM的8周稍长发挥注意力优势d_model16或32超过64开始过拟合nhead4d_model16时nhead4每个头分到4维num_layers1到22层是上限dim_feedforward64不要超过128dropout0.1到0.2位置编码后和attention输出后各一遍lr3e-4和LSTM比偏低因为Transformer梯度更猛nhead不是越大越好。d_model16、nhead8时每个头只有2维学到的注意力基本是噪声。nhead4或者2在这类任务里更正常。训练Transformer时建议加一个简单的warmup前10个batch把学习率从1e-5线性升到设定值后面再正常衰减或使用cosine schedule。流感序列损失面比较平缓warmup能减少前期震荡。5.3 5个高频避坑记录从数据泄漏到训练NaN这一节只写我在类似时间序列项目里遇到过的真坑每条都是现象、原因、解决三步。坑1训练损失降到很低预测却是水平线现象LSTM或Transformer在训练集上MSE已经很小但测试集预测曲线像一条直线起伏非常弱。原因流感数据归一化后均值在0.3左右模型发现“一直预测均值”比“努力抓峰值”的损失更低所以学成了躺平模式。解决把seq_len从8提高到12到16同时降低学习率到3e-4并检查归一化后训练集的标准差如果标准差小于0.2说明数据本身变化太小深度学习很难学到规律。坑2训练集RMSE低测试集RMSE爆炸现象换到测试集后预测值突然飞出去甚至出现负值。原因大概率是数据泄漏比如归一化时整个序列一起fit或者测试集滑窗跨到了训练集前面。解决严格按时间顺序切分scaler.fit只用训练集测试集用transform。同时确认测试集滑窗的起点是train_size - seq_len保证第一个窗口能看到训练集末尾。坑3Transformer训练到一半出现NaN loss现象loss在第20个epoch突然变成nan。原因学习率过高导致self-attention的输出溢出小数据下位置编码的数值范围也有影响。解决把学习率降到3e-4以下给PositionalEncoding的输出乘一个0.1缩放到预训练checkpoint里的常见做法优化器要用AdamW并加clip_grad_norm_数值稳定性能救回很多次训练。坑4ARIMA预测太平滑峰值完全消失现象ARIMA在测试集上的MAPE不错但峰值周预测偏差超过3周。原因ARIMA是线性模型对突然抬升的尖峰只能做“惯性外推”这是统计模型的固有边界。解决这个坑不是靠调参能解决的。正确的态度是承认ARIMA只负责趋势和基线暴发判定交给LSTM或Transformer。项目报告里可以写“ARIMA在非暴发期与深度学习模型持平在暴发期滞后1到2周”这反而是加分项。坑5反归一化后预测值超出合理范围现象预测的ILI%变成负数或者超过10%明显不符合医学常识。原因scaler.inverse_transform要求输入是二维列向量如果只传一个一维数组sklearn会当成一行处理结果完全错位。解决反变换前强制reshape成(-1, 1)pred_orig scaler.inverse_transform(np.array(preds).reshape(-1, 1)).flatten()逻辑说明reshape(-1, 1)把形状变成(样本数, 1)inverse_transform才能按列做反归一化最后flatten()变回一维方便计算指标。这是所有人都会遇到的形状问题不是模型问题。6. 三模型对比与加权集成把高分项目落在交付上跑通三个模型不是终点交付一个能让评审信服的结论才是终点。最后这一章讲怎么把结果组织成对比表、怎么集成以及哪些小技巧能让项目看起来真的有工程价值。6.1 滚动测试集与三模型结果对比测试集最好固定为最后8到10周。对每周t三个模型都只用t之前的数据做预测然后汇总误差。这种方式叫滚动测试和真实使用场景一致。输出结果时建议整理成类似下面的表格每个指标保留两位小数并且在文字里解释为什么某个模型在某项上更好。模型RMSEMAPE (%)峰值偏差 (周)ARIMA0.329.82.3LSTM0.278.11.4Transformer0.257.61.2加权集成0.216.30.9表格里的数字是我见过的典型量级真实项目必须用自己模型在测试集上的实际输出。峰值偏差列建议用2.3节里的peak_time_error计算这比只写RMSE更能打动评委。6.2 加权集成用验证集学权重还是简单平均集成不是为了炫技而是因为ARIMA擅长低频趋势LSTM擅长局部拐点Transformer擅长长距离依赖三者预测的误差不是完全正相关。最简单的集成是等权重平均三个模型各占1/3。等权重的好处是没有过拟合风险因为权重不需要在验证集上学习。如果要做加权集成我一般用验证集上的组合优化代码如下from scipy.optimize import minimize # val_preds是三个模型在验证集上的预测形状都是(n,) def obj_func(w): w np.abs(w) ensemble w[0] * val_preds[0] w[1] * val_preds[1] w[2] * val_preds[2] return float(np.sqrt(mean_squared_error(val_y, ensemble))) res minimize(obj_func, x0[1/3, 1/3, 1/3], bounds[(0, 1)] * 3) w res.x / np.sum(res.x) print(优化权重:, w)逻辑说明np.abs(w)保证权重非负归一化让权重总和为1。minimize默认用L-BFGS-B三个参数收敛非常快。这里有个坑如果不加bounds优化器可能给出负权重负权重在指标上可能分数更好但物理意义说不通评审一眼就能看出问题。权重优化完成后测试集上不要重新调权重否则等于在测试集上做超参搜索属于一种隐性数据泄漏。验证集上定的权重直接搬到测试集即可。6.3 高分项目的加分项峰值偏差、置信区间和可视化最后聊几个不用改模型就能拉高评分的小习惯。第一个是置信区间。小样本时间序列预测对点估计很容易过度自信。我通常用历史残差的标准差来画预测区间如果测试集残差的标准差是0.15那么预测值加减1.96倍标准差就是这个周的95%置信区间。不用模型不用贝叶斯直接在报告里写“基于残差的近似置信区间”方向正确又容易复现。第二个是可复现实验设置。所有随机种子固定成一个比如random.seed(42)、np.random.seed(42)、torch.manual_seed(42)并在README里说明。很多人跑同一个Transformer出现两次结果不一致就是因为没固定种子。项目报告里加一段“实验环境”说明直接写Python版本、PyTorch版本、随机种子是工程素养的体现。第三个是反直觉的结论比华丽模型更值钱。如果测试集显示Transformer没有超过LSTM不要硬调超参把数字拉平。我见过最靠谱的高分项目结论是“在流感这类50周级别周期数据上LSTM与Transformer差距不显著但集成稳定优于单模型”。这个结论比堆出三个模型然后硬吹Transformer强太多。我自己的习惯是每次做时序预测都先把ARIMA基线跑完、固定随机种子、把scaler保存下来这三步做完才允许自己碰深度学习。模型可以换alpha不能乱加测试集只能碰一次。希望这篇笔记能帮你把流感预测这个题目做得又快又稳也希望你能在报告里保留那份“真实实验记录”的诚实这比任何花哨的超参数都更能拿分。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/11 21:23:44

图像修复怎么做?马赛克去除的检测、重建与参数调优实践

简介:一套专用于图像与视频处理者进行马赛克去除的工具包,可用于修复旧影像、分析监控证据或辅助艺术创作。压缩包为rar格式,内共有四十一份文件,总体积约四点八一兆字节,主要由可执行程序、动态链接库、注册表配置及文…

2026/10/11 21:18:43

Java版jieba分词:生产级中文分词统计方案

简介:本资源是面向Java初学者与中文文本处理开发者的jieba分词实践工具包,提供开箱即用的Java版结巴分词能力,解决中文分词、词频统计及基础NLP任务快速落地问题。压缩包共56个文件,含18个核心Java源码(覆盖分词器初始…

2026/10/11 21:18:43

Docker 部署 FastGPT 时把模型接入改到 TaoToken 的完整配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 2:09:31

EMC结构设计:缝隙、开孔与搭接如何决定屏蔽效能

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 2:04:30

Winform轻量级流程图控件:GDI+实现可交互FlowChart内核

简介:这是一份基于WinForm平台实现的轻量级流程图绘制工具源码,面向C#初学者与小型项目开发者,解决快速嵌入可视化流程编辑功能的需求。资源以FlowChart.Net为基础进行精简改造,代码结构清晰、功能聚焦,适合用于教学演…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/11 0:02:13

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/11 0:02:13

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑