简介基于传染病动力学模型SEIR与LSTM神经网络实现的新型冠状病毒肺炎COVID-19预测Python项目面向计科、数据科学与大数据、人工智能等专业的课程设计、期末大作业及初期项目立项场景适合入门进阶与二次开发。项目通过控制接触率调整干预强度模拟不同防控措施对疫情发展的影响同时采用LSTM网络以前三日数据预测第四日新增趋势并计划将干预值纳入输入以优化序列建模。资源共31个文件包含12个py源码、14张PNG结果图、2份xlsx真实疫情数据以及2份md项目说明压缩包仅1.79MB目录层次清楚。源码附有详细注释和备份版本可快速理解模型构建、数据预处理与预测流程已有384人学习使用。对于希望掌握传染病动力学建模或LSTM时间序列预测的读者是一份内容完整、可直接运行的参考资料。1. 把SEIR和LSTM拼在一起做新冠预测本质是补两种模型的窟窿基于传染病动力学模型SEIR和LSTM神经网络的疫情预测核心思路是把“机理建模”和“数据驱动建模”绑到同一条流水线上。SEIR能从传播机制上推出中期趋势但拟合不了实际场景里的干预扰动、统计口径变化LSTM能把曲线形状学得很像但对未来外推接近黑匣子。两者拼在一起既保留可解释性又提高数值拟合度是目前做新冠疫情预测最常见的混合建模方案之一也是做毕业设计、数据竞赛和科研基线时绕不开的套路。这篇笔记会一次性讲清楚SEIR的离散差分实现、LSTM的数据集构造与训练、两条拼接路线以及五类我在复现过程里实实在在踩过的坑。2. SEIR模型先落地从四仓室方程到最小Python实现2.1 SEIR的四个仓室和三个参数先会读方程再会调参数SEIR里的四个仓室分别是 Susceptible易感者、Exposed暴露者、Infectious感染者、Recovered康复者。它比SIR模型多一个E仓室用来装“已经感染但还没具备传染力、也未必确诊”的人群。新冠疫情恰好有明确的潜伏期和确诊滞后如果直接上SIR潜伏期和确诊延迟会被一起揉进接触率里拟合出来的beta和gamma可信度很低。所以在疫情预测这个目标下SEIR是比SIR更贴合真实场景的起点。模型的流转方向是 S → E → I → R三个核心参数控制每一步的速率beta有效接触率单位是 1/天含义是单位时间内一个感染者与易感者有效接触并造成感染的概率sigma潜伏期转感染速率通常取 1/潜伏期均值gamma康复速率通常取 1/感染期均值。真正影响最终曲线形状的往往不是单个参数的绝对大小而是 beta/gamma 的比值也就是基本再生数R0。做参数拟合的时候我一般会先用R0的先验范围约束beta和gamma的搜索空间再去枚举sigma比三个参数一起暴力搜索省事得多。另一个值得注意的点是这里默认总人口不变且康复后不再感染对短期预测可以接受但如果预测周期超过两个月就要考虑抗体衰减和疫苗接种带来的仓室变化。2.2 用一阶差分把微分方程改写成可运行代码常微分方程形式在数学上很干净但落到Python里一阶差分迭代才是更多人能接手维护的写法。下面这段代码是显式欧拉法的SEIR输入总人口、暴露者初始值、感染者初始值和三个速率参数输出每天每个仓室的人数。import numpy as np def seir_model(total_population, exposed_initial, infectious_initial, beta, sigma, gamma, days, h0.1): 一阶差分实现 SEIR 模型显式欧拉法 Parameters ---------- total_population : int 总人口用于推算易感者初始值 exposed_initial : int 暴露者初始值 infectious_initial : int 感染者初始值 beta : float 有效接触率单位 1/天 sigma : float 潜伏期转感染速率单位 1/天 gamma : float 康复速率单位 1/天 days : int 预测总天数 h : float 内部差分步长天默认 0.1 Returns ------- np.ndarray, shape (days 1, 4) 每天对应的 [S, E, I, R]索引 0 表示第 0 天 # 初始状态总人口减去暴露者和感染者剩下的都是易感者 susceptible_initial total_population - exposed_initial - infectious_initial state np.array([susceptible_initial, exposed_initial, infectious_initial, 0.0], dtypefloat) result [state.copy()] # 内部步数每个自然日走 1/h 步 steps int(days / h) for step in range(steps): S, E, I, R state # 新暴露人数beta 乘 S 乘 I 再除以总人口避免全部人口瞬间被感染 new_exposed beta * S * I / total_population # 暴露者转感染者 new_infectious sigma * E # 感染者康复 new_recovered gamma * I # 按差分步长更新状态 S_next S - new_exposed * h E_next E (new_exposed - new_infectious) * h I_next I (new_infectious - new_recovered) * h R_next R new_recovered * h # 已经康复的不再倒回去欧拉法可能冲出负数用 max 做非负保护 state np.array([max(S_next, 0), max(E_next, 0), max(I_next, 0), max(R_next, 0)], dtypefloat) # 只在每天整点记录一次结果 if (step 1) % int(1 / h) 0: result.append(state.copy()) return np.array(result)逻辑说明显式欧拉法每一步只用当前时刻的状态计算变化量再用变化量乘以步长 h 更新状态。外层循环实际执行 days/h 步但只在整数天位置记录所以返回数组的长度是 days 1。恢复人数I/R的更新没有除总人口因为sigma和gamma本身就是速率而beta因为依赖于接触概率通常用beta * S * I / N的形式做归一化让S和I的数量级不直接影响接触率。参数说明sigma 对应潜伏期的倒数新冠潜伏期均值大约 5.2 天所以 sigma 建议在 1/5.2 到 1/6.4 之间gamma 对应感染期倒数一般取 1/7 到 1/10beta 才是真正需要反复拟合的变量。要注意的是如果真实数据集统计的是“确诊人数”而不是“实际感染人数”那么I仓室的含义和数据集对不上输出曲线就很难校准。这个口径问题后面避坑章节还会详细展开。2.3 离散化步长对结果的影响为什么1天一步不稳当很多初学者拿到这段代码后做的第一件事就是把 h 改成 1结果发现当 beta 偏大时易感人数被快速耗尽E 和 I 出现振荡甚至负数。这其实是显式欧拉法的数值稳定性问题步长太大时线性化误差会不断放大。h 取 0.1相当于把每个自然日切成 10 份积分计算量增加 10 倍但曲线平滑度和稳定性都明显改善。在实际项目里我有一个固定的验证流程用h0.1 和 h0.05 各跑一遍观察疫情峰值高度和峰值日期。如果两次结果相差超过5%说明模型对步长敏感此时调参数没有任何意义应该先把步长缩小到结果收敛为止。参数典型取值范围说明beta0.2 ~ 0.8取决于干预强度分段设置更合理sigma1/5.2 ~ 1/6.4潜伏期均值倒数gamma1/7 ~ 1/10感染期均值倒数h0.05 ~ 0.1内部差分步长越小越稳定days30 ~ 120预测窗口超过120天需引入新仓室另外随着管控措施的变化把beta设成固定值并不合理。更常见的做法是分段处理比如某段时间封控beta取低值解封后beta回升。分段参数会让LSTM的输入多一个特征维度后面混合建模时会用到这个思路。3. 用LSTM预测疫情曲线数据预处理和PyTorch最小实现3.1 从RNN到LSTM为什么时间序列预测默认选LSTMLSTMLong Short-Term Memory是循环神经网络的一种变体引入遗忘门、输入门和输出门三个门控结构解决RNN在长序列上梯度消失或者梯度爆炸的问题。疫情数据天然是时间序列前一天的数字会影响后一天而且影响可以跨周末、跨潜伏期传导这种长时间依赖是普通RNN处理不了的。所以在做“lstm时间序列预测python”这类需求时LSTM几乎成了默认选项。它不要求你对传播机制有精确的先验知识只要数据量大、序列长度合适它就能自动学到滞后相关和趋势相关。缺点也明确可解释性差几乎无法判断某个特征具体如何影响下一轮传播峰值这也是后面要和SEIR拼接的核心原因。只用LSTM预测测试集上看起来拟合度很高但一到未来外推就完全散掉这是我在新冠预测项目里最早翻车的地方。3.2 数据预处理阶段归一化、滑窗切分和训练/验证划分LSTM本身对输入数据的尺度非常敏感covid统计数字动辄上千上万直接喂给tanh激活函数梯度会被压到几乎没有。因此第一步一定是归一化。我自己常用的是标准化方式也就是减均值再除以标准差而不是按最大值缩放到0-1。原因是疫情的后续峰值可能远超历史最大值如果用min-max归一化未来真实数据天然落在训练区间之外反而引入系统偏差。滑动窗口是另一个高频出错点。时间序列预测的常见做法是用过去N天数据预测未来1天或未来K天这个N就是lookback窗口。窗口太短捕捉不到潜伏期和传播周期的影响窗口太长输入维度膨胀训练成本高且容易过拟合。对新冠数据我一般先尝试7天、14天、21天三档用验证集对比后确定。下面的代码实现了数据标准化、滑动窗口切分、训练验证划分三个步骤import numpy as np from sklearn.preprocessing import StandardScaler def build_sequences(data, lookback14, horizon1): 将原始序列切成 (lookback, features) 的输入和 (horizon,) 的标签 Parameters ---------- data : np.ndarray, shape (samples, features) 标准化后的多维特征第一列一般是每日新增确诊 lookback : int 用过去多少天做输入默认 14 horizon : int 预测未来多少天默认 1 Returns ------- X : np.ndarray, shape (n_samples, lookback, features) y : np.ndarray, shape (n_samples, horizon) X, y [], [] for i in range(len(data) - lookback - horizon 1): X.append(data[i:i lookback]) y.append(data[i lookback:i lookback horizon, 0]) return np.array(X), np.array(y) # 原始数据格式每一行是 [每日新增确诊, 每日新增治愈, 管控强度特征] raw_data load_covid_data() # 自己用 pandas 读入后转成的 ndarray # 用训练集拟合标准化参数验证集和测试集只做 transform train_size int(len(raw_data) * 0.7) val_size int(len(raw_data) * 0.15) train_raw raw_data[:train_size] val_raw raw_data[train_size:train_size val_size] test_raw raw_data[train_size val_size:] scaler StandardScaler() train_scaled scaler.fit_transform(train_raw) val_scaled scaler.transform(val_raw) test_scaled scaler.transform(test_raw) X_train, y_train build_sequences(train_scaled, lookback14, horizon1) X_val, y_val build_sequences(val_scaled, lookback14, horizon1) X_test, y_test build_sequences(test_scaled, lookback14, horizon1) print(f训练集样本数 {X_train.shape[0]}验证集样本数 {X_val.shape[0]}测试集样本数 {X_test.shape[0]})逻辑说明标准化只用训练集的fit_transform验证集和测试集只做transform这步是防止数据泄漏的关键所在后面避坑章节还会单独剖析。build_sequences把数据切成固定长度的滑动窗口X的维度变成 (样本数, lookback, 特征数)这是LSTM输入的标准形状。标签取的是窗口之后第一行的第一列也就是每日新增确诊。参数说明lookback14 对应两周刚好覆盖一个常见潜伏期加检测滞后期horizon1表示只预测第二天如果要做7天预测可以把horizon设为7但y的维度从1变成7后损失函数计算方式要调整不能直接套MSE。还有一点很容易被忽略如果原始数据里有周末不统计的情况会产生周期性的零值这些零值会让序列训练严重失真一般建议先把原始数据做七日移动平均平滑再做滑窗。3.3 最小可运行LSTM网络结构、损失函数和训练循环LSTM模型的代码本体其实不长我用PyTorch写的一个最小可用版本如下。import torch import torch.nn as nn import torch.optim as optim class CovidLSTM(nn.Module): 一个隐藏层 LSTM 全连接输出层 def __init__(self, input_size, hidden_size64, dropout0.2): Parameters ---------- input_size : int 输入特征数和滑动窗口最后一维一致 hidden_size : int LSTM 隐藏状态维数 dropout : float Dropout 比例防止过拟合 super(CovidLSTM, self).__init__() self.lstm nn.LSTM(input_sizeinput_size, hidden_sizehidden_size, num_layers1, batch_firstTrue, dropoutdropout) self.fc nn.Linear(hidden_size, 1) def forward(self, x): # x shape: (batch, lookback, input_size) out, _ self.lstm(x) # 取最后一个时间步的输出shape 变为 (batch, hidden_size) last_out out[:, -1, :] # 全连接层输出一个数 return self.fc(last_out) def train_model(model, X_train, y_train, X_val, y_val, epochs150, lr0.001, patience15): optimizer optim.Adam(model.parameters(), lrlr) criterion nn.MSELoss() best_val_loss float(inf) bad_epochs 0 for epoch in range(epochs): model.train() optimizer.zero_grad() inputs torch.tensor(X_train, dtypetorch.float32) targets torch.tensor(y_train, dtypetorch.float32) outputs model(inputs) loss criterion(outputs, targets.unsqueeze(-1)) loss.backward() # 梯度剪裁防止疫情大数值样本带来的梯度爆炸 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0) optimizer.step() model.eval() with torch.no_grad(): val_inputs torch.tensor(X_val, dtypetorch.float32) val_targets torch.tensor(y_val, dtypetorch.float32) val_outputs model(val_inputs) val_loss criterion(val_outputs, val_targets.unsqueeze(-1)) if val_loss best_val_loss: best_val_loss val_loss bad_epochs 0 torch.save(model.state_dict(), best_model.pth) else: bad_epochs 1 if bad_epochs patience: print(fearly stop at epoch {epoch}, best val loss {best_val_loss:.4f}) break if epoch % 10 0: print(fepoch {epoch}, train loss {loss.item():.4f}, val loss {val_loss.item():.4f}) # 回归结束后用验证集最优模型 model.load_state_dict(torch.load(best_model.pth)) return model逻辑说明CovidLSTM先经过单层LSTM提取序列特征再取最后一个时间步的隐藏状态扔进全连接层输出预测值。LSTM层的输出是 (batch, lookback, hidden_size)取 out[:, -1, :] 就拿到了最后一天的语义表示。训练循环里每个epoch都重新计算输入输出MSE作为损失函数Adam作为优化器。关键操作是梯度剪裁因为疫情数据在标准化之前可能已经到了数千量级标准化后再经过LSTM偶发的大梯度仍可能炸掉训练过程。参数说明hidden_size64对中小规模数据集是稳妥起点增大到128或256会提升拟合度但过拟合风险也同步增加dropout0.2提供了显式正则化batch_firstTrue让输入形状保持和numpy数组一致避免维度混淆。损失函数用MSE是对的因为这是回归任务不能用交叉熵。如果你想同时预测未来7天输出层需要改成nn.Linear(hidden_size, 7)MSE的计算也要对齐维度。4. 把SEIR和LSTM接在一起两条技术路线和适配场景4.1 路线一SEIR生成模拟数据预训练再用真实数据微调真实疫情数据通常只有几十到几百个有效样本点直接训练LSTM属于用大数据方法硬啃小样本问题过拟合几乎是必然的。这时候SEIR可以充当“数据发生器”用不同参数组合跑出大量模拟曲线把这些模拟数据作为预训练集喂给LSTM让模型先学到传播机制的通用规律再用真实数据微调最后一层或全模型。做法上第一步是准备好参数网格比如beta在0.2到0.8之间取20个值sigma在0.15到0.3之间取10个值gamma在0.1到0.3之间取10个值总共2000组参数组合。每组参数跑90天每组都能得到几条曲线新增、累计、康复。把这些曲线切片成滑动窗口样本就得到一个庞大的预训练数据集。预训练时用正常的MSE等loss稳定后把模型加载到真实数据上继续跑几十个epoch学习率调成原来的十分之一。我实际用过一次这个方案效果最好的场景是真实数据只有40天而SEIR模拟数据有2000条90天曲线。预训练让模型记住了“疫情曲线的大致形状”微调则把形状匹配到真实曲线的垂直尺度上。这个方案的短板在于SEIR参数和真实传播过程的差距会直接污染预训练数据如果SEIR参数空间没选好模型学到的是错误的“先验”微调阶段很难完全纠正。4.2 路线二SEIR做基线LSTM只学残差残差校正是更常用的方案也是我在多个疫情预测项目里最终选定的路线。思路是先校准SEIR参数让SEIR预测出一条基线曲线然后用LSTM去拟合真实曲线与SEIR曲线之间的差异也就是残差最终预测等于SEIR基线加上LSTM残差。这样LSTM不用去预测绝对值只需要预测“SEIR漏掉的那部分”任务难度显著降低。残差预测的代码实现也不复杂。首先用校准好的SEIR参数得到连续90天的预测值然后计算真实每日新增确诊减去SEIR每日新增的残差序列把残差序列当作LSTM的目标值。LSTM输入截取真实数据的滑动窗口输出就是残差。# 假设 seir_predict 是 SEIR 模型输出的每日新增感染序列 # true_cases 是真实每日新增确诊序列 # 两者长度需要先对齐用滚动窗口处理起始段的滞后差 residual true_cases - seir_predict # 标准化残差然后切滑动窗口 scaler_residual StandardScaler() residual_scaled scaler_residual.fit_transform(residual.reshape(-1, 1)) X_res, y_res build_sequences(residual_scaled, lookback14, horizon1) # 训练残差预测模型 model_res CovidLSTM(input_size1, hidden_size32) model_res train_model(model_res, X_res, y_res, X_val_res, y_val_res, epochs100, lr0.001) # 预测最终结果 SEIR 基线 残差反标准化后的 LSTM 输出逻辑说明残差序列切窗口时lookback仍然取14但输入特征只有残差一列。SEIR基线已经吸收了趋势和传播机制残差通常围绕0波动LSTM在这种序列上更容易收敛也不用担心绝对值数量级过大。最终预测时把SEIR的下一天预测值和LSTM的下一天残差预测加起来就是完整结果。这个方案的好处非常明显即使LSTM在最后几天外推失效SEIR基线也能兜底不会出现整体预测崩塌的情况。避坑指引只有一句话确保SEIR基线和真实曲线口径一致。如果SEIR输出的是“累计感染”而你拿真实“每日新增”去算残差结果必然是一堆趋势项残差LSTM学到的全是无意义的伪规律。4.3 两条路线怎么选看数据规模和SEIR的校准时长选择原则我认为主要看两个条件真实数据样本量和SEIR能否被快速校准。如果真实数据少于60个采样点单靠LSTM没有任何可靠建树走路线一用SEIR预售更好如果真实数据有100个以上采样点且SEIR参数通过优化算法能在半小时内收敛走路线二更直接解释性和稳定性都更好。如果是疫情期间做实时决策压根没有时间去反复校准SEIR路线二的前期成本就可能太高此时宁可选择路线一用参数范围覆盖不确定性。还有一个混合做法值得提一下路线一的预训练模型可以在微调阶段继续用SEIR同步生成动态数据增强也就是在训练循环里定期补充新SEIR仿真样本。这种做法的成本是训练时间增加但对防过拟合有明显帮助。业务上如果对解释性要求高最终汇报展示时采用SEIR的物理曲线为主、LSTM的残差修正为辅双方都有交代。5. 避坑排查疫情预测里LSTM的五个常见翻车点5.1 数据泄漏归一化的“全局统计量”带着未来信息现象训练集loss低到0.01验证集loss却高达0.5模型在训练集上近乎完美一到验证集就恢复平庸。原因这是我在项目里遇到最隐蔽的坑。如果对整个数据集先归一化再划分训练验证StandardScaler的mean和std就已经包含了未来数据的信息模型在训练阶段其实偷看了答案的分布。虽然看起来只差一个均值但疫情曲线是强趋势序列后期峰值远高于前期全局均值会把前期数值压到负数后期数值又过大导致训练集和验证集的数据分布根本不是同一个尺度。解决严格按“训练集fit、验证集和测试集transform”的顺序处理并且在切分滑动窗口之前不做任何跨样本的统计计算。代码里我已经用train_raw做fit_transformval_raw和test_raw只做transform这就是正确顺序。血的教训是早期版本我写过加载全部数据后统一scaler结果看起来精度极高实际一上线就崩。5.2 周末效应病例数周期性波动被LSTM当成规律现象模型预测曲线呈现明显的7天周期抖动每一周的第几天会出现固定峰值或谷值而这个规律在实际部署时根本不存在。原因不少公开数据源在周末统计口径会变化周六周日报送病例数偏低周一甚至可能把过去两天的数据一起补报上去。LSTM学到的是“序列里每隔7天有一个低谷”的表象把它当成了真实的传播规律。这种周期本质是统计噪声不是传染动力学特征。解决训练前对原始数据做七日移动平均把周末效应平滑掉。另一个办法是把星期几作为外生特征传入LSTM但这会让模型记住统计口径的规律预测未来时如果数据源口径变了反而误导模型。我在两个做过对比加星期特征看似提升拟合度但一到跨月预测就产生“每周幻觉”所以宁可先平滑再建模。平滑操作要在归一化和滑动窗口之前完成保证随后所有处理的序列都不带这种伪周期性。5.3 过拟合与梯度爆炸loss降不下来先查学习率现象训练到第50个epoch时验证集loss不降反升训练集loss还在稳步下降另一种现象是训练开始几轮loss直接变成NaN。原因前者是典型过拟合模型开始记忆训练集噪音后者通常是学习率过大加梯度爆炸特别是疫情数据标准化后仍有离群值LSTM在时间维度上的梯度穿过多个时间步后会指数级放大。解决过拟合用早停加Dropout早停的patience设为15Dropout保持0.2到0.3。我不能强调太多的是学习率不要一上来就用0.010.001是更稳定的起点如果还是NaN就降到0.0005。同时梯度裁剪我放在backward之后step之前max_norm选1.0这比调整网络结构更快解决问题。另一个隐藏很深的坑PyTorch中LSTM即使设置了dropout参数在单层LSTM下也可能不生效所以如果网络层数只有1层要么叠两层LSTM要么靠早停和正则化兜底不能寄希望于dropout这一个参数。5.4 预测曲线过于平滑MSE在均值回归现象测试集上MSE分数还行但画出来的预测曲线几乎是一条直线没有明显峰值和真实曲线的剧烈波动差距很大。原因MSE损失函数天然倾向预测未来序列的平均值。疫情数据中峰值日的数值可能是平时的好几倍MSE会把预测结果向样本均值方向拉导致输出曲线被严重“压平”。这也是疫情预测里LSTM的经典问题之一不是模型没学会而是它在尽量降低错误惩罚的代价。解决第一种方案是对标签做log1p变换先取log再标准化然后在反标准化时用expm1还原。这能把大数值峰值压缩到和普通天数相近的量级让MSE不再被极端峰值主导。第二种方案是改用分位数损失或Huber损失不顺滑地惩罚误差。Huber损失在这里可以同时兼顾曲线峰值和普通段的拟合比单纯调网络结构有效得多。如果预测目标是“拐点位置”而不是“精确数值”还可以转成分类问题预测未来趋势是上升还是下降绕过数值回归的均值陷阱。5.5 SEIR参数无法识别率参数并非都能被数据唯一确定现象对同一组真实数据跑优化初始化不同会收敛到完全不同的参数组合而且每组参数跑出来的拟合效果都一样好但预测结果差别很大。原因SEIR的状态方程是耦合的不同的beta/gamma组合可能产生非常接近的曲线这种“参数不可辨识性”在传染病模型里特别常见。试想一下感染期长短和接触率同时变大一倍R0保持不变曲线形状短期内可能难以区分。你对参数的先验越弱模型越容易在多个局部最优之间摇摆。解决在优化时加入R0的先验范围比如新冠早期R0大约在2.2到3.5之间把这个约束放进目标函数作为正则项。另一个办法是固定sigma和gamma为文献值只拟合beta这样参数空间从3维降到1维鲁棒性显著提升。如果你发现训练结果显示参数跨了很大区间及时用后者做约束更实用。6. 验证和进阶不只汇报RMSE还要看峰值偏移量模型做出来后验证这件事我吃过很多亏。一开始我也只汇报测试集RMSE后来发现两个模型RMSE相差不到1%但一个预测峰值在第42天另一个在第51天而峰值日期恰恰是决策方最关心的指标。所以现在我的验证报告固定看三类指标整体RMSE、峰值日期偏差、峰值强度偏差。峰值偏差可能比RMSE更致命尤其是当你预测的最终目的是判断医疗资源饱和度时。进阶做法是多步滚动预测验证。很多LSTM疫情预测项目只汇报“一步预测”效果也就是用第N天之前的数据预测第N1天这个任务过于简单模型大部分时间在复制最近几天的趋势。真正有挑战的是“未来7天窗口”预测用第N天之前的数据一次输出第N1到第N7天的值然后再滑到下一天。我会在测试集上跑这种滚动评估记录未来7天窗口内的平均误差这比单点预测更能暴露模型外推能力的短板。最后一个实在的建议如果预测结果要用来做展示或决策把SEIR的预测曲线和LSTM残差修正部分分别画出来决策方看到拟合效果的同时也能理解趋势来源。LSTM部分如果输出不稳定可以在预测阶段做多次dropout采样取多次预测的均值这相当于用模型自带的不确定性做一次蒙特卡洛估计。我早期一直追求单次预测最高精度后来才发现稳定比精确重要多次采样取均值的策略虽然不能提升峰值精度但能实实在在地减少曲线抖动也能给出置信区间。做完整套流程之后我现在动手新项目的第一件事永远是先检查口径再规划训练验证划分方案最后才调模型结构。这个习惯帮我避开了很多无形中的翻车。希望帮到你。本文还有配套的精品资源点击获取