简介:这份PDF面向参加数学建模竞赛的高校学生与指导教师,围绕竞赛中最常考的预测、分类、优化、评价四大模型做系统梳理,适合作为赛前复习、题型识别与建模方案选型的参考资料。文档按模型大类分章,下设神经网络、灰色预测、时间序列、马尔科夫链、支持向量机、聚类分析、主成分分析、线性与非线性规划、遗传算法、层次分析法、熵权法等常见方法,并穿插适用条件、优缺点、应用场景与总结提示,兼具模板与素材索引属性,便于快速对照赛题定位思路。包内共1个PDF文件,压缩包约225KB,体量轻便,适合随身查阅与打印。已有801人学习,说明其在建模备赛群体中具有一定参考价值;读者可从中获得四大模型的目录框架、方法比较和选用建议,用于搭建知识索引、查漏补缺与赛前快速回顾。
1. 三个人盯着一份两年的产量数据,一个人想上神经网络,一个人想画趋势线,还有一个已经在建灰色预测
这类场面在建模竞赛里太常见了:题目给的是一张几十行的表,有人上来就MLPRegressor,训到 loss 抖成心电图;换成灰色预测,三行代码出了一条平滑曲线,但被追问“为什么用它”时答不上来。这份《数学建模竞赛常考四大模型总结》PDF 的价值,不在于推导公式,而在于把预测模型、分类模型、优化模型、评价模型四大块的适用场景、前置条件和缺点摊开写在一页目录上,让你在选题后的半小时内能定方向,而不是半小时后还在纠结用 SVM 还是决策树。它更像一份建模决策手册加代码素材库,适合刚上手竞赛、需要在有限时间里把方案落地的人,也适合带队的熟手拿来当检查清单。
2. 预测模型:先看数据长度和随机性,再决定上哪条路线
2.1 四条路线对应四类数据形态
预测模型的选型,本质上不是比谁先进,而是比谁和数据形态匹配。建模题里能拿到的数据无非四种形态,对应的路线是完全不同的。
第一种是样本极少,十来个点甚至更少,还带一点单调趋势,比如某地区近八年的某项指标。这种数据上神经网络就是纯粹的过拟合表演,灰色预测才是合理选择。第二种是等间距、有明显周期或季节波动,比如逐月用电量、逐日客流,时间序列方法里的季节分解、ARIMA 才有发挥空间。第三种是前后数据之间没有强传递关系,随机性强,只能从状态转移概率上判断下一个状态,马尔科夫链就是为此设计的。第四种是数据量足够大,特征维度也不低,这时候才轮到神经网络,以及作为基线存在的线性回归拟合。
还有一类容易被忽略:数据之间找不到直接关系,但能找到“变化量”之间的关系,比如某浓度随时间的变化率与另一个变量成正比,这时候微分方程建模比任何统计模型都自然。PDF 里把这一条单独列出来,是很实用的提醒——很多人一看到“预测”两个字就往回归和神经网络上想,忘了变化率关系也是一条路。
选型上我一般的判断顺序是:先看样本量,再看是否等间距,再看随机性,最后才看维度。顺序反了,就容易出现拿神经网络去拟合十二个数据点这种操作。
2.2 灰色 GM(1,1):级比检验与后验差比怎么过
灰色预测被吐槽“理论性不强、没法论证”是有道理的,它的假设很弱,本质上是拿一条指数曲线去逼近累加序列。但它有一个别人比不了的优势:样本少也能出结果。用它之前有两道关必须过,第一道叫级比检验,第二道叫后验差比检验,很多代码素材直接跳过这两步只给一条曲线,评审一问精度就露馅。
import numpy as np def gm11(x0): x0 = np.asarray(x0, dtype=float) n = len(x0) # 1. 级比检验:lambda(k)=x0(k-1)/x0(k) 应落在可容覆盖区间内 lam = x0[:-1] / x0[1:] lo, hi = np.exp(-2 / (n + 1)), np.exp(2 / (n + 1)) if not ((lam > lo) & (lam < hi)).all(): print("级比检验未通过,需先做平移变换再试") # 2. 一次累加生成,弱化随机性 x1 = np.cumsum(x0) # 3. 紧邻均值序列,构造背景值 z1 = 0.5 * (x1[:-1] + x1[1:]) # 4. 最小二乘估计发展系数 a 与灰作用量 b B = np.column_stack([-z1, np.ones(n - 1)]) Y = x0[1:] a, b = np.linalg.lstsq(B, Y, rcond=None)[0] # 5. 时间响应式还原为原始序列 k = np.arange(n) x1_hat = (x0[0] - b / a) * np.exp(-a * k) + b / a x0_hat = np.concatenate([[x1_hat[0]], np.diff(x1_hat)]) # 6. 后验差比 C 与小误差概率 P,C 越小、P 越大越好 resid = x0 - x0_hat C = resid.std(ddof=0) / x0.std(ddof=0) P = (np.abs(resid - resid.mean()) < 0.6745 * x0.std(ddof=0)).mean() return x0_hat, a, b, C, P这段代码里有几个参数值得单独说。a是发展系数,它的绝对值大小直接决定预测能不能外推——经验上 |a| 小于 0.3 时中长期预测才勉强可信,超过 0.5 就只能报一步。b是灰作用量,反映背景值的整体水平,对结果的影响没那么敏感。C是后验差比,小于 0.35 算一级精度,0.35 到 0.5 算二级,超过 0.65 基本不用往论文里放。P是小误差概率,一般要求大于 0.8。
级比检验没过怎么办?常见做法是对原始序列先做平移,加一个常数让所有值远离零,再做累加,或者直接换方法。血泪经验是:平移常数别拍脑袋,多试几个值看 C 有没有明显下降,不然就是“数字好看了、结论还是虚的”。
2.3 神经网络的超参数必须交代清楚的四件事
PDF 里对神经网络预测的要求写得很具体:输入输出是什么、迭代次数和学习率、网络层数与每层节点数为什么这么设、评价指标怎么算。这四条说白了就是评审看论文时会追问的四句话,缺一句都显得方案没落地。
from sklearn.neural_network import MLPRegressor from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # X: 特征矩阵, y: 目标序列(时间顺序不能打乱) scaler = StandardScaler() Xs = scaler.fit_transform(X) # 时序数据不要 shuffle,最后 20% 留作测试 X_tr, X_te, y_tr, y_te = train_test_split(Xs, y, test_size=0.2, random_state=42, shuffle=False) net = MLPRegressor( hidden_layer_sizes=(32, 16), # 两层,节点数按特征维度约 2~4 倍取 activation="relu", solver="adam", learning_rate_init=1e-3, # 初始学习率,太大震荡太小爬得慢 max_iter=2000, # 迭代上限,配合早停实际用的远小于此 early_stopping=True, # 从训练集里再切 10% 做验证,防过拟合 validation_fraction=0.1, random_state=42, ) net.fit(X_tr, y_tr) pred = net.predict(X_te) print("MSE:", mean_squared_error(y_te, pred)) print("R2:", r2_score(y_te, pred)) print("最近五轮 loss:", net.loss_curve_[-5:])层数和节点数没有普适答案,但有一个能讲清楚的理由链:输入特征有 m 个,第一层取 2m 到 4m 之间,第二层取第一层的一半,任务简单就砍掉第二层。这样写进论文,比“经过多次实验确定为 32 和 16”要有说服力得多。学习率 1e-3 是 Adam 的默认值,数据量小的时候可以降到 1e-4 观察收敛曲线。
评价指标别只报准确率。回归任务看 MSE 和 R²,分类任务看混淆矩阵、精确率召回率 F1,另外补一个稳定性指标,比如重复五次随机初始化后 R² 的方差。神经网络没有显式数学模型,评审只能通过这些数字判断你训出来的东西靠不靠谱,指标给全了,可信度自然上去。
还有一个常被忽略的点:PDF 里明确写了,题目给了大量数据时,即使没要求也要做数据清洗。异常值和缺失值不能简单删行,删完样本量掉一半,评审一眼就看出偷懒。合理的做法是用插值补缺、用箱线图或 3σ 标记异常点并单独说明处理策略。
2.4 拟合与插值的分工
拟合和插值经常被混为一谈,其实目标完全不同。拟合是找一条已知形式、未知参数的曲线,让它整体上尽量逼近所有点,允许不穿过任何一个点;插值是必须穿过所有已知点,在两个点之间构造分段光滑的曲线。前者用于找规律和预测,后者用于补数据。
| 对比项 | 拟合 | 插值 |
|---|---|---|
| 是否穿过样本点 | 不要求 | 必须穿过 |
| 典型方法 | 最小二乘多项式、指数拟合 | 线性插值、三次样条、拉格朗日 |
| 适用场景 | 预测趋势、参数估计 | 缺失值填补、加密采样点 |
| 主要风险 | 多项式阶数过高导致龙格现象 | 外推能力极差,出边界就失真 |
PDF 里那句“数据缺失用插值,最好不用插值做预测”说得很到位。三次样条在样本区间内很稳,一旦外推就开始放飞,拿它做预测是典型的翻车现场。反过来,拟合用来补缺失值也不合适,因为拟合曲线不穿过原始点,会把真实观测值改掉。
3. 分类与聚类:监督的找边界,无监督的找距离
3.1 SVM 与逻辑回归的边界条件
逻辑回归和 SVM 都能做二分类,但它们的适用条件差得挺远。逻辑回归的硬性要求是:样本数至少是自变量个数的三倍以上,自变量之间相关性要低,因变量是定类数据。三条里破一条结果就会很难看,尤其是自变量高度相关的时候,系数符号会变得莫名其妙。
SVM 的思路是找最大间隔超平面,优点是高维数据也能处理、泛化能力好、占用内存小;缺点是样本量一大效率就掉,核函数和参数的选择比较敏感,原始形式只擅长二分类。PDF 里提到“观测样本很多时效率不高”和“核函数难选”这两条,实际做的时候有对应的解法。
from sklearn.svm import SVC from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.model_selection import GridSearchCV pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC(probability=True))]) param = { "svm__kernel": ["rbf", "linear"], "svm__C": [0.1, 1, 10, 100], # 惩罚系数,越大越不容忍错分 "svm__gamma": ["scale", 0.01, 0.1] # RBF 核的宽度,越大边界越曲折 } gs = GridSearchCV(pipe, param, cv=5, scoring="f1_macro", n_jobs=-1) gs.fit(X, y) print(gs.best_params_, gs.best_score_)C和gamma的配合是 SVM 调参里最玄学的部分:C大、gamma大,模型贴着训练数据走,训练集百分百、测试集崩盘;C小、gamma小,模型欠拟合,两类都分不开。经验做法是先在gamma上做粗网格,再在最优值附近细化C。另外标准化不能省,SVM 对量纲敏感,不标准化等于让数值大的特征单方面决定边界。
当逻辑回归效果很差、被判定为欠拟合时,PDF 给的两条路都很实用:换决策树,适合少量样本多维特征的场景,天然不怕欠拟合;或者先降维再用逻辑回归,把相关性高的自变量压掉。反过来,样本量很大、特征维度适中,逻辑回归的可解释性优势就体现出来了,系数符号能直接写进论文解释影响方向。
3.2 k-means 定簇、FCM 细化的两段式
聚类这块,PDF 里那句“先用一种聚类得到中心点,然后用 FCM”是整节最值钱的一句话。原因在于两种算法各有硬伤:k-means 收敛快、对异常值不敏感、准确度不错,但初始点随机,每次跑结果不一样,K 值还得人为定;FCM 允许一个样本以不同隶属度属于多个类,对满足正态分布的数据效果好,但它对初始聚类中心极其敏感,容易陷在局部最优里,而且比 k-means 慢。
把两者串起来的做法是:第一段用 k-means 扫一遍 K,用轮廓系数挑出最合理的簇数和中心点;第二段把中心点作为 FCM 的初始值,只做隶属度细化。
from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score import numpy as np # 第一段:k-means 扫 K,轮廓系数定簇数 best = None for k in range(2, 9): km = KMeans(n_clusters=k, n_init=10, random_state=42).fit(Xs) s = silhouette_score(Xs, km.labels_) if best is None or s > best[1]: best = (k, s, km.cluster_centers_) k_best, s_best, centers = best print("最优簇数", k_best, "轮廓系数", round(s_best, 3)) # 第二段:以 centers 为初值跑 FCM,m 为模糊指数,一般取 1.5~2.5 def fcm(X, centers, m=2.0, tol=1e-5, max_iter=200): c = len(centers) U = np.random.rand(len(X), c) U = U / U.sum(axis=1, keepdims=True) for _ in range(max_iter): U_old = U.copy() d2 = ((X[:, None, :] - centers[None, :, :]) ** 2).sum(axis=2) + 1e-12 U = (1 / d2) ** (1 / (m - 1)) U = U / U.sum(axis=1, keepdims=True) centers = (U ** m).T @ X / (U ** m).sum(axis=0)[:, None] if np.abs(U - U_old).max() < tol: break return U, centersn_init=10是 k-means 重复随机初始化的次数,取十次里最好的那次,能明显缓解结果不稳定的问题。m是模糊指数,越大隶属度越模糊,1.5 到 2.5 之间是常用区间,具体取多少看论文里要不要强调“某样本同时具备两类特征”。FCM 的收敛判据用隶属度矩阵的变化量,tol设 1e-5 足够了。
层次聚类在这里的角色不太一样。它不需要预设簇数,可解释性好,遇到非球形簇也能处理,但时间复杂度高,而且是贪心合并,一步错步步错,合错了没法回退。所以它更适合做探索性分析、画一张树状图说明“为什么分成这几类”,而不是作为最终分类结果的唯一依据。
3.3 PCA 降维的三个前置条件
主成分分析被滥用得最厉害。PDF 里列了三条要求:数据线性相关、所有变量是连续型、尽量服从正态分布。三条同时满足才推荐用,只满足一条两条就硬上,主成分的经济含义会变得完全没法解释。
from sklearn.decomposition import PCA import numpy as np pca = PCA().fit(Xs) cum = np.cumsum(pca.explained_variance_ratio_) k = int(np.searchsorted(cum, 0.85) + 1) # 累计方差贡献率达到 85% 的主成分个数 print("各主成分贡献率:", np.round(pca.explained_variance_ratio_, 3)) print("取前", k, "个,累计", round(cum[k - 1], 3))85% 这个阈值是常见约定,不是硬标准,社会科学类数据有时降到 70% 也能接受,关键要在论文里写清楚为什么选这个数。另外 PCA 之前的标准化不能省,不标准化的话,量纲大的变量会独占第一主成分,降维结果基本等于“把最大的那列留下来”。
还有一种用法容易被忽视:PCA 不只是降维工具,也可以直接当评价模型用,先降维再按方差贡献率加权求和算综合得分。这属于评价模型的范畴,后面会提到。
3.4 聚类结果怎么在论文里自证
聚类是无监督的,没有标签可以算准确率,所以“结果对不对”这个问题必须靠别的证据。常见做法有三类:轮廓系数看簇内紧、簇间散;可视化降维到二维后看簇的分离程度;以及业务解释,把每个簇的中心点还原成原始量纲,说清楚这一簇有什么共同特征。
PDF 里四种聚类算法的对比结论可以直接借来用:运行时间和准确度综合考虑,k-means 和 FCM 相对更优;k-means 的初始点不稳定,需要多次实验取平均;层次聚类一旦分裂或合并就不可修正;FCM 对初始中心敏感、需要人为定簇数。把这几条写进“模型优缺点”小节,比空泛地说“本算法效果好”可信得多。
4. 优化模型:目标函数写对,算法只是加速器
4.1 规划类模型:从变量表到约束表
规划模型的家族很整齐:线性规划、非线性规划、整数规划、目标规划、动态规划。前四个的建模套路几乎一样,先列决策变量,再写目标函数,再写约束,最后确定变量取值范围。区别只在目标函数和约束是不是线性的、变量要不要取整。
动态规划是另一套思路,它解决的是多阶段决策问题,把一个大问题拆成按时间或阶段排列的子问题,每步存下最优值,最后回溯。最短路径、切割下料损耗最小这类题用它最自然。它的难点不在代码,在状态定义和状态转移方程,这两样写不对,代码再漂亮也跑不出正确结果。
import numpy as np from scipy.optimize import linprog # 目标:min c^T x c = np.array([3, 5, 2, 7]) # 不等式约束 A_ub x <= b_ub A_ub = np.array([[1, 2, 1, 0], [0, 1, 3, 2]]) b_ub = np.array([10, 12]) # 等式约束 A_eq x = b_eq,没有就传 None A_eq = None b_eq = None # 变量上下界,整数规划需额外指定 integrality bounds = [(0, None)] * 4 res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method="highs") print(res.status, res.fun, res.x)method="highs"是当前比较稳的内点加单纯形混合求解器,比默认的老方法快不少。status为 0 表示找到最优解,为 2 表示不可行,为 3 表示无界,排错时先看这个字段再看结果。如果题目要求变量取整,scipy需要改用milp,或者交给专门的建模库,别指望linprog自动帮你取整。
提示:约束写完之后一定回头检查一次“这个约束在物理上说得通吗”。做过一道资源分配题,约束里漏了“每个任务必须被分配”,求解器给出的最优解是“什么都不做,成本为零”,目标函数漂亮得离谱。
4.2 遗传算法与模拟退火的参数怎么定
现代优化算法解决的是目标函数不连续、不可导、或者解空间离散的问题。遗传算法、模拟退火、禁忌搜索、蚁群算法是 PDF 里列的四类,用法上有相似之处:都要先定义解的编码方式和适应度函数,再定搜索策略。
遗传算法的参数里,种群规模一般取 20 到 100,交叉概率 0.6 到 0.9,变异概率 0.01 到 0.1。种群太小早熟收敛,太大算得慢;变异概率太小跳不出局部最优,太大就退化成随机搜索。模拟退火的关键参数是初温、降温系数和每个温度下的迭代次数,初温要保证初始阶段劣解被接受的概率接近 1,降温系数常见 0.9 到 0.99,降太快会卡住,降太慢跑不完。
| 算法 | 关键参数 | 常见取值 | 调参方向 |
|---|---|---|---|
| 遗传算法 | 种群规模 | 20~100 | 目标函数评估贵就取小 |
| 遗传算法 | 交叉概率 | 0.6~0.9 | 解空间大适当调高 |
| 遗传算法 | 变异概率 | 0.01~0.1 | 早熟收敛时调高 |
| 模拟退火 | 初始温度 | 使初始接受率接近 1 | 按目标函数量级反推 |
| 模拟退火 | 降温系数 | 0.90~0.99 | 时间够就取大 |
| 模拟退火 | 链长 | 50~200 | 变量维度高时加长 |
禁忌搜索的核心是禁忌表和藐视准则,禁忌长度一般取 5 到 20,太短容易循环,太长搜索受限。蚁群算法的关键参数是信息素挥发系数和启发因子,挥发系数 0.1 到 0.5 之间比较稳,挥发太快信息积累不起来,太慢又容易困在早期路径上。
这里必须说一句实话:这些参数没有一组放之四海皆准的值,论文里写“经过多次实验确定”是可以的,但最好附一张参数敏感性表,比如变异概率取 0.01、0.05、0.1 三档对应的最优值,让评审看到你是试出来的,不是抄来的。
4.3 热启动:用上一个最优解省掉一半算力
PDF 里那句关于“找到最优解之后与其他函数形式比较”的建议非常实用:既然已经在某个函数形式下找到了一组较优参数,换另一种函数形式或者换算法时,就没必要从头开始随机搜索,可以直接把上一步的解当成初始点,甚至把搜索范围收缩到它附近。
import numpy as np from scipy.optimize import minimize # 第一步:用遗传算法或差分进化做全局搜索,得到 x_best、f_best # 第二步:换成局部优化器,初始点取 x_best,搜索域收缩到 ±10% lo = np.maximum(x_best * 0.9, 0) # 变量非负时的下界 hi = x_best * 1.1 + 1e-6 res = minimize(fun, x_best, method="SLSQP", bounds=list(zip(lo, hi)), constraints=cons, options={"maxiter": 500, "ftol": 1e-8}) print(res.fun, res.x, res.success)这样做的好处很直接:全局算法负责跳出局部最优,局部算法负责在最优附近精修,两步的总耗时通常比单纯用全局算法跑到收敛少一半以上。SLSQP适合有约束的连续问题,ftol控制函数值的变化容差,maxiter给个上限兜底。如果第一次的解本身就不理想,缩小范围反而会把正确解排除在外,所以收缩比例别设太狠,10% 到 20% 是比较稳的区间。
另一个常被忽略的细节是:不同函数形式的结果比较,重点不是比谁的残差小,而是比哪个形式在物理意义上更站得住。拟合优度可以靠加参数堆出来,评审看的是你为什么选这个形式。
5. 避坑:五个最容易翻车的现场
5.1 数据预处理阶段
现象一:插值补完缺失值,后续模型精度不升反降。原因:三次样条在样本稀疏的区段会剧烈摆动,补出来的值偏差很大,而且插值点被当成真实观测参与了训练。 解决:缺失比例低于 5% 且缺失点附近有密集观测时用线性插值;缺失比例高或者缺失点位于序列两端时,改用拟合或者直接把该特征剔除。补值之后单独做一次分布对比,看补出来的数据和原始数据是不是一个量级。
现象二:标准化做完,聚类结果和之前一模一样。原因:StandardScaler是对每一列减均值除标准差,如果某一列本身方差极小,标准化后会被放大成噪声主导;反过来,如果所有列量纲本来就接近,标准化前后结果差别不大是正常的。 解决:先看各列的量纲和取值范围,量纲差异大的才需要标准化。PCA 和 SVM 之前必须标准化,树模型不需要。做完之后打印各列的标准差,确认没有接近零的列混进去。
5.2 模型调用阶段
现象三:k-means 每次跑出来的簇都不一样,论文里的结论没法复现。原因:初始中心随机选取,算法只保证局部最优。 解决:固定random_state,把n_init提到 10 以上,跑五次记录轮廓系数,取最好的一次写进论文,同时把五次结果的波动范围也报出来。如果波动很大,说明数据本身簇结构不明显,这时候换层次聚类或者先降维再聚类更合适。
现象四:神经网络训练集 R² 到 0.99,测试集只有 0.4。原因:层数和节点数相对样本量太大,或者训练轮数过多,模型把噪声也学进去了。 解决:先把网络砍小,两层降到一层,节点数减半;打开early_stopping,让它自己决定什么时候停;样本量小于五百的时候,老老实实回到线性回归或者灰色预测,别硬上神经网络。还有一个容易忽略的点是时序数据切分时shuffle=True,等于把未来信息泄露给了训练集,指标虚高得离谱。
5.3 结果输出阶段
现象五:评价模型算出来的排名和常识完全相反。原因:指标方向没统一,有的指标越大越好,有的越小越好,直接丢进矩阵算权重,等于把好坏颠倒了。 解决:进模型之前先做正向化,成本型指标取倒数或者用最大值减,然后统一做 min-max 标准化。标准化之后检查一遍每个指标的单调方向,确认“数值大”和“评价好”是一致的。这一步在熵权法里尤其关键,方向错了权重会全部分配到不重要的指标上。
6. 评价模型:熵权定权、模糊合成,再用灰色关联复核
评价模型这块,PDF 的建议是先上模糊综合评价,再用别的方法佐证。我一般把熵权法和模糊综合评价串起来用:熵权法负责定权重,不掺主观判断;模糊综合评价负责处理“好、较好、一般”这种边界不清的等级;最后用灰色关联度排一遍序,看两个结果的相关性,一致性高就敢往论文里写。
熵权法的逻辑很直白:某个指标在各样本间差异越大,说明它携带的信息越多,权重就该越高。反过来,所有样本在该指标上几乎一样,那它对区分优劣没有贡献,权重自然低。
import numpy as np def entropy_weight(X): X = np.asarray(X, dtype=float) # 假设 X 已完成正向化和 min-max 标准化,加小量避免 log(0) Z = X + 1e-6 P = Z / Z.sum(axis=0) # 每个指标下各样本的比重 e = -(P * np.log(P)).sum(axis=0) / np.log(len(X)) # 信息熵 d = 1 - e # 信息效用值 return d / d.sum() # 归一化得到权重 # 模糊综合评价:W 为权重向量,R 为隶属度矩阵(行是指标,列是等级) B = W @ R level = np.argmax(B) # 最大隶属度原则定等级W的维度要和R的行数对上,这是最容易出错的地方,指标从五个加到六个,权重向量忘了改就会报维度错。隶属度矩阵R一般用分段线性函数或者专家打分构造,前者可复现,后者可解释,论文里选一种写清楚就行。
熵权法有一个明确的局限:它只看数据本身的离散程度,不考虑指标的实际意义,所以完全可能出现“某个不重要的指标因为样本间波动大而拿到高权重”的情况。这也是为什么需要灰色关联做复核——关联度排序和熵权排序如果高度一致,说明结论稳;如果不一致,就得回头查指标选取和数据处理,而不是硬选一个结果写上去。
这套组合我踩过一次坑:第一版忘了把成本型指标正向化,熵权法把权重最大的给了“污染指数”这个越小越好的指标,排名出来污染最重的地方被评为最优。从那以后我每次跑评价模型,都强制先打印一张指标方向表,逐条确认“数值大等于评价好”,再往下走。希望这个习惯也能帮到你。
本文还有配套的精品资源,点击获取