☰
数维杯A题高效夺分指南:数据清洗到模型选型的完整实战
2026/10/28 8:30:38 网站建设 项目流程

简介:面向2026年第十一届数维杯大学生数学建模竞赛A题的全套保奖冲刺包,专为参赛团队、编程新手及冲击特等奖的精英队伍设计。内容覆盖从赛题思路拆解、Python/MATLAB双版本代码实现,到特等奖标准成品论文与全量结果表格,可一站式解决建模、编程、写作三大痛点。压缩包共442个文件,以198个PDF论文与参考文档、102个PNG结果图表、39个DOCX说明文档及20个XLSX数据表格为核心,另有源码、视频及模板等附件,整体约791MB,目录清晰便于按模块调用。已有174人学习下载。除完整可复现的代码与排版规范论文外,还提供数据预处理、模型训练、启发式寻优的可视化输出,以及逐行中文注释,方便快速二次开发。所有中间数据与对比分析均可直接用于论文,配合持续更新的网盘资料,实用性突出。

1. 数维杯A题夺分逻辑:拿到题目那天下午,先想清楚这三件事

参加数维杯数学建模竞赛的人,绝大多数不是冲着“能不能解出来”去的,而是冲着“能不能在72小时里交出一份像样的论文”去的。A题作为每年数维杯里区分度最高的赛题,拼的从来不是谁的算法更前沿,而是谁能在有限时间里把“问题拆解—数据处理—模型建立—结果检验—论文成型”这条流水线跑通。作为连续带过三届队伍的参赛者,我可以说,最后得高分的队伍往往不是模型最花哨的队伍,而是“每一步都不掉链子”的队伍。这篇文章直接把你从拿到题目开始要做什么、按什么顺序做、哪些参数值得调、哪些坑必须避开,按实战时间线拆开讲,适合第一次参加的队伍,也适合想在A题上冲奖的熟手队伍对照检查。

2. 拆题与数据探查:从题目文本到第一张图的完整流程

2.1 把A题翻译成可解的问题:评价类、预测类还是机理类

数维杯A题在过去几届里,偏好集中在“评价类”和“机理分析类”这两个方向上,偶尔会出现需要做预测的子问题。拿到题目后的第一个小时不建议碰代码,先把题目里出现的动词圈出来——“评价”“评估”“分析影响因素”“预测”“优化”“决策”,不同动词对应完全不同的建模路线。

  • “评价”“评估”“排序”对应评价类模型:熵权法、TOPSIS、灰色关联度、层次分析法、CRITIC、VIKOR。重点在指标体系的构建和权重计算的可解释性。
  • “预测”“演化趋势”对应预测类模型:灰色预测、ARIMA、XGBoost、LSTM、Prophet。重点在数据量是否支持所选模型,以及预测误差的可视化。
  • “机理”“动力学过程”对应机理类模型:微分方程、元胞自动机、多智能体仿真。重点在参数反演和灵敏度分析。

我一般会在题目页空白处直接把每个小问标注成“评价/预测/机理”三个类别,然后估算每个小问的分数占比,按分数占比分配队伍里三个人接下来两天的精力。A题的第一小问往往不难,但它决定了后续问题的数据基础,所以第一小问通常建议在当天晚上之前完成。

2.2 数据清洗的四个必查项:完整代码与判断标准

数维杯A题的附件数据,结构上已经有比较明显的清洗套路了。第一步建议把附件里的表头、单位、缺失值分布、异常值范围一次性扫清楚。下面是数据清洗流程的最小代码模板,我每次比赛都会先跑一遍。

import pandas as pd import numpy as np # 读取附件,先别指定index_col,第一遍要看原始结构 df = pd.read_excel("附件1.xlsx", sheet_name=0) # 1. 表头检查:查看所有列名和数据类型 print("列信息:") print(df.dtypes) # 2. 缺失值检查:查看每列缺失率 missing_ratio = df.isnull().mean().sort_values(ascending=False) print("缺失率最高的前10列:") print(missing_ratio.head(10)) # 3. 重复行检查:删除完全重复的行 before_len = len(df) df = df.drop_duplicates().reset_index(drop=True) print(f"删除重复行:{before_len} -> {len(df)}") # 4. 异常值检查:用分位数法找单变量异常点 for col in df.select_dtypes(include=[np.number]).columns: q1 = df[col].quantile(0.25) q3 = df[col].quantile(0.75) iqr = q3 - q1 lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr out_count = ((df[col] < lower) | (df[col] > upper)).sum() if out_count > 0: print(f"{col}: 异常值 {out_count} 个,范围 [{lower:.2f}, {upper:.2f}]")

