☰
数学建模2021年C题:数据清洗与统计建模完整流程解析
2026/10/25 2:49:38 网站建设 项目流程

简介:这份资料面向备战全国大学生数学建模竞赛的参赛者与指导教师,聚焦2021年C题,提供从解题思路、模型构建到算法实现的完整参考,适合需要复盘赛题、学习建模流程与MATLAB编程的学习者。压缩包共27个文件,约996KB,以13个.m脚本、10个.mat数据文件和4个.xlsx表格为主:脚本对应各小问的求解实现,数据文件保存中间计算结果便于复现,表格则涵盖供应商与转运商原始数据及订购、转运方案结果。目前已有2310人学习。资料完整呈现了理解问题、建立模型、求解验证到结果分析的全过程,读者可对照代码理解数学理论如何转化为实际计算,并借助结果表格与数据文件复现实验、检查模型合理性,对提升建模与编程能力有较高参考价值。

1. 从一道“看起来会做、一算就翻车”的题说起

数学建模2021年C题,是近几年国赛里区分度极高的一道统计建模题。它不考你背了多少算法,而是考你能不能把一份带缺失、带异常、带量纲差异的原始数据,一步步清洗成能进模型的样子,再把结论讲成一个有业务含义的故事。很多人拿到题的第一反应是“套个回归就完事”,结果在数据预处理和结果解释上大面积失分。这场考试真正拉开差距的地方,是数据清洗的规范性、模型选择的合理性、以及论文里每一步“为什么这么做”的交代。这份资料把全部代码和中间过程都留了下来,适合正在备战国赛、想照着完整流程走一遍的考生,也适合已经会写代码但不知道怎么把过程写进论文的人。下面按考点分布、高频题型、答题思路一路拆开讲。

2. 考点分布:这道题到底在考哪几块能力

2.1 数据预处理:缺失值、异常值、量纲三件套

2021年C题给的是企业实际生产与检测数据,第一关就是数据质量。阅卷时最常看到的失分不是模型错,而是预处理一笔带过。缺失值怎么处理,直接决定后面模型能不能跑通。常见做法有三类:删除、均值或中位数填充、按分组或前后值插补。这道题的数据带有明显的分组结构,直接全局均值填充会把组间差异抹平,属于典型踩坑。更稳的做法是先按类别分组,再在组内做中位数填充,并在论文里写清“为什么选组内中位数而不是全局均值”。

异常值处理同样是考点。题目数据里存在明显偏离的检测值,直接删掉会损失样本,全部保留又会拉偏回归系数。比较稳妥的路线是用箱线图或3σ原则先标记,再结合业务判断是记录错误还是真实极端值,记录错误才修正或剔除。量纲差异则体现在不同指标数值范围差好几个数量级,进模型前必须标准化或归一化,否则距离类方法和正则化都会失真。

提示:预处理每一步都要在论文里留下“判断依据”,只写“进行了缺失值处理”几乎拿不到过程分。

2.2 模型建立:回归、分类与评价指标的选择逻辑

这道题的核心建模任务围绕指标之间的关系展开,回归是主线。但面试官和阅卷人最想听的不是“我用了线性回归”,而是“我为什么先用线性回归做基线,再考虑是否需要非线性或正则化”。基线模型的价值在于给出可解释的系数方向,如果系数符号和业务常识相反,说明预处理或变量选择出了问题,这时候上复杂模型只会把错误藏得更深。

分类任务出现在需要对样本打标签或分组的环节。评价指标不能只看准确率,样本不均衡时准确率会骗人,要看召回率、精确率和混淆矩阵。这道题里如果正负样本比例悬殊,只报准确率是典型失分点。模型对比时,训练集和测试集的划分方式也要交代清楚,随机划分还是按时间划分,结论的可信度完全不同。

2.3 真题演练:预处理与建模的完整答题链

下面这段代码演示的是这道题里最常被考到的“分组中位数填充 + 标准化 + 基线回归”链条,语言用 python,逻辑按真实答题顺序组织。

