首页 / 资讯中心 / 文章详情

数学建模四类模型怎么选:预测、分类、优化、评价判型与代码骨架

数学建模四类模型怎么选:预测、分类、优化、评价判型与代码骨架 ★ FEATURED ARTICLE
简介这份PDF围绕数学建模竞赛常考的预测、分类、优化与评价四大模型展开面向备赛学生和需要快速梳理建模方法体系的读者可作为赛前复习与选题参考的模板素材。全文按模型类别组织目录逐项说明神经网络、灰色预测、时间序列、马尔科夫链、支持向量机、聚类分析、主成分分析、线性与非线性规划、遗传算法、模糊综合评价、层次分析法和熵权法等方法的适用条件、优缺点与典型应用场景并穿插模型选择与结果评价的提示。资源包共1个PDF文件大小约225KB篇幅紧凑、便于检索适合在有限时间内建立知识框架。已有801人学习读者可据此对照赛题判断该用哪类模型、如何组织论证并借目录快速定位到具体方法提升建模方案设计的条理性与完整度。1. 赛题发下来第三天三个人吵起来了一个要上 LSTM一个要写遗传算法一个坚持先用层次分析法定权重。翻回题目问的是“预测未来三年需求量、给出扩产方案、对五个备选厂址排序”——预测模型、分类模型、优化模型、评价模型这四类在数学建模竞赛里各管一段谁也替不了谁。真正卡住人的不是模型名字是判型这份数据该归到哪一类、参数从哪儿来、算出来的东西能不能自圆其说。下面按预测、分类、优化、评价四类拆开每一类都给判型依据、能直接跑通的代码骨架和参数取值的边界。新手可以照着复现熟手可以顺便对一下自己的习惯有没有跑偏。2. 预测模型先看序列图形状再决定 ARIMA、灰色还是回归2.1 判型样本量、平稳性、协变量三个问题定家族预测模型是四类里出现频率最高、也最容易套错壳的一类。拿到一列数别急着 import先回答三个问题一共多少个观测点、有没有肉眼可见的趋势和周期、除了这条序列还有没有别的解释变量。这三个问题的答案基本就把模型家族锁死了。数据形态首选备选不建议单序列样本少于 12 个灰色 GM(1,1)、指数平滑线性趋势外推LSTM、XGBoost单序列有趋势或季节样本 30 以上SARIMAHolt-Winters灰色 GM(1,1)多协变量样本 100 以上岭回归、梯度提升树随机森林单变量 ARIMA多主体面板按主体分别建模混合效应模型混在一起建模平稳性这一关很多人绕不过去。ADF 检验的原假设是“存在单位根”也就是不平稳p 值小于 0.05 才算拒绝原假设。差分的次数 d 不要为了追求 p 值一路加下去一次差分后平稳就停手过差分会把序列打成白噪声模型什么都学不到残差看着漂亮预测出来是一条直线。还有一个更基础的动作任何预测模型都得先赢朴素基线。朴素基线就是“拿上一期当下一期”或者“拿最近三期的均值”。如果 ARIMA 的误差比朴素基线还大说明这条序列里根本没有可提取的结构这时候该做的是回去检查数据而不是换个更复杂的模型继续调。2.2 statsmodels 跑通「朴素基线 → ARIMA → 残差检验」最小链路下面这段是可以直接改数据就运行的骨架四步平稳性判断、基线对照、定阶、残差体检。import numpy as np import pandas as pd from statsmodels.tsa.stattools import adfuller from statsmodels.tsa.arima.model import ARIMA from statsmodels.stats.diagnostic import acorr_ljungbox # y 是按时间顺序排好的一维观测值此处假设已按等间隔采样 s pd.Series(y, dtypefloat64) # 1. 平稳性p 小于 0.05 才认为不存在单位根 print(ADF p , round(adfuller(s, autolagAIC)[1], 4)) # 2. 朴素基线上一期直接当下一期复杂模型必须先赢它 naive_mae np.mean(np.abs(s.values[1:] - s.values[:-1])) print(naive MAE , round(naive_mae, 3)) # 3. 定阶d 由 ADF 结果决定p 和 q 在 0~2 内网格搜 AIC best_order, best_aic None, np.inf for p in range(3): for q in range(3): try: m ARIMA(s, order(p, 1, q)).fit() except Exception: continue # 不收敛的组合直接跳过不要死磕 if m.aic best_aic: best_order, best_aic (p, 1, q), m.aic res ARIMA(s, orderbest_order).fit() print(best order , best_order, AIC , round(best_aic, 2)) # 4. 残差体检Ljung-Box 的 p 大于 0.05 才说明残差接近白噪声 lb acorr_ljungbox(res.resid, lags[6], return_dfTrue) print(Ljung-Box p , round(lb[lb_pvalue].iloc[0], 4)) print(res.forecast(steps3)) # 未来三步的点预测逻辑说明定阶用 AIC 而不是看 ACF/PACF 图硬读是因为竞赛里时间紧图读错的代价比多跑几十次拟合高得多但 AIC 只在同一份数据、同样的差分阶数下可比跨 d 比较没有意义。参数上p 和 q 的搜索上限设成 2 就够样本不到 50 个点时上限设 1再往上基本都是过拟合。残差检验这一步千万不要省。Ljung-Box 的 p 值小于 0.05说明残差里还有没被提取的结构这时候要么加阶数要么回头补协变量要么承认这条序列用线性模型搞不定。我把这一步叫预测模型的黑匣子体检——模型内部发生了什么你看不见但残差会告诉你。forecast(steps3)给的是点预测论文里只写点预测会被问“区间呢”。用res.get_forecast(steps3).conf_int()拿置信区间宽度随步长变大是正常现象如果宽度不随步长增长反而说明模型设定有问题。2.3 灰色 GM(1,1)小样本的兜底方案与级比检验竞赛数据经常只有 8 到 12 个年度值这种量级上 ARIMA 定阶纯属玄学灰色 GM(1,1) 反而是更稳的选择它本质上是对一次累加序列拟合指数趋势需要的样本少对手算和代码都友好。上模型之前必须先做级比检验这是灰色模型最容易被跳过、也最容易翻车的地方。级比 λ(k) 等于前一个值除以后一个值全部落在区间 (e^(-2/(n1)), e^(2/(n1))) 内才能建模越界说明序列波动过大要么做平移变换要么换模型。import numpy as np def gm11(x, steps1): x np.asarray(x, dtypefloat) n len(x) # 级比检验不通过就别硬上先考虑平移或换模型 lam x[:-1] / x[1:] lo, hi np.exp(-2 / (n 1)), np.exp(2 / (n 1)) if not ((lam lo) (lam hi)).all(): raise ValueError(f级比越界允许区间 ({lo:.3f}, {hi:.3f}) f实际范围 ({lam.min():.3f}, {lam.max():.3f})) x1 np.cumsum(x) # 一次累加生成 z1 0.5 * (x1[1:] x1[:-1]) # 紧邻均值序列 B np.column_stack([-z1, np.ones(n - 1)]) a, b np.linalg.lstsq(B, x[1:], rcondNone)[0] # 最小二乘估参数 k np.arange(n steps) x1_hat (x[0] - b / a) * np.exp(-a * k) b / a x_hat np.diff(x1_hat, prepend0) # 累减还原成原量纲 return x_hat, a, b参数说明a 是发展系数反映增长速度b 是灰作用量可以理解成外生驱动。判断能不能用看 -a 的落点-a 不超过 0.3 可以做到中长期预测0.3 到 0.5 只报短期0.5 到 1 要非常谨慎超过 1 就别用了指数项会发散。b 本身没有独立解释意义别在论文里给它编故事。做完预测还要给精度等级。常用的是后验差比 C 等于残差标准差除以原始序列标准差C 小于 0.35 算好、小于 0.5 算合格、超过 0.65 不合格配合小误差概率 PP 大于 0.95 为好。另外用 MAPE 做横向对比时注意一个坑真值接近 0 的时候 MAPE 会爆炸这种序列改用 MAE 或 RMSE 报误差别硬套百分比。3. 分类模型从混淆矩阵倒推该用哪个分类器3.1 先定口径不平衡数据下准确率是最会骗人的指标分类模型的选型顺序和大多数教程相反不是先挑算法而是先定评价口径。竞赛数据里正负样本 9:1 是常态这时候一个“全部判成多数类”的模型准确率有 90%但它什么都没学到。教育公平、风险预警这类赛题往往更在意漏判召回而不是整体准确率。场景主指标辅助指标说明二分类正类稀少召回率、PR 曲线下面积F1别报准确率会误导评委二分类两类均衡ROC 曲线下面积准确率、F1阈值默认 0.5可调多分类类别不均macro-F1加权 F1macro 对少数类敏感有明确误判代价加权代价混淆矩阵代价矩阵要在论文里写明阈值不是必须取 0.5。用predict_proba拿到概率后按召回率要求反推阈值在论文里写清楚“取阈值 0.32 时漏判率降到 5%代价是误判率升到 18%”——这种表述比报一个孤零零的准确率有说服力得多。混淆矩阵要真的看不能只报一个数。哪两类在混、混的方向是单向还是双向直接决定下一步是补特征还是换模型。如果 A 类被判成 B 类的比例特别高先怀疑这两类的特征在某个维度上重叠而不是急着调参。3.2 sklearn 流水线把重采样关进训练折里重采样必须放在交叉验证的每一折内部这是分类模型最常见的翻车点。先对全体数据做 SMOTE 再切分合成样本会同时出现在训练折和验证折分数能虚高十几个点等真正预测时原形毕露。from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.model_selection import StratifiedKFold, cross_validate from imblearn.pipeline import Pipeline from imblearn.over_sampling import SMOTE pipe Pipeline([ (imp, SimpleImputer(strategymedian)), # 缺失值用中位数抗异常值 (sc, StandardScaler()), # 线性模型必须标准化 (smote, SMOTE(random_state42, k_neighbors5)), (clf, LogisticRegression(max_iter2000, class_weightbalanced)), ]) cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) scores cross_validate( pipe, X, y, cvcv, scoring[accuracy, f1, recall, roc_auc], return_train_scoreTrue, ) for k in scores: if k.startswith(test_): print(k, round(scores[k].mean(), 3), ±, round(scores[k].std(), 3))逻辑说明用 imblearn 的 Pipeline 而不是 sklearn 的是因为只有前者会把重采样器当成一个可 fit 的步骤在每折训练集内部单独执行。参数上k_neighbors是合成少数类样本时参考的邻居数少数类样本少于 6 个时必须把这个值调小否则直接抛异常class_weightbalanced和 SMOTE 二选一即可两个一起上常常把召回顶到很高、精确率掉到没法看。return_train_scoreTrue打开后训练分和验证分要一起看。两者差距超过 0.1基本可以判定过拟合两者都低是欠拟合或者特征本身没信息量这时候换模型没用回去做特征。标准化放在 Pipeline 里而不是提前对全量数据做理由和 SMOTE 一样均值方差里混进了验证折的信息属于隐蔽的泄漏。这类泄漏不会报错只会让你的分数不可复现。3.3 特征三查共线性、重要性排序与时间口径特征工程做完至少过三道检查。第一查共线性。线性模型对共线敏感方差膨胀因子超过 10 的变量要么删、要么合并。树模型对共线性不敏感但共线会让重要性排序变得不可解释——两个高度相关的特征重要性会被随机分到其中一个身上换个随机种子结论就变了。第二查重要性排序的稳定性。优先用置换重要性而不是模型自带的feature_importances_后者对高基数特征有系统性偏好。做法很简单打乱某一列看指标掉多少掉得越多说明越重要。跑三次不同种子排序基本一致的才写进论文。第三查时间口径。如果数据带时间戳随机 KFold 会把未来信息泄漏到训练集用TimeSeriesSplit按时间切。这一条在销量预测、信用违约这类赛题里经常被忽略而在真实业务里用未来数据训练出的模型上线当天就会失效。最后补一句特征筛选的边界特征不是越多越好也不是越少越好。加特征的唯一理由是验证分涨了如果验证分没动而训练分涨了那就是在给模型喂噪声。4. 优化与评价一个在约束里找最优解一个在指标里排先后4.1 优化题的三个翻译动作变量、目标、约束优化模型的门槛不在算法在翻译。题目里那些“在满足……的前提下使……最小”的句子要拆成三样东西。决策变量先定类型产量、流量、比例这类可以取小数的用连续变量人数、车次、设备台数用整数变量选不选、开不开用 0-1 变量。类型定错了后面的工作全白做——把人数设成连续变量解出来 3.7 个人再四舍五入成 4 个很可能已经违反约束了。目标函数要连同量纲一起写。多目标题别一上来就加权求和先各自归一化再加权否则量纲大的那个目标会独占权重。常见处理有三种加权和简单但权重难解释、ε 约束把一个目标转成约束跑出一整条帕累托前沿、分层序列按优先级依次求解。竞赛里优先用 ε 约束因为能画图图比数字好讲。约束要分清“至少”“恰好”“不超过”。把“至少需要 2 人”写成等式模型直接无解。另外一个高频错误是逻辑约束没写只有开工才产出就得补上 y 不超过 M 乘 x 这种大 M 约束M 取该变量可能的最大值取太大数值不稳定取太小会误砍掉可行解。4.2 PuLP 排班模型从求解状态码读到影子价格排班是最典型的整数规划题也最适合拿来练手。下面这个模型五个班次人员、每天三个班、每班有人数下限、每人每天最多一个班。import pulp W [A, B, C, D, E] S [早, 中, 晚] need {早: 2, 中: 1, 晚: 1} wage {(w, s): 30 5 * i 3 * j for i, w in enumerate(W) for j, s in enumerate(S)} prob pulp.LpProblem(shift, pulp.LpMinimize) x pulp.LpVariable.dicts(x, (W, S), catBinary) # 目标总人力成本最小 prob pulp.lpSum(wage[w, s] * x[w][s] for w in W for s in S) # 约束一每班人数不低于需求命名方便后面读对偶值 for s in S: prob (pulp.lpSum(x[w][s] for w in W) need[s], fdemand_{s}) # 约束二每人每天最多一个班且至少一个班 for w in W: prob (pulp.lpSum(x[w][s] for s in S) 1, fmost_{w}) prob (pulp.lpSum(x[w][s] for s in S) 1, fleast p a hrefhttps://download.csdn.net/download/weixin_39827856/87801910 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
阅读完成 · 觉得有帮助?
咨询建站