逻辑说明:上面四步是“先看结构、再看缺失、再查重复、最后找异常”的顺序。很多队伍拿到数据直接就开始跑模型,结果模型结果不好又回头查数据,浪费时间。缺失率超过30%的列,如果不是题目明确要求保留,我一般直接删掉;缺失率在5%到30%之间的列,用中位数填充比分位数填充更稳妥,因为中位数对异常值不敏感。异常值不建议直接删除,先看题目里有没有对边界情况的讨论,比如“极大值”“极小值”是不是题目专门设计出来的。

参数说明:分位数的倍数是1.5IQR,这个系数是统计学里的常规默认值,如果数据量小或者题目数据分布明显偏态,可以把系数改到3.0,避免把本身合理的极值误删。填充策略上,数值列用fillna(df[col].median()),类别列用fillna(df[col].mode()[0]),时间列一般用向前填充。

2.3 用可视化把数据“读”出来:先画图再建模

数据清洗完别急着建模,先画图。可视化在这一阶段的功能不是给论文攒图片,而是帮你判断“数据长什么样、变量之间是什么关系、有没有明显的分组或趋势”。常见做法是画三张图:每个指标的分布直方图、指标间的相关系数热力图、如果有时间维度就画时间序列折线图。

import matplotlib.pyplot as plt import seaborn as sns # 画分布图:重点看数据是否服从正态分布或对数正态 df_numeric = df.select_dtypes(include=[np.number]) num_cols = df_numeric.columns[:6] # 前6个数值列 fig, axes = plt.subplots(2, 3, figsize=(15, 10)) for i, col in enumerate(num_cols): ax = axes[i // 3][i % 3] df[col].hist(bins=30, ax=ax, edgecolor='black', alpha=0.7) ax.set_title(col) plt.tight_layout() plt.savefig("分布图.png", dpi=300, bbox_inches="tight") plt.show() # 相关系数热力图:找共线性强的指标,后续建模要处理 corr_matrix = df_numeric.corr() plt.figure(figsize=(12, 10)) sns.heatmap(corr_matrix, annot=True, fmt=".2f", cmap="coolwarm", cbar=True) plt.title("指标相关系数热力图") plt.tight_layout() plt.savefig("相关系数热力图.png", dpi=300, bbox_inches="tight") plt.show()

逻辑说明:bins=30是经验值,数据量在几百条时30个柱足够看形态,数据量上千可以调到50。相关系数超过0.8的两个指标,在后续做回归或权重计算时要考虑去重或降维,否则会导致评价模型里的权重失真。

参数说明:annot=True会在热力图上显示数值,fmt=".2f"保留两位小数,cmap="coolwarm"适合显示正负相关。图的分辨率全部设到300dpi,后面写论文直接就能插入,不用再重新生成。图片保存文件名用英文,避免部分LaTeX模板对中文文件名不兼容。

3. 模型选型与参数调整:评价类A题和预测类A题分别怎么走

3.1 评价类A题的经典组合:熵权法 + TOPSIS,为什么要这么配

A题的评价类子问题,最稳妥的组合是“熵权法算权重 + TOPSIS算排序”。理由很直接:熵权法完全由数据驱动,不需要人为给指标赋权,评委问到权重来源时队伍有得答;TOPSIS的排序结果对数据分布没有苛刻要求,而且“贴近度”这个数值在论文里非常直观,能画柱状图、雷达图做展示。

熵权法的核心计算是:对每个指标做归一化之后,计算信息熵,信息熵越小表示这个指标的变异程度越大,权重越高。需要注意的关键一步是归一化公式的选择——正向指标用(x - min) / (max - min),负向指标用(max - x) / (max - min),这一步错了后面的权重和排名全部报废。

TOPSIS部分则是把每个评价对象的各指标值与“正理想解”“负理想解”比较,计算欧氏距离,最后得到贴近度C值。C值越接近1,评价越优。