import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # 读取原始数据,假设已按题目给定字段命名 df = pd.read_csv("problem_c_data.csv") # 第一步:按分组列做组内中位数填充,保留组间差异 group_col = "category" value_cols = ["x1", "x2", "x3"] df[value_cols] = df.groupby(group_col)[value_cols].transform( lambda s: s.fillna(s.median()) ) # 第二步:用3σ原则标记异常值,仅对明显记录错误做截断 for col in value_cols: mu, sigma = df[col].mean(), df[col].std() lower, upper = mu - 3 * sigma, mu + 3 * sigma df[col] = df[col].clip(lower, upper) # 第三步:标准化,消除量纲差异 scaler = StandardScaler() X = scaler.fit_transform(df[value_cols]) y = df["target"].values # 第四步:划分训练测试集并跑基线回归 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) model = LinearRegression().fit(X_train, y_train) pred = model.predict(X_test) print("RMSE:", mean_squared_error(y_test, pred, squared=False)) print("R2:", r2_score(y_test, pred))

这段代码的关键不在语法,而在每一步的顺序和理由。groupby(...).transform保证填充值只在组内计算,不会跨组污染;clip只做截断而不删除样本,避免样本量骤减;StandardScaler放在划分之前对全量做拟合在严格意义上存在信息泄露风险,更规范的做法是先在训练集上fit,再对测试集transform。面试里如果被追问“你的标准化有没有数据泄露”,能答出这一点就是加分项。评价指标同时报 RMSE 和 R2,是因为 RMSE 有量纲、R2 无量纲,两个一起看才能判断模型是“绝对误差小”还是“解释力够”。

2.4 真题演练:模型对比题怎么答出层次

题目常要求“比较至少两种模型并说明选择理由”。这类题的答题模板是:先给基线,再给改进,最后用同一套指标对比。比如线性回归做基线,随机森林做非线性对照,两者用相同的训练测试划分和相同的评价指标。答题时要写清“随机森林提升了多少、代价是什么”,代价通常是可解释性下降和调参成本上升。面试官最想听的是你知不知道每个模型的适用边界,而不是你把所有模型都跑一遍然后挑分数最高的那个。

3. 高频考点:统计建模里反复出现的五个得分点

3.1 变量选择与多重共线性

这道题的自变量之间往往存在相关性,直接全塞进回归会导致系数不稳定、符号反常。高频考法是让你判断“要不要做变量筛选”。稳妥路线是先看相关系数矩阵,相关性过高的变量保留业务含义更清晰的那个,或者用方差膨胀因子做诊断。答题时要说明“剔除不是因为算法说不行,而是因为两个变量在业务上重复表达同一信息”。只写“用了逐步回归”而不解释保留和剔除的理由,过程分照样丢。

3.2 模型评价与交叉验证

单次划分的训练测试结果波动大,交叉验证是更稳的评价方式。这道题的数据量不算大,五折交叉验证比单次划分更能反映模型稳定性。答题时要说清折数选择、每折的划分方式,以及最终报告的是均值还是某一次结果。常见错误是交叉验证和最终模型训练用了不同的预处理流程,导致评价结果偏乐观。

3.3 结果解释与业务落地

建模不是算出数字就结束,题目通常要求给出结论和建议。这一步考的是把系数、重要度翻译成业务语言的能力。比如某个变量系数为正,要说明“该指标上升时目标值倾向于上升”,再结合题目背景给出可操作建议。只贴一张特征重要度图而不解释,是典型的“有结果没结论”。

3.4 真题演练:共线性诊断的答题写法

import numpy as np import pandas as pd from statsmodels.stats.outliers_influence import variance_inflation_factor # 计算方差膨胀因子,识别共线性 X_vif = df[["x1", "x2", "x3"]].dropna() vif_data = pd.DataFrame() vif_data["feature"] = X_vif.columns vif_data["VIF"] = [ variance_inflation_factor(X_vif.values, i) for i in range(X_vif.shape[1]) ] print(vif_data)

