简介:2024华为杯研究生数学建模E题(高速公路应急车道紧急启用)参赛方案全套合集,面向参赛学生与建模爱好者,覆盖问题拆解、模型构建、代码实现到论文成文全流程。包内含25个文件,以9个Python求解脚本、8份PDF思路与论文、6份Word文档为主体,另有压缩包和说明txt,分别对应分问代码、详细建模过程、可视化汇总及数据说明,整体体积29.5MB,便于直接下载使用,目录结构清晰。已有330人学习浏览,适合急需系统参考或冲刺提分的队伍。资源不仅给出每问详细思路与高质量成品论文,还包含三套参考论文及代码更新说明,尤其提供Matlab/Python双版本求解代码与YOLOv8多车道元胞自动机仿真思路,可帮助读者快速理解应急车道启用的建模逻辑,并在比赛中直接借鉴或扩展。
1. 应急车道紧急启用这道题,本质是"检测-预测-决策"三联题
2024 华为杯研究生数学建模 E 题,围绕应急车道紧急启用展开:节假日返程高峰或突发事故后主路持续拥堵,要不要临时放行社会车辆进入应急车道,什么时机放、放多久、什么条件收回。表面是交通管理决策,拆开是一条完整的"检测-预测-决策"技术链路:先判定拥堵事件,再预测未来 15-30 分钟交通走势,最后求解应急车道的最优启用时机和时长。每个环节既要有可解释的数学模型,也要有可复现的 py 求解代码,最终整理成能直接支撑论文图表的计算管线。适合读这篇文章的人:备赛数模的队伍、做交通流与智能管控方向的研究生,以及想把应急策略模块落到实际项目里的工程技术人员。下面按拆题、建模、代码、避坑、交付五个部分讲透。
2. 赛题拆解与数据画像:三个子问题各自要什么
拿到赛题的第一件事不是查文献,而是把题目给的数据字段和已知条件摊开,做出"有什么数据、能算什么、缺什么"的清单。应急车道启用这类题,数据通常分三类:断面检测数据(流量、速度、占有率)、事件记录(事故、施工、节假日安排)、路网属性(车道数、应急车道位置、限速值)。三个子问题正好对应三条任务线:判定拥堵、预测状态、决策启用。这三条线不是割裂的,前一个问题的输出是后一个问题的输入,所以我建议先把数据口径统一好再做建模。另外提醒一句,赛题数据文件往往不止一张表,断面信息表、检测数据表、事件记录表之间靠传感器 ID 和时间戳关联,第一遍先把主键看清楚,后面省很多事。
2.1 流量-速度-占有率三元组:先理解检测数据口径再动手
检测器数据里最常见的三个字段是流量 q(辆/小时)、速度 v(km/h)、占有率 o(%)。它们不是三个独立变量,而是同一段道路交通状态在三个维度上的投影。流量和速度的散点形态能看出自由流和拥堵流的边界:自由流段速度高但流量不一定最大;同步流段速度下降但流量保持高位;堵塞流段速度和流量同时骤降,占有率抬到峰值。特别要注意的是,占有率序列对车辆堆积的响应通常比速度快一个采样周期——车辆在断面处减速排队的瞬间,占有率先抬升,速度后下降。这个先后关系是后续拥堵预判和特征工程的基础。
拿到数据后先把三个字段做时间对齐,统一重采样成 5 分钟粒度,流量用求和,速度和占有率用均值。处理时两个数据质量问题必须堵住。第一,单位不统一,有的断面给的是每车道每小时的折算流量,有的给的是断面总量,不先做单位校验就取平均,会算出离谱的"平均单车道流量"。第二,速度定义混淆,区间平均速度(路段长度除以行程时间)和检测点瞬时速度是两回事,混用会导致拥堵起止时间整体偏移。我一般会在清洗阶段打印每列的描述性统计,把单位、量纲、缺失率记录在一个 data_profile 文件里,后续写论文"数据说明"小节直接引用。
清洗完成后第一件事是画每个断面的 q-v 散点图和速度时间序列,用颜色标注工作日、节假日、夜间时段。这个图不直接产出结果,但它是后面所有阈值和模型选型的依据——你会发现不同断面的"拥堵速度阈值"差异很大,城市快速路和山区高速的临界速度可能相差 20 km/h 以上。所以我不建议用全局固定阈值,而是每个断面单独标定,或者用分位数自适应:取速度序列的 15 分位数作为候选阈值,再乘以 1.2 的安全系数,比拍脑袋定 45 更可解释,论文里也能给出完整标定过程。
缺失数据要单独统计,不要静默处理。我常用的分层策略是:每列缺失率超过 10% 的断面标记为低置信断面,建模时给低权重或直接剔除;缺失率在 3%-10% 的用线性插值;低于 3% 的前值填充就行。这个分层写在论文里,能看出你对数据质量有完整考量。
2.2 子问题一的判别逻辑:拥堵识别不是算个阈值那么简单
第一问通常是识别拥堵事件并给出起止时间。最朴素的做法是速度低于某个值且持续一段时间,但固定阈值有双向的毛病:阈值为 30 km/h 时,低速大流量的同步流状态会被漏掉;阈值提到 60 km/h 时,周末傍晚的常规缓行会被误判成拥堵事件。这两个错误方向在论文里都不好解释,因为评委随便抽一个时间点就能看出你的事件表不对。
我常用的判定是三个条件 AND:速度 15 分钟滑动平均低于 45 km/h,占有率相对同期基线抬升超过 15 个百分点,状态持续至少 15 分钟。三个条件分别对应"状态异常、突变确认、持续时间验证"。关键是占有率基线不能用全天均值,必须取"同一时段的历史中位数",否则早晚高峰的常态高占有率会被当成拥堵。更精细的做法是叠加变点检测——对占有率序列求一阶差分,差分超过某个百分位的位置作为候选起点,再用速度条件做二次确认。PELT 或二分段线性拟合这类变点方法适合处理"拥堵是渐变还是突变"的判别,但对 5 分钟粒度数据来说收益有限,三条件 AND 的性价比更高。
这一问的输出要结构化:一张事件表,字段包含 start_time、end_time、duration_min、峰值排队估算、受影响断面列表。事件表而不是一张热力图,是因为第二问的预测和第三问的决策都要拿事件表做输入。另外,每识别出一个事件,就顺手把持续时间和最大排队长度算好存下来,这两个变量在第三问的效益函数里直接用到。很多队伍到第三问才回头补这些特征,白白多跑一遍全流程。这一问的验收标准是:事件表里任意抽一个事件,你能在原始速度曲线上指出对应时段,并且起止时间误差不超过两个采样周期。
2.3 子问题二、三的联动:预测和决策为什么要分开建模
第二问做短时预测,第三问做启用决策。很多人把两个问题揉在一起:先用预测模型得到未来速度,再套一个"速度低于某个阈值就开启应急车道"的规则。这个思路论文里看着通顺,但经不起推敲。第一,预测误差没有传导机制,预测一偏决策跟着错,评委追问鲁棒性就答不上来。第二,预测解决的是"未来状态是什么",决策解决的是"在当前和未来的状态下,启用应急车道的收益是否大于代价",两者的目标函数不一样,不能共用一个规则。
正确关系是:预测模型输出未来 15-30 分钟的速度、占有率分布(不只是点估计),决策模型把这份分布当作输入之一,再结合排队长度估算、事故风险、切换成本做效益-成本最优化。也就是说,第二问提供"状态先验",第三问在状态先验的基础上做判断。评委看重的就是这层解耦:预测允许有误差,但决策模型必须对误差有鲁棒性。实操上可以在决策规则里加一条"未来持续拥堵概率超过 70% 才触发",而不是看到单点预测低于阈值就动作。这条概率约束在论文里非常好写,一张"不同触发概率下的收益对比"表就能证明你的决策模型不是规则堆砌。一句话总结:预测是"看清路",决策是"敢不敢走",两件事要分开调参,合在一起只会互相拖累。
3. 模型建立:从交通流理论到启用决策的完整链路
建模的目标是把"是否启用应急车道"这个二值决策翻译成一组可计算的量化模型。下面按三个子问题给出模型框架和参数建议。整套思路不依赖特定数据集,拿到具体数据后按断面替换字段即可,重点是理解每个参数为什么这么取。
3.1 拥堵判别模型:混合阈值 + 排队论校验
第一问的模型结构推荐三层判别:初筛层用速度阈值,确认层用占有率突变,校验层用排队论估算排队长度。前两层在 2.2 里讲过,这里重点说排队论校验。排队论在交通流建模里的落地方式是累积到达-离去曲线:从拥堵起点开始,把检测断面的累计流量减去累计通过量,差值就是排队车辆数。排队长度 = 排队车辆数 / (车道数 × 平均车头间距)。这个计算不需要仿真软件,用 pandas 的 cumsum 就能完成。
参数上,拥堵状态下的平均车头间距取 7-9 米比较常见,对应车辆密度大约 110-140 veh/km/车道。排队长度算出来后,和路段的物理储备长度比较——应急车道启用价值之一就是缩短排队回溢到上游入口的概率,所以"排队长度是否接近上游匝道"是第三问效益函数里的关键变量。这里有一个细节:排队长度是动态变化的,不要只算峰值,要输出一个排队长度的时间序列,在论文里配合拥堵事件曲线图展示,比单点值更有说服力。
值得提醒的是,排队论校验不要求精确,它的作用是排除"速度低但排队并不长"的伪拥堵。比如一个匝道出口的短时减速带,速度低但排队长度只有几十米,这种不是应急车道该处理的场景。把排队长度超过物理长度的阈值卡到"接近上游匝道"这个量级,能有效过滤小扰动。校验层的输入就是 2.2 节的事件表,输出是每个事件的排队长度序列,中间不需要额外建模。
3.2 短时预测模型:LSTM 与统计基线的取舍
第二问的预测目标通常是未来 15-30 分钟的速度或流量。我的习惯是先做一个统计基线:历史同期均值加上最近 15 分钟的实际偏差修正。这个基线一般不会太差,MAE 通常能到深度模型的 80% 水平,但短板是反应慢——当拥堵突然加剧时,基线要滞后 2-3 个周期才能跟上。所以统计基线用来做对照,不做法主力。
主力模型用 LSTM 或 GRU 就够了,研究生数模竞赛不需要上 Transformer。输入窗口取 12 个时间步(60 分钟),预测步长取 3-6 步(15-30 分钟)。特征用流量、速度、占有率、节假日 dummy 变量、时段编码(正弦+余弦组合),输出为速度序列。模型结构对应 4.3 节的代码:两层 LSTM,隐藏单元 64 和 32,dropout 0.2,学习率 0.001,batch size 32,早停 patience 5。核心超参见下表,直接按这个起步再微调。
| 参数名 | 取值 | 说明 |
|---|---|---|
| 回看窗口 | 12 步(60 分钟) | 覆盖一个完整高峰演进周期 |
| 预测步长 | 3-6 步(15-30 分钟) | 与决策时间粒度对齐 |
| 隐藏单元 | 64 / 32 | 两层递减,防止过拟合 |
| dropout | 0.2 | 训练阶段随机失活比例 |
| 学习率 | 0.001(Adam) | 配合早停使用 |
| batch size | 32 | 时序样本量小,大 batch 无必要 |
这里有两个必坑点。第一,交通时序的"回归到均值"问题:预测步长拉长后模型输出会趋向历史均值,因为 MSE 损失函数在平均化误差时奖励了保守预测。缓解办法是改预测速度的一阶差分,或者自定义损失函数,把速度变化量的误差也纳入惩罚。第二,数据泄露:时间序列必须按时间顺序切分,不能用随机切分,否则验证集某一天的数据和训练集里前一天的数据直接相邻,模型等于见过答案。预测结果务必输出置信区间——用验证集上不同分位数的误差宽度来估计,这个分布直接喂给第三问的决策模型,比点估计值有用得多。
注意:统计基线不是摆设,论文里一定要有"基线 vs LSTM"的对比表。没有对比,模型效果好坏无从谈起,评委也无法判断你的模型相对简单方法到底提升在哪。
3.3 启用决策模型:效益函数驱动的动态规划
第三问的决策模型推荐用效益-成本框架。启用应急车道的收益 = 通行能力提升带来的总行程时间节省;成本 = 安全风险 + 应急功能受限 + 切换代价。通行能力提升按"额外增加约一条车道"折算:单车道理论通行能力取 1800-2200 veh/h,开启应急车道后实际增加量按饱和度折减,常见折减系数 0.5-0.7,因为应急车道较窄、限速往往偏低、不是所有司机都敢走。
决策时机用动态规划求解:把时间轴切成 5 分钟步长,状态是"当前是否启用",状态转移的代价包含开启/关闭的切换成本——设置引导标识、调整限速需要 10-15 分钟过渡期,过渡期里整段路的通行能力反而下降。目标函数是决策窗口(通常未来 2 小时)内累计收益最大化。DP 状态只有开/关两个,转移逻辑简单,但切换成本必须加进转移矩阵,否则模型会给出每 5 分钟开关一次的荒谬策略。
效益函数的具体形式我建议这样写:时刻 t 的收益 = 排队长度缩短带来的时间节省 - 启用时间累积的安全风险惩罚 - 切换动作的一次性成本。排队长度缩短量用 3.1 的排队论差值计算,时间价值按车辆数 × 节省分钟 × 单位时间价值折算。安全风险惩罚设成每分钟扣固定比例收益,系数没有标准答案,建议在论文里做敏感性分析,给出 0.1%、0.3%、0.5% 三档结果对比,比硬填一个数更有说服力。最后输出一张"启用时间段列表",每一项附上预计净收益,评委看到的是可解释的决策过程,而不是黑匣子结果。
4. 高质量 py 求解代码:从数据清洗到结果导出的四段管线
代码按"数据预处理→拥堵判别→预测模型→决策输出"四段组织,每段独立成 .py 文件,运行时按顺序执行。分段的好处是中途换模型或调参不用重跑全流程。运行环境用 vscode 配好 python 环境,命令行运行 .py 文件用 python xxx.py 即可。下面给的是可运行的骨架代码,你把数据路径和参数改成赛题里的实际值就行。
4.1 数据预处理与特征工程:时间对齐、缺失值与断面统一
import pandas as pd import numpy as np def preprocess(raw_df: pd.DataFrame, sensor_id: int, resample_rule: str = '5min') -> pd.DataFrame: """对单断面检测数据做重采样与缺失值填补。 raw_df: 原始数据, 包含 time, flow, speed, occupancy, sensor_id 列 sensor_id: 当前断面编号 resample_rule: 重采样粒度, 默认 5 分钟 """ df = raw_df[raw_df['sensor_id'] == sensor_id].copy() df['time'] = pd.to_datetime(df['time']) df = df.set_index('time').sort_index() # 异常值剔除: 速度为负或超过 180 km/h 直接置 NaN df.loc[(df['speed'] < 0) | (df['speed'] > 180), 'speed'] = np.nan df.loc[df['flow'] < 0, 'flow'] = np.nan # 重采样: 流量求和, 速度与占有率求均值 df = df.resample(resample_rule).agg( {'flow': 'sum', 'speed': 'mean', 'occupancy': 'mean'}) # 缺失值处理: 最多连续 2 步用线性插值, 更长用同期小时中位数兜底 df['flow'] = df['flow'].interpolate(limit=2) df['speed'] = df['speed'].interpolate(limit=2) df['occupancy'] = df['occupancy'].interpolate(limit=2) fill_mask = df[['flow', 'speed', 'occupancy']].isna().any(axis=1) if fill_mask.any(): hourly_median = df.groupby(df.index.hour)[ ['flow', 'speed', 'occupancy']].transform('median') df.loc[fill_mask] = df.loc[fill_mask].fillna(hourly_median.loc[fill_mask]) return df这里两个参数值得展开。resample 粒度选 5 分钟是数模赛常规做法:太细(1 分钟)会放大检测噪声,导致拥堵识别抖动;太粗(15 分钟)会抹掉拥堵起止的突变点。interpolate 的 limit=2 表示最多填补两个连续缺失步,超过部分用同期小时中位数——既保留短缺失的连续性,又避免长缺失段被线性趋势带偏。处理完后务必输出一份每列均值、标准差、缺失率的统计摘要,写进论文附录,这个动作在评阅时很加分。
提示:预处理后的数据先落盘成 CSV。后续所有脚本都从这个 CSV 读取,别再动原始数据,这样调参时数据口径不会悄悄变化。
4.2 拥堵判别代码:三条件 AND 与事件表输出
def detect_congestion(df: pd.DataFrame, v_thresh: float = 45, occ_delta: float = 15, min_minutes: int = 15) -> pd.DataFrame: """三条件识别拥堵事件, 输出事件表。 条件1: 速度15分钟滑动平均低于 v_thresh 条件2: 占有率相对同期历史中位数抬升超过 occ_delta 个百分点 条件3: 状态持续至少 min_minutes """ speed_ma = df['speed'].rolling(3, center=True).mean() # 3个5分钟=15分钟 occ_baseline = df.groupby(df.index.hour)['occupancy'].transform('median') occ_rise = df['occupancy'] - occ_baseline cond_speed = speed_ma < v_thresh cond_occ = occ_rise > occ_delta candidate = (cond_speed & cond_occ).astype(int) events = [] start = None for ts, flag in candidate.items(): if flag == 1 and start is None: start = ts elif flag == 0 and start is not None: duration_min = (ts - start).total_seconds() / 60 if duration_min >= min_minutes: events.append({ 'start_time': start, 'end_time': ts, 'duration_min': duration_min }) start = None return pd.DataFrame(events)rolling 窗口设成 3 个采样步并取 center=True,是有意为之:拥堵起止时刻本身模糊,中心滑窗让判定边界的相位延迟减半。代价是序列首尾产生 NaN,但对事件级输出影响不大。groupby(df.index.hour) 算同期基线是关键——直接用全天均值做基线,夜间低流量时段的正常低速度会被误判为拥堵。这段跑完把事件表另存 CSV,后面两个子问题直接从 CSV 读入。
4.3 预测模型代码:两层 LSTM 的最小实现
import tensorflow as tf from tensorflow.keras import layers, models def build_lstm(input_dim: int, hidden: int = 64, steps_out: int = 3) -> tf.keras.Model: """两层 LSTM 预测未来 steps_out 个时间步的速度。 输入形状: (batch, 12, input_dim), 12 是回看窗口(60分钟) """ inp = layers.Input(shape=(12, input_dim)) x = layers.LSTM(hidden, return_sequences=True)(inp) x = layers.LSTM(hidden // 2)(x) x = layers.Dropout(0.2)(x) out = layers.Dense(steps_out)(x) model = models.Model(inp, out) model.compile(optimizer=tf.keras.optimizers.Adam(0.001), loss='mse') return model输入窗口固定 12 步(60 分钟)、预测 3 步(15 分钟),是交通短时预测的经验默认组合。hidden 取 64、第二层减半到 32,是防止过拟合——交通数据通常只有几千行,两层各 128 很容易跑过拟合。训练前把特征做 StandardScaler 标准化,预测完再反标准化。这段代码没有做差分预测,5.1 节会说明为什么要改成差分目标,建议拿到题后直接按差分方式实现。
4.4 决策输出与论文图表落地
决策部分的代码依赖题目第三问的评分口径,这里给框架逻辑:把预测模型输出的速度与占有率分布、拥堵事件表里的持续时间与排队长度、路网属性一起传入效益函数。效益函数返回每个"启用/不启用"状态的收益值,再用动态规划枚举 2 小时决策窗口内的开关组合。输出的两张表直接进论文:一张是"启用时间段列表",列出 start、end、持续时长、预计净收益;另一张是"效益-成本明细表",分列收益、安全风险、切换成本、净值。
图表部分用 matplotlib 画三条曲线——不启用时的速度曲线、启用时的推算速度曲线、实际速度曲线,三线对比是第三问最直观的结果展示。这里有个细节:实际速度曲线要从题目数据或仿真中获取,推算速度曲线是模型推算的,两条曲线之间的面积差就是应急车道启用的收益可视化。这个图放在论文结果页的第一张,评委一眼就能看懂你的模型产生了什么价值。
5. 避坑专题:建模和代码里最容易翻车的五个细节
这一章全是我实际跑这类题踩过的坑,按现象→原因→解决写。时间紧的话至少把前三条看完,它们直接决定结果能不能自圆其说。
5.1 现象:预测曲线在高峰期整体偏低,低谷期整体偏高
原因:LSTM 用 MSE 做损失函数,本质是在逼近条件均值,而交通状态在高峰期的方差很大。模型为了降低整体误差会主动回避极端值,输出向均值收缩,这是统计学习里的"回归到均值"现象,在交通预测里表现得特别明显。
解决:不预测速度绝对值,改预测速度的一阶差分;训练时用自定义损失,MSE 和差分 MSE 按 0.7:0.3 加权。差分预测反推回绝对值后,峰值位置对得上,幅值略偏,但比直接预测好很多。代码上的改动很小:y 列变成 df['speed'].diff().fillna(0),预测输出做 cumsum 加回基准速度即可。
5.2 现象:拥堵事件起止时间滞后于肉眼判断 10-20 分钟
原因:速度滑动平均是滞后指标,再加上固定阈值 45 km/h,拥堵刚形成时速度还没降到阈值以下。这个滞后对后续决策是致命的——触发时机晚 10 分钟,启用决策就晚了两个时间步。
解决:把占有率突变作为"预警通道"。占有率序列对车辆堆积的响应比速度快 1-2 个采样周期。用双通道 OR 触发,再做持续时间 AND 确认:条件变成 (cond_speed | cond_occ) 作为候选,然后在候选段内部检查 cond_speed 是否在前 3 个时间步内成立。这个组合既敏感又不会频繁误报,代码上比 4.2 节多两行。
5.3 现象:启用策略在验证集上收益很小甚至为负
原因:十有八九是切换成本设得太低或没设,模型做出了频繁开关的贪心决策。应急车道不是免费午餐,每次开启要摆放引导标识、调整限速,过渡期里整段路的通行能力反而下降。没有切换成本时,动态规划会追逐每一个小的收益波动,输出"开 5 分钟关 5 分钟"的不合理策略。
解决:给开启和关闭动作分别设 10-15 分钟的过渡期,过渡期收益按负值计入。收益函数里加一项"启用时长惩罚",单位时间扣一定比例收益,策略才会收敛到"持续启用一个合理时段"的形态。切换成本的具体数值没有标准答案,论文里做敏感性分析即可,建议至少给 10 / 15 / 20 分钟三档对比。
5.4 现象:代码本地运行正常,换一台机器结果完全不一样
原因:路径写死、随机数种子没固定、中间结果没有落盘。数模竞赛交的是"结果可复现",不是"算法很随机"。
解决:数据路径写进配置文件;LSTM 训练前固定 tf.random.set_seed(2024) 和 np.random.seed(2024);预处理输出的事件表、标准化参数都落盘成 CSV 或 npz,后续阶段直接读文件而不是重新计算。交卷时提交一个 run_all.py,用 argparse 接收数据根目录和配置文件路径——这正是 python 给另一个 py 脚本传递参数的常规做法,比在代码里硬编码路径可靠得多。换一台机器从头跑,只要数据和种子一致,结果就是可复现的。
5.5 现象:预测模型在验证集上误差很低,但一上真实场景就崩
原因:时间序列数据泄露。训练集和验证集如果是随机切分,验证集某几天的数据可能在时间上直接紧挨训练集,模型相当于见过答案。
解决:按时间顺序切分,前 70% 时间段做训练,后 30% 做验证。更严格的做法是滚动验证:每天用前 N-1 天训练、预测第 N 天。另外,所有特征工程必须只用当前步及之前的信息,禁止用到未来的统计量——比如"用全天均值做归一化"就是典型的泄露,应该用滚动窗口的均值,或者直接用原始值配 StandardScaler 并在训练集上拟合。
6. 让求解代码跑得稳、交得出手:参数传递、打包与验证技巧
到这一步,模型和代码都齐了,最后的工作是把代码变成"评委能复现、自己能改参"的交付物。三个实用技巧值得参考。
第一,用配置文件统一管参数。把速度阈值、占有率阈值、LSTM 隐藏单元数、预测步长、排队论车头间距全部写进一个 config.py,主程序只从里面读。调参时不动逻辑代码,论文里的参数设置表直接拿配置文件截图。第二,入口脚本支持命令行传参,用 argparse 接收数据目录和配置文件路径,方便在一个批处理脚本里批量跑多个场景,这是 python 脚本间传参的常规姿势。如果要在没有 python 环境的机器上演示,可以把核心脚本用 py 打包成 exe,但数模竞赛不建议这么做——评委要审代码,直接交 .py 源码加 requirements.txt 是最稳妥的。第三,长训练任务要处理好后台运行和日志。很多人问"py 脚本运行电脑息屏可以吗",可以,但前提是日志和断点保存做好:每个 epoch 写一次日志,训练结束自动保存模型权重和预测结果,这样跑通宵也不用守着屏幕。
验证方面我保留一个固定习惯:每次改完模型或参数,在同一套验证集上跑完整流程,记录四项指标——预测 MAE、RMSE、拥堵事件检测的 F1-score、决策总收益,追加写进一个结果日志文件。这样赛前反复改模型时,不会出现"改完不知道自己变好还是变差"的局面。还有一个小建议:每次跑完把关键图表和指标截进论文草稿对应的位置,最后两天只做整合不重新跑实验,能省下大量时间。数模竞赛的代码不需要达到工程级规范,但做到可复现、参数集中、日志完整,已经是前 10% 的交付水平了。希望帮到你。
本文还有配套的精品资源,点击获取