import numpy as np def entropy_weight(data): # 数据已归一化,行是样本,列是指标 n, m = data.shape # 计算每个样本占该指标总和的比例 p = data / data.sum(axis=0, keepdims=True) # 避免log(0),给一个极小值 p = np.clip(p, 1e-12, 1) # 信息熵 e = -np.sum(p * np.log(p), axis=0) / np.log(n) # 差异系数 d = 1 - e # 权重 w = d / d.sum() return w def topsis(data, weights): # 数据已归一化且为正向指标 norm_data = data / np.sqrt((data ** 2).sum(axis=0)) weighted_data = norm_data * weights best = weighted_data.max(axis=0) worst = weighted_data.min(axis=0) s_best = np.sqrt(((weighted_data - best) ** 2).sum(axis=1)) s_worst = np.sqrt(((weighted_data - worst) ** 2).sum(axis=1)) c = s_worst / (s_best + s_worst) return c

逻辑说明:p = data / data.sum(axis=0, keepdims=True)是按列归一化每个样本的占比。np.clip(p, 1e-12, 1)防止某些指标出现0占比导致log(0)报错。TOPSIS里的np.sqrt((data ** 2).sum(axis=0))是向量归一化,和熵权法的极差归一化是两种不同的归一化,不能混用。

参数说明:eps=1e-12是一个经验值,如果数据样本量极大,可以调到1e-10,影响很小。TOPSIS的权重要和熵权法的输出维度严格一致,如果指标体系有14个指标,weights就应该是长度为14的一维数组,调试时先打印weights.shape确认。

3.2 预测类A题怎么选:XGBoost还是LSTM,边界在哪里

预测类题在A题里通常以“未来某段时间的指标变化”出现。这块是大坑高发区,不少队伍拿过来就用LSTM,结果训练几小时、预测效果还不如简单的线性外推,原因多半是数据量太小。

我的原则是:样本量少于500条时优先考虑XGBoost或随机森林,因为树模型对小样本更友好,参数调节快,而且特征重要度可以直接写进论文。样本量超过几千条、且数据有明显的周期性和序列依赖时,才考虑LSTM。如果你的数据是逐年或逐月一条,三年也就36条,这种量级跑LSTM基本是自找麻烦。

XGBoost做预测时,一个重要细节是构建滞后特征。把历史值变成t-1, t-2, t-3的滞后列,让模型看到“过去”才能预测“未来”。

import pandas as pd from xgboost import XGBRegressor from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.metrics import mean_squared_error def build_lag_features(data, target_col, lags=[1, 2, 3]): df_lag = data.copy() for lag in lags: df_lag[f"{target_col}_lag{lag}"] = df_lag[target_col].shift(lag) df_lag = df_lag.dropna().reset_index(drop=True) return df_lag df_lag = build_lag_features(df, "value", lags=[1, 2, 3]) feature_cols = [c for c in df_lag.columns if c != "value"] X = df_lag[feature_cols] y = df_lag["value"] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) model = XGBRegressor( n_estimators=200, max_depth=3, learning_rate=0.05, subsample=0.8, colsample_bytree=0.8, random_state=42 ) model.fit(X_train, y_train) pred = model.predict(X_test) rmse = mean_squared_error(y_test, pred, squared=False) print(f"RMSE: {rmse:.4f}")

逻辑说明:build_lag_features里的shift(lag)是把目标列的后一个值变成前一个值,构造滞后特征后必须dropna(),否则前几行会出现NaN,训练时会报错或自动忽略。train_test_split(..., shuffle=False)对时间序列是必须的,不允许打乱顺序,否则会用到未来数据训练,指标虚高但实际预测一塌糊涂。

参数说明:max_depth=3是防过拟合的保守值,小样本建议保持3到4。learning_rate=0.05配合n_estimators=200是一组常用配置,如果发现训练集精度不够,先把n_estimators加一倍,而不是把学习率调大,学习率调大容易让模型在验证集上翻车。subsample=0.8和colsample_bytree=0.8分别是行采样和列采样的比例,一般不低于0.7,不然模型欠拟合。

3.3 参数怎么调:网格搜索与交叉验证代码模板

调参环节最容易陷入“调一整晚没结果”的窘境。XGBoost的参数空间巨大,我建议只对三个最敏感的参数做网格搜索:n_estimators、max_depth、learning_rate。其他的保持默认,先把这几个定下来,再往后调整正则化参数。

