多元时间序列预测一直是数学建模竞赛里的重头戏。不管是华为杯还是研究生数学建模,碰到交通流量预测、空气质量预报、电力负荷预估这类题目时,最大的难点往往不是模型不够复杂,而是变量之间的关系压根不是静止的。你用一个固定矩阵描述变量关联,结果新数据进来就失效;你说变量之间相互独立,又把真实场景里“PM2.5浓度影响能见度,风速反过来稀释PM2.5”这种强耦合关系全丢了。我最近深入研究了一个叫FACT的方法——用细粒度跨变量卷积建模动态变量交互,把跨变量依赖从静态变成了动态,处理和这类问题很顺手。这篇文章不聊虚的,直接拆解这个方法的原理,然后结合建模竞赛实战场景,讲清楚怎么落地用起来。
1. 先搞明白:动态变量交互到底难在哪
建模竞赛里,大家最常用的一套预测思路是:把每个变量当成一条时间序列,然后用LSTM、GRU或者Transformer去拟合时间依赖。这个方法在变量少、关系简单的时候效果还行,一旦变量数量上来,比如一个城市空气质量数据集里有PM2.5、PM10、O3、NO2、SO2、CO、风速、风向、气温、湿度,你就会发现单变量建模有一个致命伤——变量之间隔着一条信息鸿沟。
这里我拿一个生活化场景来类比。你把一组传感器当成一家公司里的员工,每个员工都记录自己的KPI。单变量建模就相当于每个员工只看着自己的历史业绩做下季度规划,完全不关心其他人手里的资源、市场动态、协作进度。这种模式下,遇到系统性风险时所有员工都会同时误判。在空气污染场景里,某天突然刮起大风,如果只看PM2.5的历史趋势,模型会给你报一个“持续累积”的预测,但事实上风速这个变量已经悄悄把污染物稀释了。这个信息就被漏掉了。
跨变量卷积建模解决的就是这个信息孤岛问题。FACT的核心思路是把变量维度和时间维度分开处理,然后用卷积的方式让变量之间互相“看见”对方。这个方向不只FACT在做,Crossformer、DLinear、PatchTST这些模型都往这个方向探索过,但每个方法都有自己的局限。Crossformer用全连接层把所有变量一次性融合,参数规模随着变量数量平方级增长,且学到的是静态关联;PatchTST在时间维度上做得极其精美,却在跨变量维度上选择了一条清晰的“channel independent”路线,主动放弃变量交互;DLinear更是直接用线性层摊平一切,交互深度不足。
我用一个表格把主流方案和FACT的差异梳理了一下,这样看更直观:
| 模型 | 跨变量建模方式 | 动态交互能力 | 信息瓶颈 | 适用场景 |
|---|---|---|---|---|
| LSTM/GRU单变量建模 | 无跨变量交互 | 无 | 漏掉变量耦合关系 | 独立序列 |
| Transformer类(全局注意力) | 全变量两两关联 | 弱(静态权重为主) | 计算量随变量数平方增长 | 小规模变量 |
| Crossformer | 全连接跨变量嵌入 | 较弱(矩阵固定) | 参数冗余,难以捕捉突变的交互关系 | 变量关系稳定场景 |
| DLinear | 单层线性映射 | 无 | 过度简化非线性关系 | 基准对比 |
| FACT | 细粒度跨变量卷积 | 强(逐时间步动态生成卷积核) | 计算量可控,无显著瓶颈 | 高维动态关联的多元时间序列 |
这个对比最关键的落点是FACT的“动态”这个属性。传统方法做跨变量交互时,通常学习一个固定的权重矩阵,比如变量A对变量B的影响系数是0.5,那就是0.5,不管今天空气质量是优还是重度污染,这个关系都不变。但现实世界不是这样的:晴天的时候太阳辐射对臭氧生成的影响极其显著,阴天的时候这条链路几乎失效;工作日早高峰的交通流量和事故率高度相关,凌晨两点这个相关性就完全不存在。这就是动态变量交互的真实含义——变量之间的耦合强度会随着时间、随着外部状态的变化而改变。
FACT针对这个痛点,把跨变量建模拆成了“细粒度”的操作:不是一次性在所有变量上做一个粗粒度融合,而是先把变量的特征分解成共享特征和变量特定特征,再按时间步动态更新卷积核。这东西听起来抽象,但本质上就是你在看数据的时候,不要问“A和B整体上是什么关系”,而是问“在t这一刻,A和B之间正在发生什么关系”。后面我详细拆这个机制。
还有一点需要提醒:建模竞赛中很多人碰到变量多的问题,第一反应就是做个特征选择或者PCA降维,删掉几个“不太重要”的变量。这个思路在处理线性关系时有效,但碰上非线性耦合场景,很可能删掉的那几个“次要变量”恰恰在某个时间段里占据了主导地位。风速这个变量在空气污染预测中经常被当成弱特征,可一旦发生沙尘暴或者强对流天气,风速就成了决定性因子。FACT这类模型的好处是:它可以完整保留变量,然后在训练过程中自行决定每条变量交互路径的强弱。数据本身会告诉你哪条交互通道在这个时间窗口里变强了,哪个变弱了。
2. 细粒度跨变量卷积的核心机制拆解
2.1 共享特征与变量特定特征的分离
FACT一开始做的不是直接卷积,而是对输入数据的特征空间做了一个划分:一部分是共享特征,一部分是变量特定特征。为什么非得这么做?我实际跑实验时的理解是这样的:如果直接把原始变量扔进卷积核,卷积核会被每个变量自身的量纲和分布搞乱。风速的数值可能是0到20,PM2.5的数值可能是0到500,CO的数值可能只有0到5——这几种特征混在一起生成卷积核,模型得花大量参数去区分量纲,真正学习交互关系的参数反而被挤占了。
共享特征的设定是:在t这个时间截面上,各个变量之间共有的那部分信息,比如整体趋势、共同的周期波动、同源驱动的变化。这个思路跟时序分解里的Seasonal-Trend Decomposition很像,只不过FACT把它嵌入到了特征提取层内部。变量特定特征则是每一个变量自己独有的信息,比如PM2.5自身的高频抖动、某个传感器特有的噪声模式。
我在处理竞赛数据时发现一个有用的小操作:在进入模型之前,先手动把原始数据做一次标准化和趋势对齐。共享特征部分最好使用同一套scale进行标准化,变量特定特征则各自单独标准化。这个预处理方式能让FGCC的分解模块更早收敛,你在训练前期就能看到一个相当平滑的损失下降曲线。很多同学喜欢“一把梭”直接喂原始数据,结果损失曲线抖得跟心电图一样,这往往是量纲问题没有预先处理到位。
2.2 动态卷积核的生成逻辑
FGCC最核心的操作为什么叫“细粒度”?这个细体现在它生成卷积核的粒度上。传统卷积网络在图像处理里的逻辑是一个卷积核扫遍全图,但FGCC不这么干。FGCC是为每一个时间步、每一组变量组合,动态生成对应的卷积核。
打个比方,传统跨变量建模像是你拍了一张全景照片,然后用一个固定的滤镜去处理整张图;FGCC的做法是把照片按时间和区域切成很多小块,每一块重新计算当前光线下应该用什么参数去调整。
这个动态生成的过程在代码层面可以拆成这样几个步骤:
第一步,输入特征先经过一个共享嵌入层,得到一个中间表示H。这个H包含了当前时间步所有变量的信息压缩。
第二步,通过一个核生成网络,把H映射为一组卷积核参数。这个网络本身不复杂,通常就是两层全连接加非线性激活,复杂之处在于:输出的卷积核参数数量随变量数变化,但它是动态生成的,所以能实时反映当前各变量的状态。
第三步,用生成出来的卷积核跟变量特征做卷积操作。此刻的卷积不是全变量的大融合,而是细粒度地在相关的变量子集上做局部卷积,单个注意力集中到了“这个时间点哪些变量在协同变化”上。
核生成网络的参数是固定的,网络本身是静态训练的,但输入到网络里的特征是变化的,输出卷积核因此也是逐时间步变化的。用口语一点说就是:网络学了一个“如何快速计算卷积核”的函数,而不是直接学一个固定的卷积核。
我刚理解这个概念的时候,想到了一个特别贴切的比喻:你把卷积核想象成做饭时的菜谱。FACT不是给你一本固定的菜谱让你天天照着做,而是每次根据冰箱里有什么食材(当前变量的状态)、当前天气和环境(时间步状态)、吃饭人的心情(上游特征),临时帮你写一道新菜谱。所以每次做出来的菜都能贴合当下情况。
2.3 卷积如何“跨变量”而不丢失时间信息
跨变量卷积最容易出现的毛病是:做变量融合的时候把时间顺序打乱了,导致模型只记住了变量间的空间关系,忘了时间上的先后依赖。FACT在设计上避开了这个坑——它的FGCC模块只负责处理变量维度的交互,时间依赖的建模是由另一个模块TCC(Temporal Convolution Component)单独负责的。
这些设计理念落实到竞赛工程里的意义是:你在实现的时候可以把两个模块串在一起,先让FGCC对每个时间截面的变量做交互建模,把融合后的特征按时间顺序排列,再交给TCC做时间维度的卷积。特征先横向融合,再纵向积累。这个串联结构保证了信息在两个维度上的流动是有序的,不会混在一起。
实际操作过程中,可以留意一下两个模块的嵌入维度设置。我试过几组组合,发现FGCC的输出维度保持与输入维度一致,或者略大一点,然后TCC的卷积核尺寸设置成覆盖2到4个时间步,整体效果最稳定。如果你把TCC的卷积核设得太大,比如覆盖10个时间步,时间依赖会被过度平滑,曲线的尖峰和突变细节会丢失。这点和图像卷积的直觉是一样的:卷积核越大,捕捉的越偏向全局趋势,细节分辨越低。
3. 建模竞赛场景下的FACT落地实操
3.1 数据预处理的四个关键动作
不管是华为杯还是其他建模竞赛,拿到数据的第一件事情永远是清理和结构梳理。我在处理多元时间序列数据时,基本会固定走四个动作:缺失值处理、异常值识别、序列平稳化、滑窗构建。
缺失值处理这块,多元时间序列和单变量不一样,你不仅要看单个变量自己的缺失,还要看变量之间的缺失模式。比如风速和PM2.5同时缺失,和只有风速缺失,处理策略完全不同。前者可能指向传感器停机或者通信故障,补值方案要谨慎;后者可能只是随机丢失,线性插值就够了。FACT模型对缺失值敏感程度低于树模型,但也不能指望它自动处理一切,建议在进模型之前就把缺失补好。
序列平稳化上,常见的做法是差分或者取对数。在做完平稳化之后,需要把原始统计量记录下来,因为最后模型输出的预测值必须恢复成原尺度,否则你写论文的时候会发现预测结果对不上真实数据的单位。这个反变换步骤在竞赛论文的模型评估环节很容易被忽略,但评委用rmse一算就能发现你数据对不上。
滑窗构建是最影响训练效率的一步。窗口长度决定了模型能看到多长的历史信息,我一般用两个原则来确定窗口长度:第一,需要覆盖数据里最长的周期成分,比如交通流量数据有24小时周期,那窗口至少得涵盖24个时间点;第二,窗口长度宁长勿短,长了模型可以通过注意力机制自己决定关注哪段历史,短了想关注也关注不了。不过在FACT里窗口也不能太长,因为FGCC逐时间步生成卷积核,窗口越长,单次前向计算就要生成越多的卷积核,显存消耗会显著增长。我通常设置在24到96之间,具体看数据采样频率。
3.2 模型配置和训练细节
FACT在训练过程中有几个关键参数直接影响最终效果。嵌入维度是第一个要定的,这个值决定了特征表示的容量。我在小规模数据集上习惯用64,中等规模用128,如果数据量大且变量数超过20个,会考虑256。需要留意的是,嵌入维度过大在FGCC的核生成网络里会带来更多的参数,但收敛速度会变慢,所以不要在比赛初期一上来就开256这种大维度,先用128跑通全流程再考虑要不要加。
第二个参数是核生成网络的隐层维度。按我的经验,这个值设置在嵌入维度的1.5倍到2倍之间。它是学习和生成动态卷积核的主力,如果容量设置太小,生成的卷积核会缺少多样性,不同时间步之间卷积核的差异不明显,动态交互就退化成静态交互了。
学习率调度我用的是余弦退火加线性warmup。刚开始训练的前5个epoch用很小的学习率做warmup,让核生成网络先稳定下来,然后进入余弦退火阶段。这个做法的收益在FACT上体现得很明显——因为这个模型分两段式生成卷积核,信息流动链比较长,如果不做warmup,前期的梯度震荡会特别剧烈。
还有一个值得专门说的点:损失函数的选择。FACT原论文使用MAE或者MSE作为基础损失,但在竞赛场景里,我更建议使用Huber Loss或者平滑L1 Loss。原因很实在,因为竞赛数据里经常包含一些由于传感器故障、突发极端天气产生的离群值,MSE会对这些离群值给过高权重,导致模型的注意力被少数异常点吸引,动态卷积核的生成也被干扰。Huber Loss在误差接近零时表现为L2损失保证平滑,误差超过阈值后切换为L1损失限制梯度大小,对离群值鲁棒很多。我自己常用阈值为1.0,效果比较稳定。
3.3 评价指标和验证方式
数学建模竞赛里,预测类题目的评价指标通常给的是RMSE、MAPE或者皮尔逊相关系数。用FACT做预测时,我强烈建议你同时跟踪这三种指标,因为它们三个观察的角度完全不同:RMSE对大幅度误差敏感,MAPE看的是相对误差但真实值为零的时候会爆,皮尔逊相关系数看的是趋势一致性但完全不关心数值偏差。一个模型完全可能RMSE很高但皮尔逊相关系数接近0.9,说明趋势对了但幅值偏了;也可能反过来。写论文的时候同时报告这三个指标,也能让陈述显得更严密。
验证方式上,时间序列预测不能照搬普通机器学习的K折交叉验证——随机打乱就会让时间顺序错乱,造成严重的数据泄漏。推荐用滚动时间窗口验证法:用前70%-80%的数据训练,后面20%-30%的数据验证,然后在验证集上按时间步逐步前移,每移动一步就做一次预测和评估。这个方法最贴近真实预测场景,也是竞赛评委期望看到的验证方式。
4. 典型竞赛题目场景实战案例
4.1 场景一:空气质量预测里的强动态耦合
空气质量预测是多元时间序列建模竞赛里特别经典的一类题。题目一般会给过去几十天的多站点污染物浓度和气象数据,让你预测未来几天的PM2.5峰值浓度。这类题目的跨变量交互真实存在而且变化剧烈:白天太阳辐射强,NO2和挥发性有机物在光照下发生光化学反应生成臭氧,所以NO2和O3的交互关系在白天是正相关主导;到了夜间,光化学反应停止,O3会与NO反应重新消耗,交互关系就反转了。你要是用静态权重建模,这种日内反转的交互模式是学不出来的。
用FACT处理这个场景时,流程这样走:先把所有变量按15分钟频率重采样,做缺失插值,然后构造滑窗。FGCC模块会重点捕捉“当前时段臭氧浓度上升时,哪些变量正在协同变化”这类信息。我在实际训练中发现,动态卷积核在这个场景里很自然地聚焦到了NO2、太阳辐射、温度这组变量上,而在夜间时间步上,卷积核的关注重心会自动转移到NO、相对湿度上。不需要有人告诉模型你这个场景的化学机理,模型通过数据学出来的交互模式与大气化学常识相当吻合。
这个案例给竞赛选手的启发很直接:别一开始就想着把手头所有变量都塞进模型,也别因为怕复杂就删变量。动态交互建模本身就是让数据自己告诉你交互结构。如果题目给了30个变量,直接全部交给FACT,让FGCC自己挖掘结构,然后你在论文里把学到的交互权重可视化出来,呈现效果和物理含义阐释都会好很多。
4.2 场景二:交通流量预测中的周期性交互转移
交通流量预测类的题目,典型的变量有各路段的流量、平均车速、车道占有率、天气状况、事件信息。周期性很强,但周期性本身不行交互会发生转移:早高峰期间,主干道流量和匝道汇入流量的交互最强,因为匝道拥堵直接拖垮主干道;平峰时段,这个链路就弱化甚至消失,流量和车速的交互变成主导。
这类数据有一个特点:交互模式在一天之内会发生多次切换,而切换的时刻和强度在不同星期几还不同。用FACT来处理,FGCC的核心优势被充分放大——它可以为上午8点生成一组卷积核,体现主干道和匝道的强关联;再为上午11点生成另一组卷积核,把交互重心转移到流量和车速上。模型通过整个数据集的训练,自动学习到了这套“按时间段切换交互模式”的逻辑。
竞赛写论文时,我习惯把动态卷积核在不同时间段的差异可视化,画一个热力图:横轴是时间步,纵轴是变量对组合,颜色深浅表示卷积核权重强度。这种图放在论文里非常直观,评委一看就明白你的模型确实建模了动态交互,而不是套了一个黑盒了事。热度图能显著提高模型的说服力,尤其是你还能指着图上说“早高峰这一块颜色明显变深了,说明模型捕捉到了主干道和匝道的协同”。
4.3 代码框架速写:一个最小可用的FACT结构
纯说理论容易飘,我自己整理了一个最小可用的PyTorch风格代码框架,帮你把FACT的核心结构串起来。这个代码不是完整的训练脚本,但你可以拿它当骨架,往里面填自己的数据读取和训练逻辑。
import torch import torch.nn as nn import torch.nn.functional as F class DynamicConv(nn.Module): """动态卷积核生成与跨变量卷积""" def __init__(self, input_dim, hidden_dim): super().__init__() self.input_dim = input_dim # 核生成网络:从共享特征映射到卷积核参数 self.kernel_fc1 = nn.Linear(input_dim, hidden_dim) self.kernel_fc2 = nn.Linear(hidden_dim, input_dim * input_dim) def forward(self, x): batch, ts, dim = x.shape out = [] for t in range(ts): xt = x[:, t, :].unsqueeze(-1) # (batch, dim, 1) # 动态生成当前时间步的卷积核权重 kernel = torch.tanh(self.kernel_fc1(xt.squeeze(-1))) kernel = self.kernel_fc2(kernel) # (batch, dim * dim) kernel = kernel.view(batch, dim, dim) # 使用矩阵乘法实现跨变量卷积 yt = torch.bmm(kernel, xt) # (batch, dim, 1) out.append(yt) return torch.stack(out, dim=1).squeeze(-1)这段代码要重点理解三个地方:
一个是卷积核参数的映射方式。kernel_fc2把隐层向量映射到input_dim乘以input_dim的维度,这就是一个完整的二维卷积核展开。对每一组变量对,都有对应的权重。这个权重的数值不是固定的,它由当前时间步的输入特征动态决定。
另一个是矩阵乘法的运算逻辑。torch.bmm(kernel, xt)利用二维卷积核作用于当前时间步的变量向量,相当于把变量之间的线性耦合关系应用了一遍。如果你想要非线性交互,可以在这层之后加一个激活函数,或者把卷积核的生成过程加深。
第三是for循环明显效率偏低。完整实现会用2D卷积或者矩阵批量乘法来替代显式循环,但这里用for循环是为了让你看清楚“逐时间步动态生成”到底是怎么发生的。竞赛场景里如果时间步很长,建议用torch.einsum做批量计算,能快很多。
4.4 在竞赛论文里如何讲清楚这个方法
竞赛论文和学术论文不同,不需要太厚的数学推导,但需要把“你用了什么方法,为什么管用,效果如何验证”讲明白。FACT这部分内容我建议在论文里按这样组织:
模型设计模块先引出问题——变量间结构是动态变化的,固定权重矩阵表达不了这种变化。中间放架构图,核心展示FGCC模块的输入输出流程。然后单独开一小节写动态卷积核生成机制,用一句话说明:卷积核由核生成网络基于当前时间步的状态实时计算得到,因此不同时间步的交互权重是可以瞬变的。再用前面那个热力图做可视化证据,最后给出消融实验:去掉FGCC换成静态全连接,计算预测误差上升多少。
这个组织方式的逻辑传导很顺畅:问题-方案-机制-证据-效果。评委顺着这个结构读下来,不用额外花精力去“猜”你这个模型blocks到底怎么工作的,印象分会高不少。
5. 常见问题与实操避坑经验
5.1 变量数量太大导致核生成网络参数爆炸
核生成网络把特征映射到input_dim的平方维度,如果变量数是50,那最后就要生成2500个权重的卷积核,参数规模一下就上去了。处理方式有两个:一个是对变量做分组,先按业务含义分组(气象组、污染组、交通组),组内用FGCC,组间用简单的全局融合,这样单次卷积核的规模会小很多;另一个是使用低秩分解,把卷积核矩阵分解成两个低秩矩阵的乘积,大幅压缩参数量。竞赛里如果变量在30个以内,不做低秩分解问题不大;超过30个,建议先分组。
5.2 动态卷积核训练不收敛
核生成网络离输入层比较近,收敛速度会直接影响整体模型的稳定性。我在调试时遇到过的典型困境:损失下降几个epoch后进入平台期,无论怎么调学习率都下不去。后来排查原因是卷积核的初始化方式。核生成网络的输出在初始阶段如果数值太大,矩阵乘法就会放大特征,导致梯度爆炸。解决方法有两种:把kernel_fc2的权重初始化设成均值为0、方差极小的分布;或者在生成卷积核后加一层LayerNorm,约束输出范围。后者效果更好,但需要多调一个归一化层的参数。
我在代码框架里没有加这个归一化,属于刻意留白。你真训练时如果发现前期损失锯齿状跳动,第一反应就往这里查,基本能解决。这个优化操作很值得记住,因为我换过好几种初始化方式,最后真正把稳定性拉起来的就是这个LayerNorm。
5.3 长序列预测误差累积
这个问题在竞赛预测题里极其常见:模型训练时用的是单步预测解码,验证时却让你预测未来24个时间点。单步预测每一步的误差都会喂给下一步,误差像滚雪球一样越来越大。FACT的全流程里有一个分层渐进预测的设计,把预测拆成多个层级,每层只预测一个较短的片段,然后用预测出的片段拼接成完整未来序列。这个层级结构对缓解误差累积效果很明显。竞赛里如果遇到长时间预测的题目,建议在FACT骨干上加一个自回归修正模块:预测每一段之后,将预测值反馈到输入窗口末尾,让模型看到自己的预测结果再做下一步决策。这会在训练和推理阶段增加一些时间成本,但预测精度提升是值得的。
5.4 竞赛数据噪声大导致动态卷积核抖动剧烈
竞赛数据的噪声水平通常比公开数据集更高。FGCC动态生成卷积核的特性在噪声大的时候容易出问题:卷积核随着噪声来回抖动,导致预测波动剧烈、方差变大。我的处理经验是给核生成网络加一个平滑约束,把相邻时间步生成的卷积核差值加入损失函数做正则项。具体操作是取出相邻时间步的卷积核矩阵,计算Frobenius范数差值,乘一个较小的权重系数加到总损失上。这个正则项能压制卷积核的高频抖动,让动态交互的变化更平滑、更贴近真实物理过程的连续性。毕竟真实世界里变量交互模式的切换通常不是阶跃的,而是渐变的。
5.5 快速判断FACT是否适合当前赛题
不是所有预测题都适合直接上FACT。我用朴素的标准做判断:如果题目给的变量少于5个,而且变量之间相关性本身很弱,那动态交互建模就是杀鸡用牛刀,直接上LSTM或者GRU,结果可能更好更稳;如果变量在5个以上,而且你观察到数据里有明显的联动现象或不同时间段的交互转移,比如交通、气象、能源这些场景,那FACT就处在能发力的范围内。
还有一个判断信号值得留意:先做一个快速的Granger因果检验,看看变量之间是否存在双向因果或者随时间变化的因果结构。如果检验结果显示滞后变量之间有显著的交叉预测能力,用FACT的动态交互建模会如鱼得水。如果因果结构很微弱,说明变量可能基本独立,FACT的优势就不明显。这个检验在动手训练模型之前花半个小时做一下,能给你省一整天的无效训练时间。
6. 写在最后:关于这个方法,我的一些实践感受
研究FACT的过程中,给我最大触动的点在于:它把“跨变量交互”这个被很多人用一句“注意力机制”带过的问题,重新拉回到一个可解释、可操作的粒度上。传统注意力机制确实能看到变量间的关联,但它给的是一个点乘相似度,缺乏空间结构的建模能力;FGCC直接生成卷积核来操作变量向量,交互不再是相似度分数,而是真正改变了特征向量的组合方式。这种区别在竞赛数据上的表现就是:预测曲线在突变时刻的响应更快,不再拖着长长的滞后。
建模竞赛不比拼谁的模型看起来更炫,拼的就是谁能更准确地还原数据背后的生成机制。FACT的思路之所以适合竞赛场景,本质上是它承认了一个事实:变量之间的不是固定不变的,而是会随着时间、随着外部条件不断重组的。把这个动态性建模出来,预测精度和解释力都会上一个台阶。如果大家在实际复现过程中遇到问题,欢迎随时找我讨论,我也很想知道这个方法在不同竞赛题目上的表现差异。