VIF 的经验判断是大于10提示存在较强共线性,但答题时不能只报数字,要接着写“因此考虑剔除某变量或改用正则化方法”。参数说明上,variance_inflation_factor的第一个参数是特征矩阵,第二个是特征列索引,返回该特征被其余特征解释的程度。面试追问“VIF高了一定要删变量吗”,正确回答是不一定,要看业务含义和模型目的,预测优先可以保留,解释优先才考虑剔除。

3.5 真题演练:交叉验证的规范写法

from sklearn.model_selection import cross_val_score from sklearn.ensemble import RandomForestRegressor # 五折交叉验证评估模型稳定性 rf = RandomForestRegressor(n_estimators=200, random_state=42) scores = cross_val_score(rf, X, y, cv=5, scoring="neg_root_mean_squared_error") print("各折RMSE:", -scores) print("平均RMSE:", -scores.mean())

cv=5表示五折,scoring用负均方根误差是因为 sklearn 的评分约定“越大越好”,取负号后报告时再转回正数。答题时要说明“报告的是五折平均和波动范围”,只报一个平均数而不提波动,会被认为对模型稳定性没有概念。

4. 易错点:五个最容易丢分的地方

4.1 缺失值全局填充,抹掉组间差异

错在哪:直接df.fillna(df.mean())一把梭。为什么错:这道题数据有分组结构,全局均值会把不同组的水平差异压平,后续回归系数失真。怎么答对:先分组再组内填充,并在论文里写明分组依据和填充统计量。

4.2 异常值一删了之

错在哪:看到离群点就drop。为什么错:极端值可能是真实业务信号,删掉会改变样本分布,还可能删掉关键案例。怎么答对:先标记再判断,记录错误才修正,真实极端值保留并在论文里说明处理方式。

4.3 标准化顺序搞反导致信息泄露

错在哪:先对全量数据fit_transform再划分训练测试。为什么错:测试集的分布信息提前进入了预处理参数,评价结果偏乐观。怎么答对:训练集fit,测试集只transform,交叉验证时把预处理放进管道。

4.4 只报准确率不看样本均衡

错在哪:分类任务只写“准确率95%”。为什么错:样本不均衡时高准确率可能只是把所有样本判成多数类。怎么答对:同时报混淆矩阵、召回率和精确率,说明正负样本比例。

4.5 有模型无解释

错在哪:贴完系数表和重要度图就结束。为什么错:题目要的是结论和建议,数字本身不构成答案。怎么答对:每个关键变量配一句业务解释,最后落到可操作建议。

5. 答题节奏:从读题到交卷的固定动作

带过几轮备赛后我发现,这道题失分的人往往不是不会,而是节奏乱。我的固定动作是:读题先圈出“数据字段、任务目标、交付物”三样东西,花十分钟把数据字段和题目要求对齐,避免建模到一半发现漏了某个指标。预处理阶段强制自己写一张小表,列出每个字段的缺失比例、异常标记数、处理方式,这张表直接搬进论文就是过程分。建模阶段先跑基线再谈改进,基线结果不管好坏都留着,它是后面所有对比的锚点。写论文时按“数据问题—处理方法—模型选择—结果解释—建议”五段走,每段第一句先给结论再给依据,阅卷人扫一眼就能抓到得分点。

阶段固定动作对应得分点
读题圈字段、圈目标、圈交付物审题分
预处理缺失比例表、异常标记表过程分
建模先基线后改进,统一评价指标方法分
写作结论先行,每步给理由表达分

押题方向上,预处理规范性和模型对比几乎是必考,结果解释的比重在逐年上升。与其背十个模型,不如把一条“清洗—基线—对比—解释”的链条练到能默写。从那以后我每次带人备赛,都强制先走一遍这条链条再碰复杂模型,翻车的次数明显少了。希望帮到你。

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

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

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

立即咨询