from sklearn.model_selection import GridSearchCV param_grid = { "n_estimators": [100, 200, 300], "max_depth": [3, 4, 5], "learning_rate": [0.01, 0.05, 0.1] } grid_model = XGBRegressor(random_state=42) grid_search = GridSearchCV( estimator=grid_model, param_grid=param_grid, cv=3, scoring="neg_mean_squared_error", n_jobs=-1 ) grid_search.fit(X_train, y_train) print("最优参数:", grid_search.best_params_) print("最优得分:", grid_search.best_score_) best_model = grid_search.best_estimator_ final_pred = best_model.predict(X_test)

逻辑说明:scoring="neg_mean_squared_error"因为GridSearchCV内部是找最大值,所以用负的MSE,数值越接近0说明误差越小。cv=3对于几百条数据来说够用,数据量大可以提高到5。搜索的意义不在于找到“全局最优”,而是确认参数组合是否稳定——如果最优参数落在网格边界上,说明你的网格范围设窄了,把边界值扩展后再跑一轮。

参数说明:n_jobs=-1启用所有CPU核心。比赛用的是笔记本电脑,跑网格搜索时CPU占用会很高,建议跑之前先保存一次数据清洗的中间结果,避免内存不够导致IDE卡死。三组参数共27种组合,几万条数据大概只需要几分钟,如果超过半小时,先检查是不是后台有别的程序占内存。

4. A题避坑指南:比赛中最容易翻车的五个环节

4.1 附件里的“单位不统一”让所有结果量级错乱

现象:模型跑出来的权重分布、预测结果和题目给的参考范围完全对不上,甚至出现几百倍的量级差。

原因:附件数据里,有的列是“万吨”,有的是“吨”,有的百分比做了小数处理有的没有,直接read_excel进来全当数值处理,归一化时量纲完全被扭曲。

解决:清洗阶段就要做人肉单位审计——打印每一列的最大值和最小值,把数值范围差异超过3个数量级的列挨个检查,在代码里写一个单位换算字典,一次性完成标准化。例如全部转成统一单位后再进模型。

4.2 把“第一问的模型”硬套在“第二问的问题”上

现象:第一问是评价类,第二问是预测类,第二问结果方差极大,评委读不懂你第二问在算什么。

原因:很多队伍图省事,一个模型从头用到尾,第一问的指标体系里根本没有时间序列信息,却拿去做第二问的趋势预测,数据基础不成立。

解决:在拆题阶段就按“每个小问用什么模型”画出模型地图。不同小问可以用同一份数据,但模型选择必须重新做。第二问如果是预测,必须重新构造特征、重新划分训练集测试集,不能直接复用第一问的完整数据集。

4.3 代码跑出来没有中间结果,论文查不到数字

现象:论文写到最后发现某个表格里的数字不知道是哪个脚本跑出来的,想重跑一遍还要重新清洗数据。

原因:队伍协作时各跑各的,没有约定统一的输出路径。常见做法是每个模型脚本最后都to_csv输出中间结果。

解决:从第一天开始就约定一个result/文件夹,所有脚本运行结束都把关键指标输出到CSV里,文件名带题目小问编号。pred.to_csv("result/q2_pred.csv", index=False)这类写法成本极低,但关键时刻能救命。

4.4 LSTM模型深陷循环超参数地狱

现象:LSTM跑了两个小时后,训练损失持续下降但验证损失完全不动,内心开始怀疑人生。

原因:小样本数据本身就喂不饱LSTM,再加上学习率、隐层维度、dropout、序列长度四个参数互相耦合,调参时间根本不够。

解决:比赛期间遇到LSTM不收敛,立即降级到XGBoost或随机森林,不要恋战。如果题目明确时间序列且数据量足够,再LSTM,否则树模型几乎总能在更短时间里给出可解释且稳定的结果。

4.5 灵敏度分析只是“重跑一遍”,没有对参数扰动逻辑

现象:评委一眼看出你的灵敏度分析就是换个参数值把模型重跑了一遍,没展示结果随参数变化是否合理。

原因:灵敏度分析要有逻辑闭环——选定哪个参数、调整幅度多大、为什么调整这个范围、结果如何验证。随便跑两遍完全站不住。

解决:对评价类模型,对权重向量做±10%和±20%扰动,看排名是否发生显著变化;对预测类模型,对滞后阶数或训练集长度做扰动,看误差的变化幅度。输出一张参数变化-结果变化的对照表,这就够了。

5. 完整代码实现:从数据清洗到结果导出的可复现模板

5.1 一个完整的评价模型流水线代码模板

