简介:一套面向高校数学建模竞赛的完整培训材料,涵盖基础理论、建模方法、真题解析与源代码实现,适合从入门到备赛冲刺的各阶段学生。压缩包共61个文件,约2.02MB,以30个MATLAB脚本、16个Word文档和6个Excel表格为主,另有少量PPT演示、数据文件与自动保存备份,脚本可直接用于模型求解与仿真,文档则包含赛题详解、优秀论文和算法案例。已有355人学习下载,内容包括历年真题(如1998年A题、2003年A题)、自动化车床管理、钢管订购与运输等经典赛题,以及蒙特卡洛法、神经网络等常用算法代码,可帮助读者理解从问题分析到编程实现再到论文输出的完整流程。对于正在备战数模竞赛的学生而言,这份材料既能巩固数理基础,也能提供可复用的代码模板和写作范本,具有较高的参考价值。1. 数学建模竞赛的准备周期为什么离不开这套真题解读和源代码数模培训和数模竞赛材料里最值钱的东西,不是某一道题的答案,而是一条从“读题 → 建模 → 编程 → 写作”的完整链路。多数队伍翻车都不是算法学得少,而是到了比赛第三天还在补环境、修代码,论文里的数字跟程序跑出来的对不上。这套含真题解读和源代码的资源,把培训讲义、赛题拆解、参考论文框架和可直接运行的算法脚本打包在一起,适合被临时抓来带队数模培训的指导老师、第一次参加校级或省级选拔的学生队伍,以及赛后想复盘自己到底输在哪里的参赛者。它不负责替你思考,但能保证你不卡在“知道模型却写不出第一行代码”这个坎上。2. 真题解读与论文结构:先搞清数模竞赛评委在看什么2.1 七段式论文结构与评审落点很多队伍拿到真题解读就急着看模型公式,这是本末倒置。评委看一篇数模论文的平均时间只有几分钟,真正决定名次的是前三十秒内摘要有没有把“问题、模型、结果、误差”四件事说清楚。包内的真题解读几乎都围绕七段式结构展开:摘要、问题重述、模型假设、符号说明、模型建立与求解、模型检验、评价与推广。论文模块主要内容常见失分点摘要问题重述、所用模型、数值结果、误差只写背景,没有具体数字问题重述用自己的话转述题目大段抄题,压缩包里的批注版真题会直接标出来模型假设对数据、环境做合理限定假设过多导致模型失真,或过少导致推导不严谨符号说明变量一览表符号前后不一致,代码变量与论文符号对不上模型建立与求解推导过程、算法步骤、代码片段只贴大段代码不做逻辑解释模型检验残差、误差率、灵敏度分析完全没有检验环节评价与推广模型局限与可扩展点空话套话,落不到具体数据上我一般要求学生在写摘要前先回答三个问题:用的是什么模型、输入数据是什么、输出的核心数值是多少。摘要里必须出现至少两个模型名加三组数值,比如“均值误差为0.12”“灵敏度在±20%内排名稳定”这种话,评委扫一眼就能判断这篇论文是否认真跑了实验。2.2 真题解读的正确操作:从题眼到模型归类真题解读不是用来背的,它是用来建立“题型到算法”映射的。包内常见的真题解读文件按年份和题目编号组织,每套题解包含题目原文、参考论文摘要和三页左右批注。拿到一套题,我习惯按四步走:圈题眼:把题干拆成背景、数据、问题三块,标出“预测、优化、评价、分类”这类动词。分类型:题干里出现“未来某时段流量”是预测类;“多个方案选优”是评价类;“最小化成本或最大化收益”是优化类。对模型:把类型映射到包内代码目录,不用现场翻书。定数据接口:找到数据文件的列名、单位、缺失值标记,别等到比赛第二天才发现单位不统一。一个参考映射表长这样:赛题类型高频模型代码包对应文件预测类GM(1,1)、线性回归、ARIMA、LSTMpredict/gm111.py、predict/regression.py评价类AHP、熵权法、TOPSISevaluate/ahp.py、evaluate/topsis_entropy.py优化类线性规划、整数规划、遗传算法optimize/lp.py、optimize/ga.py分类类逻辑回归、随机森林、SVMclassify/logit.py、classify/rf.py这里有个很隐蔽的坑:参考论文选用的模型往往偏“好看”,比如评价题非要用AHP加模糊综合,但真实比赛数据里可能存在大量缺失值,AHP的判断矩阵压根构造不出来。真题解读的价值是让你看到模型适用边界,而不是让你原样照搬。我每次带模拟项目X的数据训练,都会强制学生先写一段数据探查代码,把列类型、缺失率、量纲差异打出来,再决定用哪个模型。3. 源代码包与复现环境:把数模培训里的算法从黑匣子变成工具3.1 代码包目录结构与算法清单这套资源里的源代码部分不是零散脚本,而是按功能分好层的。解压后常见目录如下:. ├── data/ # 赛题数据与预处理中间结果 ├── code/ │ ├── predict/ # 灰色预测、线性回归、时间序列 │ ├── evaluate/ # AHP、TOPSIS、熵权法 │ ├── optimize/ # 线性规划、遗传算法、模拟退火 │ ├── classify/ # 逻辑回归、随机森林 │ └── plot/ # 出图与中文字体配置 ├── papers/ # 真题解读、参考论文与批注 └── requirements.txt数据目录、代码目录、论文目录分开,是数模培训里最基本但最容易忽略的好习惯。很多队伍把代码和数据混在一个文件夹里,最后导出结果时找不到原始数据。包内每个子目录通常带一个README说明,讲了每个脚本的输入输出,这比代码本身还重要。3.2 搭建可复现的Python环境:依赖与版本锁代码是否能跑起来,一半取决于环境多干净。我一般建议用虚拟环境,别直接在全局Python里装包,否则不同项目之间的依赖打架,比赛当天很容易翻车。python -m venv .venv source .venv/bin/activate # Windows 下用 .venv\Scripts\activate pip install --upgrade pip pip install -r requirements.txt逻辑说明:python -m venv .venv创建隔离环境,激活后所有包只装进这个项目目录,不会污染系统Python。requirements.txt里通常锁定这几个核心包:numpy、pandas、scipy、scikit-learn、matplotlib、openpyxl。参数说明:Python版本建议锁定在3.9附近,太新的3.12有时会让部分依赖包需要重新编译,对比赛队伍不划算;openpyxl是read_excel读取xlsx的引擎,没装会报ImportError。3.3 跑通第一个脚本:路径、编码与数据接入环境装好后,别急着跑高深算法,先跑一个读数据脚本验证链路通不通。import pandas as pd # data_path 改成你自己解压后的绝对路径,Windows 下注意反斜杠 data = pd.read_excel("data/traffic_flow.xlsx", engine="openpyxl", parse_dates=["date"], index_col="date") series = data["flow"].dropna() print(series.head())逻辑说明:read_excel读取Excel表格,parse_dates=["date"]把日期列解析成时间类型,index_col="date"把日期设为索引,方便后续按时间切片。dropna()剔除缺失值,但这里只是探查用,正式建模不要直接删,第5章会专门讲。参数说明:engine="openpyxl"是显式指定读取xlsx的引擎,如果报Missing optional dependency 'openpyxl',执行pip install openpyxl即可。这段跑通后,再进预测模块。from models import GM111 # 以包内常见封装为例,实际文件名见各目录README model = GM111(n=5) # n=5 表示预测未来5个时间点 model.fit(series.values[:20]) # 只用前20个样本做拟合 result = model.predict()逻辑说明:GM111是对灰色预测的一个轻量封装,fit接收一维数组,predict返回预测值。参数说明:n是外推长度,经验上限是样本长度除以3,超过这个值预测曲线容易指数爆炸;fit里传前20个点是因为这类模型用太多历史点反而会把噪声学进去,尤其是趋势有波动的数据。4. 三类高频题实战:参数设置与结果落表4.1 预测类:GM(1,1) 与线性回归做基线灰色预测是数模赛场上的“老朋友”,数据量少、趋势单调时特别好用。包内predict目录下的gm111.py核心逻辑如下:import numpy as np def gm11(x0, K=5): # x0:一维原始序列,长度建议不小于4 x0 = np.asarray(x0, dtype=float) n = len(x0) x1 = np.cumsum(x0) # 一次累加,弱化随机波动 Z = (x1[:-1] + x1[1:]) / 2.0 # 紧邻均值生成序列 B = np.column_stack([-Z, np.ones(n-1)]) Y = x0[1:] u = np.linalg.lstsq(B, Y, rcond=None)[0] # 最小二乘求发展系数 a 和灰作用量 b a, b = u[0], u[1] xhat = np.zeros(n + K) xhat[0] = x0[0] for k in range(1, n + K): xhat[k] = (x0[0] - b / a) * np.exp(-a * (k - 1)) + b / a out = np.diff(xhat, prepend=xhat[0]) # 累减还原 return out[:n], out[n:]逻辑说明:np.cumsum做一次累加,是把波动序列变平滑的标准操作;np.linalg.lstsq求解最小二乘问题得到参数a和b,a是发展系数,反映增长趋势,b是灰作用量。参数说明:K是外推期数,我一般控制在样本长度的三分之一以内;rcond=None是让numpy自动处理奇异矩阵,避免报错。跑出来之后还要跟一个基线模型对比,否则评委问“凭什么用灰色预测”时答不上来。from sklearn.linear_model import LinearRegression X = np.arange(len(series)).reshape(-1, 1) y = series.values model = LinearRegression().fit(X, y) pred = model.predict(np.arange(len(series), len(series)+5).reshape(-1, 1))逻辑说明:线性回归只是把时间序号当自变量,数值当因变量,跑一个最小二乘拟合;它不是一个“好”的预测模型,但绝对是一个合格的baseline。参数说明:reshape(-1, 1)是sklearn对输入格式的硬要求,特征必须是二维数组,很多新手在这里报错。对比GM(1,1)和线性回归的误差,如果灰色预测没有明显更优,就老实写回归。4.2 评价类:熵权法算权重,TOPSIS排排序评价类赛题里,AHP因为要人工构造判断矩阵,主观性强,容易在答辩环节被质疑。我更推荐先用熵权法从数据里反推权重,再用TOPSIS排序,这样每一步都有数据支撑。def entropy_weight(X): # X:样本×指标矩阵,已经完成正向化 X = X / X.sum(axis=0, keepdims=True) # 归一化 n = X.shape[0] k = 1 / np.log(n) e = -k * (X * np.log(X + 1e-9)).sum(axis=0) # 信息熵 w = (1 - e) / (1 - e).sum() # 权重 return w逻辑说明:熵权法的思路是指标数据越分散,信息量越大,权重越高。X / X.sum(axis=0)按列归一化,np.log(X + 1e-9)防止log0产生负无穷。参数说明:1e-9是平滑因子,如果某列数值为0,这个加项能让计算不崩溃;正向化要在这一步之前完成,比如成本型指标取倒数或取负值。def topsis(X, w): Z = X / np.sqrt((X**2).sum(axis=0, keepdims=True)) # 向量归一化 ideal_best = Z.max(axis=0) # 正理想解 ideal_worst = Z.min(axis=0) # 负理想解 d_best = np.sqrt(((Z - ideal_best)**2).dot(w)) d_worst = np.sqrt(((Z - ideal_worst)**2).dot(w)) return d_worst / (d_best + d_worst) # 贴近度逻辑说明:TOPSIS先构造正理想解和负理想解,然后计算每个样本到两者的距离。贴近度越大说明离正理想解越近,离负理想解越远。参数说明:w是熵权法输出的权重向量,dot(w)是加权欧式距离;如果指标没统一量纲,贴近度会被数值量级大的指标主导,这也是第5章要展开的坑。4.3 优化类:线性规划与遗传算法兜底优化题的经典套路是先用线性规划求出理想解,再用启发式算法验证或改进。from scipy.optimize import linprog # 目标函数:最大化 3*x1 + 5*x2,转成最小化负值 c = [-3, -5] # 约束:x1 <= 4, 2*x2 <= 12, 3*x1 + 2*x2 <= 18 A = [[1, 0], [0, 2], [3, 2]] b = [4, 12, 18] bounds = [(0, None), (0, None)] res = linprog(c, A_ub=A, b_ub=b, bounds=bounds, method="highs") print(res.x, -res.fun)逻辑说明:linprog默认解最小化问题,所以最大化目标要加负号,res.fun加负号后才是真实最大值。A_ub和b_ub表示小于等于约束,这是线性规划的标准形式。参数说明:method="highs"是scipy 1.6以后默认的求解器,比旧的单纯形算法稳定很多;变量无上限时用None,有整数要求时得换milp,不能直接传整数约束。当约束非线性或变量离散时,线性规划解不了,就用包内optimize/ga.py的遗传算法框架。这类算法主要调三个参数:种群规模(50到200之间)、迭代次数(100到300之间)、交叉变异概率(通常0.7到0.2),跑十次取最优解。记住一个习惯:先跑线性规划拿到上界,再跑遗传算法看能不能贴近上界,如果差很多就是编码方式出了问题。5. 常见避坑与排查:从数据到提交的五个翻车现场5.1 数据与建模的翻车现场翻车点一:缺失值直接删除,预测曲线集体偏掉。现象:dropna()之后样本量少了一半,预测结果跟原始数据完全对不上。原因:Excel里的空白格被读到DataFrame里是NaN,盲目删行会把有效信息一起删掉。解决:先跑data.isna().sum()统计每列缺失量,再决定策略。数值列用df['flow'].interpolate()做线性插值,比例超过30%的列只能当参考,不进模型。翻车点二:量纲不统一,TOPSIS排序被大数支配。现象:熵权法算出的权重正常,但贴近度排序几乎只跟“价格”这一列一致。原因:价格单位是万元,其他指标是百分比或千克,向量归一化后量级大的列方差占绝对主导。解决:建模前统一计量单位,并做一次极差归一化(X - X.min(0)) / (X.max(0) - X.min(0)),让所有指标落在0到1之间再算权重。翻车点三:灰色预测外推期数设太大,曲线直接爆炸。现象:预测第10期出现几千亿的数量级。原因:GM(1,1)里的指数项会随K增大快速累加,本质只适合短期外推。解决:把K限制在样本长度的三分之一以内,论文里明确写“本模型仅作短期预测”,并给出残差检验表,证明前几个预测点的误差在可接受范围。5.2 写作与提交的翻车现场翻车点四:摘要只写研究背景,没有任何数值结果。现象:评委看完摘要不知道这篇论文解决了什么,也不知道最终预测值是多少。原因:把摘要写成了科普文,没有按“问题-模型-结果-误差”的结构组织。解决:摘要第一句就写“针对XX问题,建立XX模型,求得XX=1.23,模型平均误差为X%”,把灵敏度结论也塞进最后一句,比如“当权重在±20%内扰动时,排名保持稳定”。评委看到数字,才会接着看正文。翻车点五:论文里的数字和代码跑出来的对不上。现象:论文写“均方误差为0.12”,评委复跑是0.35;或者图表里的曲线比代码多了一段。原因:最后一天边改参数边手动截图,没有全量重跑脚本。解决:比赛期间所有文件按“题号_模型_日期.py”命名,每一次改动后强制把输出CSV和图片重新导出,论文里每个数字都必须能在某个CSV里查到。> 提示:我把这当作“后悔药”机制——宁可在最后半天重新渲染一次全部图表,也别赌评委不会复跑你的代码。6. 最后一天冲刺:灵敏度分析、模型对比与出图规范进入比赛最后一天,不要再往模型里塞新算法,把精力放在三个动作上:灵敏度分析、模型对比、出图规范化。灵敏度分析是让评委相信模型稳健的最快手段。做法是给关键参数加扰动,看排序或预测结果有没有翻转:# 对权重向量施加扰动,观察TOPSIS排名变化 for alpha in [-0.2, -0.1, 0.1, 0.2]: w2 = w + alpha * np.ones(len(w)) w2 = w2 / w2.sum() rank = topsis(X, w2) print(f"alpha={alpha:+.1f} ->", np.argsort(-rank)[:5])逻辑说明:alpha是扰动幅度,正负分别代表权重上调或下调;每次扰动后重新归一化再排序。如果前五名在四组扰动下基本不变,这段输出就能直接写进模型检验章节。参数说明:np.ones(len(w))保证所有权重同方向扰动,更精细的做法是每次只扰动一个指标,观察单一权重的敏感度。模型对比表是论文的点睛之笔。别只放最终模型的结果,把基线模型也放上去:模型平均绝对误差结论线性回归0.34趋势拟合,适合作为基线GM(1,1)0.12短期预测稳定,优于基线最后是出图规范。很多队伍算法跑得很好,图却丑得离谱。打开包内plot下的配置文件,至少要把中文字体和不支持负号的问题解决:import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] plt.rcParams['axes.unicode_minus'] = False plt.figure(dpi=300)逻辑说明:font.sans-serif指定中文字体,axes.unicode_minus让负号正常显示,不设置这两行的话,论文里会出现方框和乱码负号。参数说明:dpi=300是印刷级清晰度,插入Word时建议用PNG格式,别直接截屏。从那以后,我每次带队到最后一天,都会强制走一遍“扰动-对比-重导出”这个流程,宁可少做一个花哨模型,也要做到论文里每个数字都能追溯、每张图都敢让评委放大看。希望帮到你。本文还有配套的精品资源,点击获取
简介:一套面向高校数学建模竞赛的完整培训材料,涵盖基础理论、建模方法、真题解析与源代码实现,适合从入门到备赛冲刺的各阶段学生。压缩包共61个文件,约2.02MB,以30个MATLAB脚本、16个Word文档和6个Excel表格为主,另有少量PPT演示、数据文件与自动保存备份,脚本可直接用于模型求解与仿真,文档则包含赛题详解、优秀论文和算法案例。已有355人学习下载,内容包括历年真题(如1998年A题、2003年A题)、自动化车床管理、钢管订购与运输等经典赛题,以及蒙特卡洛法、神经网络等常用算法代码,可帮助读者理解从问题分析到编程实现再到论文输出的完整流程。对于正在备战数模竞赛的学生而言,这份材料既能巩固数理基础,也能提供可复用的代码模板和写作范本,具有较高的参考价值。1. 数学建模竞赛的准备周期为什么离不开这套真题解读和源代码数模培训和数模竞赛材料里最值钱的东西,不是某一道题的答案,而是一条从“读题 → 建模 → 编程 → 写作”的完整链路。多数队伍翻车都不是算法学得少,而是到了比赛第三天还在补环境、修代码,论文里的数字跟程序跑出来的对不上。这套含真题解读和源代码的资源,把培训讲义、赛题拆解、参考论文框架和可直接运行的算法脚本打包在一起,适合被临时抓来带队数模培训的指导老师、第一次参加校级或省级选拔的学生队伍,以及赛后想复盘自己到底输在哪里的参赛者。它不负责替你思考,但能保证你不卡在“知道模型却写不出第一行代码”这个坎上。2. 真题解读与论文结构:先搞清数模竞赛评委在看什么2.1 七段式论文结构与评审落点很多队伍拿到真题解读就急着看模型公式,这是本末倒置。评委看一篇数模论文的平均时间只有几分钟,真正决定名次的是前三十秒内摘要有没有把“问题、模型、结果、误差”四件事说清楚。包内的真题解读几乎都围绕七段式结构展开:摘要、问题重述、模型假设、符号说明、模型建立与求解、模型检验、评价与推广。论文模块主要内容常见失分点摘要问题重述、所用模型、数值结果、误差只写背景,没有具体数字问题重述用自己的话转述题目大段抄题,压缩包里的批注版真题会直接标出来模型假设对数据、环境做合理限定假设过多导致模型失真,或过少导致推导不严谨符号说明变量一览表符号前后不一致,代码变量与论文符号对不上模型建立与求解推导过程、算法步骤、代码片段只贴大段代码不做逻辑解释模型检验残差、误差率、灵敏度分析完全没有检验环节评价与推广模型局限与可扩展点空话套话,落不到具体数据上我一般要求学生在写摘要前先回答三个问题:用的是什么模型、输入数据是什么、输出的核心数值是多少。摘要里必须出现至少两个模型名加三组数值,比如“均值误差为0.12”“灵敏度在±20%内排名稳定”这种话,评委扫一眼就能判断这篇论文是否认真跑了实验。2.2 真题解读的正确操作:从题眼到模型归类真题解读不是用来背的,它是用来建立“题型到算法”映射的。包内常见的真题解读文件按年份和题目编号组织,每套题解包含题目原文、参考论文摘要和三页左右批注。拿到一套题,我习惯按四步走:圈题眼:把题干拆成背景、数据、问题三块,标出“预测、优化、评价、分类”这类动词。分类型:题干里出现“未来某时段流量”是预测类;“多个方案选优”是评价类;“最小化成本或最大化收益”是优化类。对模型:把类型映射到包内代码目录,不用现场翻书。定数据接口:找到数据文件的列名、单位、缺失值标记,别等到比赛第二天才发现单位不统一。一个参考映射表长这样:赛题类型高频模型代码包对应文件预测类GM(1,1)、线性回归、ARIMA、LSTMpredict/gm111.py、predict/regression.py评价类AHP、熵权法、TOPSISevaluate/ahp.py、evaluate/topsis_entropy.py优化类线性规划、整数规划、遗传算法optimize/lp.py、optimize/ga.py分类类逻辑回归、随机森林、SVMclassify/logit.py、classify/rf.py这里有个很隐蔽的坑:参考论文选用的模型往往偏“好看”,比如评价题非要用AHP加模糊综合,但真实比赛数据里可能存在大量缺失值,AHP的判断矩阵压根构造不出来。真题解读的价值是让你看到模型适用边界,而不是让你原样照搬。我每次带模拟项目X的数据训练,都会强制学生先写一段数据探查代码,把列类型、缺失率、量纲差异打出来,再决定用哪个模型。3. 源代码包与复现环境:把数模培训里的算法从黑匣子变成工具3.1 代码包目录结构与算法清单这套资源里的源代码部分不是零散脚本,而是按功能分好层的。解压后常见目录如下:. ├── data/ # 赛题数据与预处理中间结果 ├── code/ │ ├── predict/ # 灰色预测、线性回归、时间序列 │ ├── evaluate/ # AHP、TOPSIS、熵权法 │ ├── optimize/ # 线性规划、遗传算法、模拟退火 │ ├── classify/ # 逻辑回归、随机森林 │ └── plot/ # 出图与中文字体配置 ├── papers/ # 真题解读、参考论文与批注 └── requirements.txt数据目录、代码目录、论文目录分开,是数模培训里最基本但最容易忽略的好习惯。很多队伍把代码和数据混在一个文件夹里,最后导出结果时找不到原始数据。包内每个子目录通常带一个README说明,讲了每个脚本的输入输出,这比代码本身还重要。3.2 搭建可复现的Python环境:依赖与版本锁代码是否能跑起来,一半取决于环境多干净。我一般建议用虚拟环境,别直接在全局Python里装包,否则不同项目之间的依赖打架,比赛当天很容易翻车。python -m venv .venv source .venv/bin/activate # Windows 下用 .venv\Scripts\activate pip install --upgrade pip pip install -r requirements.txt逻辑说明:python -m venv .venv创建隔离环境,激活后所有包只装进这个项目目录,不会污染系统Python。requirements.txt里通常锁定这几个核心包:numpy、pandas、scipy、scikit-learn、matplotlib、openpyxl。参数说明:Python版本建议锁定在3.9附近,太新的3.12有时会让部分依赖包需要重新编译,对比赛队伍不划算;openpyxl是read_excel读取xlsx的引擎,没装会报ImportError。3.3 跑通第一个脚本:路径、编码与数据接入环境装好后,别急着跑高深算法,先跑一个读数据脚本验证链路通不通。import pandas as pd # data_path 改成你自己解压后的绝对路径,Windows 下注意反斜杠 data = pd.read_excel("data/traffic_flow.xlsx", engine="openpyxl", parse_dates=["date"], index_col="date") series = data["flow"].dropna() print(series.head())逻辑说明:read_excel读取Excel表格,parse_dates=["date"]把日期列解析成时间类型,index_col="date"把日期设为索引,方便后续按时间切片。dropna()剔除缺失值,但这里只是探查用,正式建模不要直接删,第5章会专门讲。参数说明:engine="openpyxl"是显式指定读取xlsx的引擎,如果报Missing optional dependency 'openpyxl',执行pip install openpyxl即可。这段跑通后,再进预测模块。from models import GM111 # 以包内常见封装为例,实际文件名见各目录README model = GM111(n=5) # n=5 表示预测未来5个时间点 model.fit(series.values[:20]) # 只用前20个样本做拟合 result = model.predict()逻辑说明:GM111是对灰色预测的一个轻量封装,fit接收一维数组,predict返回预测值。参数说明:n是外推长度,经验上限是样本长度除以3,超过这个值预测曲线容易指数爆炸;fit里传前20个点是因为这类模型用太多历史点反而会把噪声学进去,尤其是趋势有波动的数据。4. 三类高频题实战:参数设置与结果落表4.1 预测类:GM(1,1) 与线性回归做基线灰色预测是数模赛场上的“老朋友”,数据量少、趋势单调时特别好用。包内predict目录下的gm111.py核心逻辑如下:import numpy as np def gm11(x0, K=5): # x0:一维原始序列,长度建议不小于4 x0 = np.asarray(x0, dtype=float) n = len(x0) x1 = np.cumsum(x0) # 一次累加,弱化随机波动 Z = (x1[:-1] + x1[1:]) / 2.0 # 紧邻均值生成序列 B = np.column_stack([-Z, np.ones(n-1)]) Y = x0[1:] u = np.linalg.lstsq(B, Y, rcond=None)[0] # 最小二乘求发展系数 a 和灰作用量 b a, b = u[0], u[1] xhat = np.zeros(n + K) xhat[0] = x0[0] for k in range(1, n + K): xhat[k] = (x0[0] - b / a) * np.exp(-a * (k - 1)) + b / a out = np.diff(xhat, prepend=xhat[0]) # 累减还原 return out[:n], out[n:]逻辑说明:np.cumsum做一次累加,是把波动序列变平滑的标准操作;np.linalg.lstsq求解最小二乘问题得到参数a和b,a是发展系数,反映增长趋势,b是灰作用量。参数说明:K是外推期数,我一般控制在样本长度的三分之一以内;rcond=None是让numpy自动处理奇异矩阵,避免报错。跑出来之后还要跟一个基线模型对比,否则评委问“凭什么用灰色预测”时答不上来。from sklearn.linear_model import LinearRegression X = np.arange(len(series)).reshape(-1, 1) y = series.values model = LinearRegression().fit(X, y) pred = model.predict(np.arange(len(series), len(series)+5).reshape(-1, 1))逻辑说明:线性回归只是把时间序号当自变量,数值当因变量,跑一个最小二乘拟合;它不是一个“好”的预测模型,但绝对是一个合格的baseline。参数说明:reshape(-1, 1)是sklearn对输入格式的硬要求,特征必须是二维数组,很多新手在这里报错。对比GM(1,1)和线性回归的误差,如果灰色预测没有明显更优,就老实写回归。4.2 评价类:熵权法算权重,TOPSIS排排序评价类赛题里,AHP因为要人工构造判断矩阵,主观性强,容易在答辩环节被质疑。我更推荐先用熵权法从数据里反推权重,再用TOPSIS排序,这样每一步都有数据支撑。def entropy_weight(X): # X:样本×指标矩阵,已经完成正向化 X = X / X.sum(axis=0, keepdims=True) # 归一化 n = X.shape[0] k = 1 / np.log(n) e = -k * (X * np.log(X + 1e-9)).sum(axis=0) # 信息熵 w = (1 - e) / (1 - e).sum() # 权重 return w逻辑说明:熵权法的思路是指标数据越分散,信息量越大,权重越高。X / X.sum(axis=0)按列归一化,np.log(X + 1e-9)防止log0产生负无穷。参数说明:1e-9是平滑因子,如果某列数值为0,这个加项能让计算不崩溃;正向化要在这一步之前完成,比如成本型指标取倒数或取负值。def topsis(X, w): Z = X / np.sqrt((X**2).sum(axis=0, keepdims=True)) # 向量归一化 ideal_best = Z.max(axis=0) # 正理想解 ideal_worst = Z.min(axis=0) # 负理想解 d_best = np.sqrt(((Z - ideal_best)**2).dot(w)) d_worst = np.sqrt(((Z - ideal_worst)**2).dot(w)) return d_worst / (d_best + d_worst) # 贴近度逻辑说明:TOPSIS先构造正理想解和负理想解,然后计算每个样本到两者的距离。贴近度越大说明离正理想解越近,离负理想解越远。参数说明:w是熵权法输出的权重向量,dot(w)是加权欧式距离;如果指标没统一量纲,贴近度会被数值量级大的指标主导,这也是第5章要展开的坑。4.3 优化类:线性规划与遗传算法兜底优化题的经典套路是先用线性规划求出理想解,再用启发式算法验证或改进。from scipy.optimize import linprog # 目标函数:最大化 3*x1 + 5*x2,转成最小化负值 c = [-3, -5] # 约束:x1 <= 4, 2*x2 <= 12, 3*x1 + 2*x2 <= 18 A = [[1, 0], [0, 2], [3, 2]] b = [4, 12, 18] bounds = [(0, None), (0, None)] res = linprog(c, A_ub=A, b_ub=b, bounds=bounds, method="highs") print(res.x, -res.fun)逻辑说明:linprog默认解最小化问题,所以最大化目标要加负号,res.fun加负号后才是真实最大值。A_ub和b_ub表示小于等于约束,这是线性规划的标准形式。参数说明:method="highs"是scipy 1.6以后默认的求解器,比旧的单纯形算法稳定很多;变量无上限时用None,有整数要求时得换milp,不能直接传整数约束。当约束非线性或变量离散时,线性规划解不了,就用包内optimize/ga.py的遗传算法框架。这类算法主要调三个参数:种群规模(50到200之间)、迭代次数(100到300之间)、交叉变异概率(通常0.7到0.2),跑十次取最优解。记住一个习惯:先跑线性规划拿到上界,再跑遗传算法看能不能贴近上界,如果差很多就是编码方式出了问题。5. 常见避坑与排查:从数据到提交的五个翻车现场5.1 数据与建模的翻车现场翻车点一:缺失值直接删除,预测曲线集体偏掉。现象:dropna()之后样本量少了一半,预测结果跟原始数据完全对不上。原因:Excel里的空白格被读到DataFrame里是NaN,盲目删行会把有效信息一起删掉。解决:先跑data.isna().sum()统计每列缺失量,再决定策略。数值列用df['flow'].interpolate()做线性插值,比例超过30%的列只能当参考,不进模型。翻车点二:量纲不统一,TOPSIS排序被大数支配。现象:熵权法算出的权重正常,但贴近度排序几乎只跟“价格”这一列一致。原因:价格单位是万元,其他指标是百分比或千克,向量归一化后量级大的列方差占绝对主导。解决:建模前统一计量单位,并做一次极差归一化(X - X.min(0)) / (X.max(0) - X.min(0)),让所有指标落在0到1之间再算权重。翻车点三:灰色预测外推期数设太大,曲线直接爆炸。现象:预测第10期出现几千亿的数量级。原因:GM(1,1)里的指数项会随K增大快速累加,本质只适合短期外推。解决:把K限制在样本长度的三分之一以内,论文里明确写“本模型仅作短期预测”,并给出残差检验表,证明前几个预测点的误差在可接受范围。5.2 写作与提交的翻车现场翻车点四:摘要只写研究背景,没有任何数值结果。现象:评委看完摘要不知道这篇论文解决了什么,也不知道最终预测值是多少。原因:把摘要写成了科普文,没有按“问题-模型-结果-误差”的结构组织。解决:摘要第一句就写“针对XX问题,建立XX模型,求得XX=1.23,模型平均误差为X%”,把灵敏度结论也塞进最后一句,比如“当权重在±20%内扰动时,排名保持稳定”。评委看到数字,才会接着看正文。翻车点五:论文里的数字和代码跑出来的对不上。现象:论文写“均方误差为0.12”,评委复跑是0.35;或者图表里的曲线比代码多了一段。原因:最后一天边改参数边手动截图,没有全量重跑脚本。解决:比赛期间所有文件按“题号_模型_日期.py”命名,每一次改动后强制把输出CSV和图片重新导出,论文里每个数字都必须能在某个CSV里查到。> 提示:我把这当作“后悔药”机制——宁可在最后半天重新渲染一次全部图表,也别赌评委不会复跑你的代码。6. 最后一天冲刺:灵敏度分析、模型对比与出图规范进入比赛最后一天,不要再往模型里塞新算法,把精力放在三个动作上:灵敏度分析、模型对比、出图规范化。灵敏度分析是让评委相信模型稳健的最快手段。做法是给关键参数加扰动,看排序或预测结果有没有翻转:# 对权重向量施加扰动,观察TOPSIS排名变化 for alpha in [-0.2, -0.1, 0.1, 0.2]: w2 = w + alpha * np.ones(len(w)) w2 = w2 / w2.sum() rank = topsis(X, w2) print(f"alpha={alpha:+.1f} ->", np.argsort(-rank)[:5])逻辑说明:alpha是扰动幅度,正负分别代表权重上调或下调;每次扰动后重新归一化再排序。如果前五名在四组扰动下基本不变,这段输出就能直接写进模型检验章节。参数说明:np.ones(len(w))保证所有权重同方向扰动,更精细的做法是每次只扰动一个指标,观察单一权重的敏感度。模型对比表是论文的点睛之笔。别只放最终模型的结果,把基线模型也放上去:模型平均绝对误差结论线性回归0.34趋势拟合,适合作为基线GM(1,1)0.12短期预测稳定,优于基线最后是出图规范。很多队伍算法跑得很好,图却丑得离谱。打开包内plot下的配置文件,至少要把中文字体和不支持负号的问题解决:import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] plt.rcParams['axes.unicode_minus'] = False plt.figure(dpi=300)逻辑说明:font.sans-serif指定中文字体,axes.unicode_minus让负号正常显示,不设置这两行的话,论文里会出现方框和乱码负号。参数说明:dpi=300是印刷级清晰度,插入Word时建议用PNG格式,别直接截屏。从那以后,我每次带队到最后一天,都会强制走一遍“扰动-对比-重导出”这个流程,宁可少做一个花哨模型,也要做到论文里每个数字都能追溯、每张图都敢让评委放大看。希望帮到你。本文还有配套的精品资源,点击获取