把前面拆开讲的清洗、熵权法、TOPSIS拼成一个完整的脚本,这就是A题评价类小问的最小可复现基座。比赛时可以把附件换成自己的数据,按这个顺序跑通再改参数。

import pandas as pd import numpy as np # ---------- 第1步:数据读取与预处理 ---------- df = pd.read_excel("附件1.xlsx") df = df.drop_duplicates().reset_index(drop=True) # 对数值列做中位数填充 num_cols = df.select_dtypes(include=[np.number]).columns for col in num_cols: df[col] = df[col].fillna(df[col].median()) # ---------- 第2步:指标极差归一化 ---------- # 需要手动指定正向指标和负向指标 positive_cols = ["指标1", "指标2", "指标3"] negative_cols = ["指标4", "指标5"] data_norm = pd.DataFrame() for col in positive_cols: data_norm[col] = (df[col] - df[col].min()) / (df[col].max() - df[col].min()) for col in negative_cols: data_norm[col] = (df[col].max() - df[col]) / (df[col].max() - df[col].min()) # ---------- 第3步:熵权法计算权重 ---------- def entropy_weight(data): p = data / data.sum(axis=0, keepdims=True) p = np.clip(p, 1e-12, 1) e = -np.sum(p * np.log(p), axis=0) / np.log(len(data)) d = 1 - e weights = d / d.sum() return weights weights = entropy_weight(data_norm) # ---------- 第4步:TOPSIS排序 ---------- def topsis(data, weights): norm_data = data / np.sqrt((data ** 2).sum(axis=0)) weighted = norm_data * weights best = weighted.max(axis=0) worst = weighted.min(axis=0) s_best = np.sqrt(((weighted - best) ** 2).sum(axis=1)) s_worst = np.sqrt(((weighted - worst) ** 2).sum(axis=1)) c = s_worst / (s_best + s_worst) return c df["综合得分"] = topsis(data_norm, weights) df["排名"] = df["综合得分"].rank(ascending=False, method="min") df[["样本编号", "综合得分", "排名"]].to_csv("result/q1_result.csv", index=False) print(df[["样本编号", "综合得分", "排名"]].sort_values("排名"))

逻辑说明:正向指标归一化和负向指标归一化两个循环分开写,目的是让你在跑之前就明确哪些指标“越大越好”、哪些“越小越好”。很多队伍在这一步把所有指标都当成正向的,结果排名结果和题目常识完全冲突。

参数说明:rank(ascending=False, method="min")是降序排名,得分最高排名第一。method="min"表示并列时取最小排名,比赛中常见用法;如果想要更细的区分可以改成method="dense",但论文里一般默认说明“并列取最小”。

5.2 一个预测类模型流水线代码模板:从滞后特征到输出预测值

import pandas as pd import numpy as np from xgboost import XGBRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # ---------- 第1步:读取时序数据 ---------- df_ts = pd.read_excel("附件2.xlsx", parse_dates=["日期"]) df_ts = df_ts.sort_values("日期").reset_index(drop=True) # ---------- 第2步:构造滞后特征 ---------- for lag in [1, 2, 3]: df_ts[f"value_lag{lag}"] = df_ts["value"].shift(lag) df_ts = df_ts.dropna().reset_index(drop=True) # ---------- 第3步:划分训练与测试 ---------- feature_cols = [c for c in df_ts.columns if c.startswith("value_lag")] X = df_ts[feature_cols] y = df_ts["value"] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # ---------- 第4步:训练与预测 ---------- model = XGBRegressor( n_estimators=300, max_depth=3, learning_rate=0.03, subsample=0.8, colsample_bytree=0.8, random_state=42 ) model.fit(X_train, y_train) pred = model.predict(X_test) # ---------- 第5步:输出指标和预测值 ---------- rmse = mean_squared_error(y_test, pred, squared=False) r2 = r2_score(y_test, pred) print(f"RMSE: {rmse:.4f}, R2: {r2:.4f}") # 特征重要性输出,写论文用 importance = pd.DataFrame({"feature": feature_cols, "importance": model.feature_importances_}) importance = importance.sort_values("importance", ascending=False) print(importance) pred_df = pd.DataFrame({"日期": df_ts["日期"].iloc[X.index], "实际值": y, "预测值": pred}) pred_df.to_csv("result/q2_pred.csv", index=False)

逻辑说明:滞后阶数[1, 2, 3]是常用的起点配置,如果数据有明显周期性,比如每年按季度统计,可以加lag4和lag8。特征重要性feature_importances_是XGBoost自带属性,论文里用来支撑“哪些历史时点影响最大”的判断,这是评委喜欢看到的加分细节。

参数说明:n_estimators=300配合learning_rate=0.03是一组偏保守的组合,训练时间稍长但不容易过拟合。如果你发现R2为负数,说明模型比直接用均值预测还差,优先检查是否有趋势项没处理,比如先做一阶差分再喂给模型。

5.3 结果可视化与图表导出的规范模板

模型跑完之后,论文需要的图表在这个模块统一导出,保证全队用的图风格一致。

import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] # Windows用黑体 plt.rcParams["axes.unicode_minus"] = False # 正常显示负号 # 评价结果排序条形图 df_sorted = df.sort_values("综合得分", ascending=True) plt.figure(figsize=(10, 8)) plt.barh(df_sorted["样本编号"], df_sorted["综合得分"], color="#4C72B0") plt.xlabel("综合得分") plt.ylabel("样本编号") plt.title("评价对象综合得分排序") plt.tight_layout() plt.savefig("result/fig_q1_rank.png", dpi=300, bbox_inches="tight") plt.show() # 预测值与实际值对比图 plt.figure(figsize=(12, 6)) plt.plot(pred_df["日期"], pred_df["实际值"], label="实际值", marker="o") plt.plot(pred_df["日期"], pred_df["预测值"], label="预测值", marker="x") plt.xlabel("日期") plt.ylabel("指标值") plt.legend() plt.title("预测结果与实际值对比") plt.tight_layout() plt.savefig("result/fig_q2_compare.png", dpi=300, bbox_inches="tight") plt.show()

逻辑说明:plt.rcParams["font.sans-serif"] = ["SimHei"]是解决中文乱码的核心设置,不设置的话,图表里的中文标题会出现方框。比赛用Mac的话,把SimHei改成Arial Unicode MS。

参数说明:dpi=300保证打印清晰,bbox_inches="tight"自动裁剪空白边。条形图颜色选#4C72B0是seaborn的默认蓝,印刷效果干净。所有图表统一放在result/目录,文件命名带小问编号,避免最后论文排版时到处找图。

6. 论文落地的最后三小时:图表、摘要和模型检验的取舍

论文是整个比赛的最终交付物,代码和模型只是支撑材料。最后三小时的优先级应该是:摘要 > 图表 > 灵敏度分析 > 模型改进。很多队伍把最后时间耗在优化模型上,结果摘要没写完,这是最亏的。

摘要的写法有硬规矩:第一段写背景、研究对象、你做了什么、用了什么方法、得到什么结论。注意是“先总后分”,第一段全文最浓缩的部分——篇幅占整个摘要的30%左右。第二段开始按小问顺序逐段写,每一段都要有“数据 + 方法 + 关键结果”。数字要具体,比如“通过熵权法计算14项指标权重,排名第1的样本综合得分为0.873,与排名第2的样本差距为4.6%”,比“排名靠前”这种模糊描述有力得多。摘要里不加公式、不写模型代码原理,这些都留给正文。

图表是评委快速评定你工作量和专业度的地方。一张图要包含坐标轴标签、单位、必要的图例和合适的标题,图片分辨率必须达到300dpi。正文里引图时注意别写“如上图所示”这种废话,直接写“图1展示了…”。表格统一用三线表,不画竖线,不搞花哨配色。模型的检验环节,除了R2和RMSE,评价类模型补一个“权重扰动灵敏度分析”表格,预测类模型补一个“不同训练集长度下的预测误差”表格,这两张表可以放在模型的最后一个小节里,内容和代码在上一章已经可以复用。

最后一个晚上的习惯,我会重新从头到尾读一遍论文的摘要和结论,模拟评委拿着这个摘要能不能看懂“这题怎么解、结果是什么”。如果摘要里读不出完整逻辑链,哪怕图表再精致都白搭。每一次数维杯我带队伍的经验最后都指向同一件事——建模赛不是一个证明“算法最强”的赛,是一场证明“你最可靠”的赛。把这条准则刻进团队流程里,三天时间交出一份完整、可复现、图表规范的论文并不难。希望这篇拆解能帮你把时间省在真正值得的地方,比赛顺利。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询