总览类别常见模型主要作用数模常用度主观赋权AHP 层次分析法根据专家判断确定权重★★★★★客观赋权熵权法根据数据差异程度定权★★★★★客观赋权CRITIC根据变异性指标冲突性定权★★★★☆客观赋权变异系数法根据相对离散程度定权★★★☆☆组合赋权AHP-熵权、博弈论组合赋权综合主客观权重★★★★☆综合排序TOPSIS离理想方案越近越好★★★★★模糊评价模糊综合评价处理“优、良、中、差”等模糊评价★★★★★灰色评价灰色关联分析小样本、不完全信息下比较接近程度★★★★☆效率评价DEA 数据包络分析多投入、多产出下比较相对效率★★★★☆综合评价PCA 主成分综合评价降维后构造综合得分★★★★☆秩次评价RSR 秩和比法根据秩次进行综合评价和分档★★★☆☆折中决策VIKOR在“整体最好”和“最差短板”之间折中★★★☆☆多属性决策ELECTRE通过“优于关系”比较方案★★★☆☆多属性决策PROMETHEE基于偏好函数进行方案排序★★★☆☆云模型评价正态云模型同时处理随机性与模糊性★★★☆☆AHP层次分析一致性检验的含义用于确定构建的判断矩阵是否存在逻辑问题1构造判断矩阵2层次单排序根据我们构成的判断矩阵求解各个指标的权重有三种方式一种是方根法一种是和法一重特征值方根法一行所有数乘一起开根号标准化和法特征值法直接求最大特征值对应的特征向量并归一化就是最后要的权重结果3求解最大特征根与CI值判断 判断矩阵是不是正确的AW为判断矩阵*标准化后的权重然后按按行的累加值直接特征值法真正把所有特征值算出来取最大的C.I.越大判断矩阵的不一致性程度越严重Satty 模拟 1000 次得到的随机一致性指标 R.I.取值表如下表 所示当 C.R.0.1 时表明判断矩阵 A 的一致性程度被认为在容许的范围内4层次总排序只使用 NumPy 实现 AHP 层次分析法。 import numpy as np # Saaty 随机一致性指标索引表示判断矩阵阶数 n。 RI_TABLE { 1: 0.00, 2: 0.00, 3: 0.58, 4: 0.90, 5: 1.12, 6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45, 10: 1.49, 11: 1.51, 12: 1.48, 13: 1.56, 14: 1.57, 15: 1.59, } def validate_judgment_matrix(matrix, tolerance1e-8): 检查判断矩阵是否为正互反方阵。 matrix np.asarray(matrix, dtypefloat) if matrix.ndim ! 2 or matrix.shape[0] ! matrix.shape[1]: raise ValueError(判断矩阵必须是方阵) if np.any(matrix 0): raise ValueError(判断矩阵中的元素必须大于 0) if not np.allclose(np.diag(matrix), 1.0, atoltolerance): raise ValueError(判断矩阵的对角线元素必须为 1) if not np.allclose(matrix * matrix.T, 1.0, atoltolerance): raise ValueError(判断矩阵必须满足 a[i,j] * a[j,i] 1) return matrix def ahp_weights(matrix): 使用最大特征值法计算权重并进行一致性检验。 matrix validate_judgment_matrix(matrix) n matrix.shape[0] eigenvalues, eigenvectors np.linalg.eig(matrix)# 计算特征值和特征向量 max_index np.argmax(eigenvalues.real)# 获取最大特征值的索引 lambda_max float(eigenvalues[max_index].real)# 获取最大特征值 principal_vector np.abs(eigenvectors[:, max_index].real)# 获取对应的特征向量并取绝对值 weights principal_vector / principal_vector.sum()# 归一化特征向量得到权重 # 一致性指标 CI 和一致性比率 CR if n 2: ci 0.0 cr 0.0 else: ci (lambda_max - n) / (n - 1)# 计算一致性指标 CI if n not in RI_TABLE: raise ValueError(当前 RI 表仅支持 115 阶判断矩阵) cr ci / RI_TABLE[n]# 计算一致性比率 CR return { weights: weights, lambda_max: lambda_max, ci: float(ci), cr: float(cr), passed: bool(cr 0.10),# 一致性检验通过的条件是 CR 0.10 } def print_result(title, names, result): 输出一组权重及其一致性检验结果。 print(f\n{title}) for name, weight in zip(names, result[weights]): print(f {name:8}: {weight:.4f}) print(f lambda_max {result[lambda_max]:.6f}) print(f CI {result[ci]:.6f}) print(f CR {result[cr]:.6f}) print( 一致性检验, 通过 if result[passed] else 未通过) def main(): # 目标层选择最佳供应商。 criteria [产品质量, 采购价格, 交付能力, 售后服务] alternatives [供应商A, 供应商B, 供应商C] # 准则层判断矩阵质量、价格、交付、服务两两比较。 criteria_matrix np.array( [ [1, 3, 5, 4],#1-9行对于列越来越重要 [1/3, 1, 2, 2],#倒数列对于行重要 [1/5, 1/2, 1, 1/2], [1/4, 1/2, 2, 1], ], dtypefloat, ) # 方案层判断矩阵分别在每项准则下比较三个供应商。 alternative_matrices { 产品质量: np.array( [[1, 3, 5], [1/3, 1, 2], [1/5, 1/2, 1]], dtypefloat ), 采购价格: np.array( [[1, 1/2, 1/4], [2, 1, 1/3], [4, 3, 1]], dtypefloat ), 交付能力: np.array( [[1, 2, 1/2], [1/2, 1, 1/3], [2, 3, 1]], dtypefloat ), 售后服务: np.array( [[1, 1/3, 2], [3, 1, 5], [1/2, 1/5, 1]], dtypefloat ), } criteria_result ahp_weights(criteria_matrix) print_result(准则层权重, criteria, criteria_result) local_weight_columns [] all_passed criteria_result[passed] for criterion in criteria: result ahp_weights(alternative_matrices[criterion]) print_result(f方案层权重——{criterion}, alternatives, result) local_weight_columns.append(result[weights]) all_passed all_passed and result[passed] # 每列对应一个准则每行对应一个供应商。 local_weights np.column_stack(local_weight_columns) total_scores local_weights criteria_result[weights] ranking np.argsort(total_scores)[::-1] print(\n综合得分与排序) for rank, index in enumerate(ranking, start1): print(f 第 {rank} 名{alternatives[index]}得分 {total_scores[index]:.4f}) if not all_passed: print(\n警告存在未通过一致性检验的判断矩阵应重新调整比较值。) if __name__ __main__: main()(base) PS D:\桌面\华为杯\code d:/Users/anaconda3/python.exe d:/桌面/华为杯/code/评价类/ahp.py 准则层权重 产品质量 : 0.5498 采购价格 : 0.2143 交付能力 : 0.0942 售后服务 : 0.1417 lambda_max 4.056585 CI 0.018862 CR 0.020958 一致性检验 通过 方案层权重——产品质量 供应商A : 0.6483 供应商B : 0.2297 供应商C : 0.1220 lambda_max 3.003695 CI 0.001847 CR 0.003185 一致性检验 通过 方案层权重——采购价格 供应商A : 0.1365 供应商B : 0.2385 供应商C : 0.6250 lambda_max 3.018295 CI 0.009147 CR 0.015771 一致性检验 通过 方案层权重——交付能力 供应商A : 0.2970 供应商B : 0.1634 供应商C : 0.5396 lambda_max 3.009203 CI 0.004601 CR 0.007933 一致性检验 通过 方案层权重——售后服务 供应商A : 0.2297 供应商B : 0.6483 供应商C : 0.1220 lambda_max 3.003695 CI 0.001847 CR 0.003185 一致性检验 通过 综合得分与排序 第 1 名供应商A得分 0.4462 第 2 名供应商B得分 0.2846 第 3 名供应商C得分 0.2692TOPSIS逼近理想解排序法有多个评价对象每个对象有多个指标我到底怎么综合这些指标给对象排个名最优方案 距离最好方案最近 距离最差方案最远开始↓输入决策矩阵、权重和指标类型↓检查决策矩阵和权重是否合法↓将权重归一化↓对不同类型的指标进行正向化处理├─ 效益型指标保持不变├─ 成本型指标最大值减去原值├─ 目标型指标计算与目标值的接近程度└─ 区间型指标计算与最优区间的接近程度↓对正向化指标矩阵进行标准化处理↓标准化指标矩阵乘以指标权重↓确定正理想解和负理想解↓计算各方案到正理想解的距离↓计算各方案到负理想解的距离↓计算各方案的 TOPSIS 综合得分↓按照综合得分从高到低排序↓输出各方案得分和排名↓结束越接近1越好使用 NumPy 实现 TOPSIS逼近理想解排序法。 支持四类指标 1. benefit效益型数值越大越好 2. cost成本型数值越小越好 3. target目标型越接近给定目标值越好 4. interval区间型落在给定区间内最好。 from dataclasses import dataclass from typing import Optional, Sequence, Tuple import numpy as np dataclass(frozenTrue) class TopsisResult: 保存 TOPSIS 的主要中间结果和最终排序。 scores: np.ndarray ranking: np.ndarray normalized_matrix: np.ndarray weighted_matrix: np.ndarray positive_ideal: np.ndarray negative_ideal: np.ndarray distance_to_positive: np.ndarray distance_to_negative: np.ndarray def _convert_to_benefit( matrix: np.ndarray, indicator_types: Sequence[str], targets: Optional[Sequence[Optional[float]]], intervals: Optional[Sequence[Optional[Tuple[float, float]]]], ) - np.ndarray: 把各种指标统一转换为“越大越好”的形式。 converted matrix.astype(float, copyTrue) n_indicators matrix.shape[1] targets [None] * n_indicators if targets is None else list(targets) intervals [None] * n_indicators if intervals is None else list(intervals) if len(indicator_types) ! n_indicators: raise ValueError(indicator_types 的长度必须等于指标个数) if len(targets) ! n_indicators or len(intervals) ! n_indicators: raise ValueError(targets 和 intervals 的长度必须等于指标个数) for j, kind in enumerate(indicator_types): kind kind.lower() column matrix[:, j] if kind benefit: continue if kind cost: # 用“列最大值减原值”正向化避免使用倒数时遇到零。 converted[:, j] np.max(column) - column elif kind target: if targets[j] is None: raise ValueError(f第 {j 1} 个目标型指标缺少目标值) deviation np.abs(column - float(targets[j])) max_deviation np.max(deviation) converted[:, j] ( np.ones_like(column) if max_deviation 0 else max_deviation - deviation ) elif kind interval: if intervals[j] is None: raise ValueError(f第 {j 1} 个区间型指标缺少最优区间) lower, upper intervals[j] if lower upper: raise ValueError(f第 {j 1} 个指标的区间下限不能大于上限) deviation np.where( column lower, lower - column, np.where(column upper, column - upper, 0.0), ) max_deviation np.max(deviation) converted[:, j] ( np.ones_like(column) if max_deviation 0 else max_deviation - deviation ) else: raise ValueError( f未知指标类型 {kind!r}应为 benefit、cost、target 或 interval ) return converted def topsis( decision_matrix: Sequence[Sequence[float]], weights: Sequence[float], indicator_types: Sequence[str], *, targets: Optional[Sequence[Optional[float]]] None, intervals: Optional[Sequence[Optional[Tuple[float, float]]]] None, ) - TopsisResult: 计算各方案的 TOPSIS 得分并返回由优到劣的排序。 参数 decision_matrix: 决策矩阵每行是一个方案每列是一个指标。 weights: 各指标权重函数内部会自动归一化使权重之和为 1。 indicator_types: 每列的指标类型。 targets: 目标型指标的目标值其他位置填 None。 intervals: 区间型指标的最优区间其他位置填 None。 matrix np.asarray(decision_matrix, dtypefloat) weight_array np.asarray(weights, dtypefloat) if matrix.ndim ! 2 or matrix.shape[0] 2 or matrix.shape[1] 1: raise ValueError(决策矩阵必须是至少包含 2 个方案的二维矩阵) if not np.all(np.isfinite(matrix)): raise ValueError(决策矩阵不能包含 NaN 或无穷大) if weight_array.ndim ! 1 or len(weight_array) ! matrix.shape[1]: raise ValueError(weights 的长度必须等于指标个数) if not np.all(np.isfinite(weight_array)) or np.any(weight_array 0): raise ValueError(权重必须是有限的非负数) if np.sum(weight_array) 0: raise ValueError(权重之和必须大于 0) weight_array weight_array / np.sum(weight_array)# 归一化权重使其和为 1 benefit_matrix _convert_to_benefit(# 指标正向化越大越好 matrix, indicator_types, targets, intervals ) # 向量归一化消除不同指标量纲的影响。 column_norms np.sqrt(np.sum(benefit_matrix**2, axis0)) # 全零列说明该指标下所有方案表现相同不应影响方案间距离。 zero_columns column_norms 0 if np.any(zero_columns): benefit_matrix[:, zero_columns] 1.0# 统一赋值为 1避免除以零 column_norms[zero_columns] np.sqrt(matrix.shape[0]) normalized benefit_matrix / column_norms# 归一化指标矩阵 weighted normalized * weight_array#权重越大的指标对最终距离和综合得分的影响越大 # 所有指标已经正向化因此最大值为正理想解最小值为负理想解 positive_ideal np.max(weighted, axis0) negative_ideal np.min(weighted, axis0) distance_positive np.linalg.norm(weighted - positive_ideal, axis1) distance_negative np.linalg.norm(weighted - negative_ideal, axis1) denominator distance_positive distance_negative # 计算c分母为0则说明所有方案完全相同则没有优劣之分统一记为 0.5。 scores np.divide( distance_negative, denominator, outnp.full_like(denominator, 0.5), wheredenominator ! 0, ) #kindstable 表示使用稳定排序。当两个方案得分相同时保持它们原来的先后顺序。 ranking np.argsort(-scores, kindstable) return TopsisResult( scoresscores, rankingranking, normalized_matrixnormalized, weighted_matrixweighted, positive_idealpositive_ideal, negative_idealnegative_ideal, distance_to_positivedistance_positive, distance_to_negativedistance_negative, ) def main() - None: 运行一个供应商综合评价示例。 alternatives [供应商 A, 供应商 B, 供应商 C, 供应商 D] criteria [产品质量, 采购价格, 交付准时率, 售后响应时间] # 行对应供应商列依次对应上面的四个指标。 decision_matrix np.array( [ [92, 108, 96, 3.0], [88, 100, 91, 2.0], [95, 115, 98, 4.0], [90, 105, 94, 2.5], ], dtypefloat, ) weights [0.35, 0.25, 0.25, 0.15]#这个权重是根据AHP计算出来的表示每个指标的重要性 indicator_types [benefit, cost, benefit, cost] result topsis(decision_matrix, weights, indicator_types) print(指标, 、.join(criteria)) print(\nTOPSIS 得分与排名) for rank, index in enumerate(result.ranking, start1): print(f 第 {rank} 名{alternatives[index]}得分 {result.scores[index]:.4f}) if __name__ __main__: main()(base) PS D:\桌面\华为杯\code d:/Users/anaconda3/python.exe d:/桌面/华为杯/code/评价类/topsis.py 指标 产品质量、采购价格、交付准时率、售后响应时间 TOPSIS 得分与排名 第 1 名供应商 B得分 0.9321 第 2 名供应商 D得分 0.6838 第 3 名供应商 A得分 0.4757 第 4 名供应商 C得分 0.0679熵权法Entropy Weight Method, EWM熵权法是一种客观赋权法避免了人为因素带来的偏差。越可能发生的事信息熵越大信息量越少权值也越低。信息熵本质上就是对信息量的期望。熵越大差异越小信息量越小发生概率越大。标准化去除量纲影响效益型指标成本性指标4、差异系数或信息效用值。信息熵越大信息效用值越小。信息熵越小信息效用值越大。信息效用值越大指标权重越高。5、6、使用 NumPy 实现熵权法Entropy Weight Method。 熵权法根据指标数据的差异程度客观确定权重指标差异越大 提供的信息越多权重通常越高。 from dataclasses import dataclass from typing import Sequence import numpy as np dataclass(frozenTrue) class EntropyWeightResult: 保存熵权法的计算结果。 weights: np.ndarray entropy: np.ndarray information_utility: np.ndarray normalized_matrix: np.ndarray probability_matrix: np.ndarray scores: np.ndarray ranking: np.ndarray def entropy_weight( decision_matrix: Sequence[Sequence[float]], indicator_types: Sequence[str], ) - EntropyWeightResult: 计算指标的熵权以及各方案的综合得分和排名。 参数 decision_matrix: 决策矩阵每行是一个方案每列是一个指标。 indicator_types: 各指标类型benefit 表示越大越好 cost 表示越小越好。 返回 包含指标权重、信息熵、综合得分和排名的结果对象。 matrix np.asarray(decision_matrix, dtypefloat) if matrix.ndim ! 2 or matrix.shape[0] 2 or matrix.shape[1] 1: raise ValueError(决策矩阵必须是至少包含 2 个方案的二维矩阵) if not np.all(np.isfinite(matrix)): raise ValueError(决策矩阵不能包含 NaN 或无穷大) if len(indicator_types) ! matrix.shape[1]: raise ValueError(indicator_types 的长度必须等于指标个数) # 第一步使用极差法正向化、无量纲化使结果落在 [0, 1]。标准化 normalized np.empty_like(matrix, dtypefloat)#创建一个与 matrix 形状相同的空数组用于存储正向化后的数据 for j, kind in enumerate(indicator_types): kind kind.lower() column matrix[:, j] column_min np.min(column) column_max np.max(column) value_range column_max - column_min # 所有方案取值相同时该指标没有区分能力先统一记为 1。 if value_range 0: normalized[:, j] 1.0 elif kind benefit: normalized[:, j] (column - column_min) / value_range elif kind cost: normalized[:, j] (column_max - column) / value_range else: raise ValueError( f未知指标类型 {kind!r}应为 benefit 或 cost ) # 第二步计算每个方案在各指标下的比重 p_ij。也是归一化 column_sums np.sum(normalized, axis0) probability normalized / column_sums # 第三步计算信息熵 e_j。规定 0 * ln(0) 0。 n_alternatives matrix.shape[0] log_probability np.zeros_like(probability) positive probability 0 log_probability[positive] np.log(probability[positive]) entropy -np.sum(probability * log_probability, axis0) / np.log( n_alternatives ) # 消除浮点运算可能产生的极小越界误差。 entropy np.clip(entropy, 0.0, 1.0) # 第四步差异系数信息效用值越大指标提供的信息越多。 information_utility 1.0 - entropy utility_sum np.sum(information_utility) if np.isclose(utility_sum, 0.0): # 所有指标都没有区分能力时采用等权避免除以零。 weights np.full(matrix.shape[1], 1.0 / matrix.shape[1]) else: weights information_utility / utility_sum#熵权就是归一化 # 第五步用正向化后的数据进行加权求和并由高到低排序。 scores normalized weights ranking np.argsort(-scores, kindstable) return EntropyWeightResult( weightsweights, entropyentropy, information_utilityinformation_utility, normalized_matrixnormalized, probability_matrixprobability, scoresscores, rankingranking, ) def main() - None: 运行一个供应商综合评价示例。 alternatives [供应商 A, 供应商 B, 供应商 C, 供应商 D] criteria [产品质量, 采购价格, 交付准时率, 售后响应时间] # 每行代表一个供应商每列依次对应上面的四项指标。 decision_matrix np.array( [ [92, 108, 96, 3.0], [88, 100, 91, 2.0], [95, 115, 98, 4.0], [90, 105, 94, 2.5], ], dtypefloat, ) indicator_types [benefit, cost, benefit, cost] result entropy_weight(decision_matrix, indicator_types) print(熵权法计算的指标权重) for criterion, weight in zip(criteria, result.weights): print(f {criterion}{weight:.4f}) print(\n方案综合得分与排名) for rank, index in enumerate(result.ranking, start1): print( f 第 {rank} 名{alternatives[index]} f得分 {result.scores[index]:.4f} ) if __name__ __main__: main()(base) PS D:\桌面\华为杯\code d:/Users/anaconda3/python.exe d:/桌面/华为杯/code/评价类/entropy_weight.py 熵权法计算的指标权重 产品质量0.2863 采购价格0.2385 交付准时率0.2437 售后响应时间0.2315 方案综合得分与排名 第 1 名供应商 A得分 0.5647 第 2 名供应商 C得分 0.5300 第 3 名供应商 D得分 0.5189 第 4 名供应商 B得分 0.4700灰色关联Grey Relational AnalysisGRA看每个方案的数据变化趋势和“理想方案”的变化趋势有多像。越像关联度越高方案越好。信息不完全性系统的结构、参数、边界条件、输入输出关系中至少有一项是未知或模糊的。数据稀疏性系统可观测的数据量少小样本无法通过传统统计方法如回归分析捕捉规律。不确定性与非线性系统内部因素之间、因素与目标之间的关系是非线性、非确定性的无法用简单的线性方程描述1、正向化2、选择参考序列3、计算距离4、计算灰色关联系数某一个指标越接近理想值这个指标对应的灰色关联系数就越大分辨系数一般为0.5。5、计算灰色关联度表示与参考序列的关联程度没有权重直接求均值有权重越大方案越好。也可以用灰色关联度计算权重使用 NumPy 实现灰色关联分析Grey Relational Analysis, GRA。 灰色关联分析通过比较各方案序列与最优参考序列的接近程度 得到灰色关联系数、综合关联度以及方案排名。 from dataclasses import dataclass from typing import Optional, Sequence import numpy as np dataclass(frozenTrue) class GreyRelationalResult: 保存灰色关联分析的主要计算结果。 normalized_matrix: np.ndarray reference_sequence: np.ndarray difference_matrix: np.ndarray relational_coefficients: np.ndarray relational_grades: np.ndarray ranking: np.ndarray weights: np.ndarray def grey_relational_analysis( decision_matrix: Sequence[Sequence[float]], indicator_types: Sequence[str], weights: Optional[Sequence[float]] None, rho: float 0.5, ) - GreyRelationalResult: 计算各方案的灰色关联度并返回由优到劣的排序。 参数 decision_matrix: 决策矩阵每行是一个方案每列是一个指标。 indicator_types: 指标类型benefit 表示越大越好cost 表示越小越好。 weights: 指标权重。省略时使用等权输入后会自动归一化。 rho: 分辨系数取值范围为 (0, 1)通常取 0.5。 matrix np.asarray(decision_matrix, dtypefloat) if matrix.ndim ! 2 or matrix.shape[0] 2 or matrix.shape[1] 1: raise ValueError(决策矩阵必须是至少包含 2 个方案的二维矩阵) if not np.all(np.isfinite(matrix)): raise ValueError(决策矩阵不能包含 NaN 或无穷大) if len(indicator_types) ! matrix.shape[1]: raise ValueError(indicator_types 的长度必须等于指标个数) if not 0 rho 1: raise ValueError(分辨系数 rho 必须满足 0 rho 1) n_indicators matrix.shape[1] if weights is None: weight_array np.full(n_indicators, 1.0 / n_indicators) else: weight_array np.asarray(weights, dtypefloat) if weight_array.ndim ! 1 or len(weight_array) ! n_indicators: raise ValueError(weights 的长度必须等于指标个数) if not np.all(np.isfinite(weight_array)) or np.any(weight_array 0): raise ValueError(权重必须是有限的非负数) if np.sum(weight_array) 0: raise ValueError(权重之和必须大于 0) weight_array weight_array / np.sum(weight_array) # 第一步极差标准化并将所有指标统一为“越大越好”。 normalized np.empty_like(matrix, dtypefloat) for j, kind in enumerate(indicator_types): kind kind.lower() column matrix[:, j] column_min np.min(column) column_max np.max(column) value_range column_max - column_min # 该列数据完全相同时各方案在此指标上的表现相同。 if value_range 0: normalized[:, j] 1.0 elif kind benefit: normalized[:, j] (column - column_min) / value_range elif kind cost: normalized[:, j] (column_max - column) / value_range else: raise ValueError( f未知指标类型 {kind!r}应为 benefit 或 cost ) # 第二步以各指标的最优值组成参考序列。 reference np.max(normalized, axis0) # 第三步计算各方案序列与参考序列的绝对差。 differences np.abs(normalized - reference) global_min np.min(differences) global_max np.max(differences) # 第四步计算灰色关联系数。越接近1越好。 if np.isclose(global_max, 0.0): # 所有方案完全相同时所有关联系数均为 1。 coefficients np.ones_like(differences) else: coefficients (global_min rho * global_max) / ( differences rho * global_max ) # 第五步对关联系数加权求和得到综合灰色关联度。 grades coefficients weight_array ranking np.argsort(-grades, kindstable) return GreyRelationalResult( normalized_matrixnormalized, reference_sequencereference, difference_matrixdifferences, relational_coefficientscoefficients, relational_gradesgrades, rankingranking, weightsweight_array, ) def main() - None: 运行一个供应商综合评价示例。 alternatives [供应商 A, 供应商 B, 供应商 C, 供应商 D] criteria [产品质量, 采购价格, 交付准时率, 售后响应时间] # 每行代表一个供应商每列依次对应上面的四项指标。 decision_matrix np.array( [ [92, 108, 96, 3.0], [88, 100, 91, 2.0], [95, 115, 98, 4.0], [90, 105, 94, 2.5], ], dtypefloat, ) indicator_types [benefit, cost, benefit, cost] weights [0.35, 0.25, 0.25, 0.15] result grey_relational_analysis( decision_matrix, indicator_types, weightsweights, rho0.5, ) print(指标权重) for criterion, weight in zip(criteria, result.weights): print(f {criterion}{weight:.4f}) print(\n灰色关联度与排名) for rank, index in enumerate(result.ranking, start1): print( f 第 {rank} 名{alternatives[index]} f关联度 {result.relational_grades[index]:.4f} ) if __name__ __main__: main()(base) PS D:\桌面\华为杯\code d:/Users/anaconda3/python.exe d:/桌面/华为杯/code/评价类/grey_relational.py 指标权重 产品质量0.3500 采购价格0.2500 交付准时率0.2500 售后响应时间0.1500 灰色关联度与排名 第 1 名供应商 C关联度 0.7333 第 2 名供应商 B关联度 0.6000 第 3 名供应商 A关联度 0.5435 第 4 名供应商 D关联度 0.5108CRITICCriteria Importance Through Intercriteria Correlation基于指标对比强度和指标间冲突性的客观赋权法一个指标如果自身差异很大而且和其他指标不太重复那么它的信息量就大权重就应该高。熵权法相比多考虑了一件事指标之间是不是重复第 j 个指标的信息量通常写成自身标准差 皮尔逊系数归一化输入决策矩阵↓正向化和极差标准化↓计算标准差↓计算相关系数↓计算冲突性↓计算指标信息量↓计算 CRITIC 权重↓计算方案得分与排名CRITIC 法不宜采用 Z-score 标准化因为 Z-score 处理会使各指标的标准差统一为 1导致标准差无法反映指标的对比强度。可以采用极差标准化在消除量纲并完成指标正向化的同时保留标准化后各指标分布差异。使用 NumPy 实现 CRITIC 客观赋权法。 CRITICCriteria Importance Through Intercriteria Correlation同时考虑 1. 指标内部的数据差异即对比强度 2. 指标之间的相关程度即冲突性。 指标对比越强、与其他指标的冲突越大其客观权重通常越高。 from dataclasses import dataclass from typing import Sequence import numpy as np dataclass(frozenTrue) class CriticResult: 保存 CRITIC 法的主要中间结果和最终结果。 weights: np.ndarray normalized_matrix: np.ndarray standard_deviations: np.ndarray correlation_matrix: np.ndarray conflicts: np.ndarray information: np.ndarray scores: np.ndarray ranking: np.ndarray def critic_weight( decision_matrix: Sequence[Sequence[float]], indicator_types: Sequence[str], ) - CriticResult: 计算 CRITIC 指标权重以及各方案的综合得分和排名。 参数 decision_matrix: 决策矩阵每行是一个方案每列是一个指标。 indicator_types: 指标类型benefit 表示越大越好 cost 表示越小越好。 matrix np.asarray(decision_matrix, dtypefloat) if matrix.ndim ! 2 or matrix.shape[0] 2 or matrix.shape[1] 1: raise ValueError(决策矩阵必须是至少包含 2 个方案的二维矩阵) if not np.all(np.isfinite(matrix)): raise ValueError(决策矩阵不能包含 NaN 或无穷大) if len(indicator_types) ! matrix.shape[1]: raise ValueError(indicator_types 的长度必须等于指标个数) # 第一步极差标准化并将指标统一转换为“越大越好”。 normalized np.empty_like(matrix, dtypefloat) for j, kind in enumerate(indicator_types): kind kind.lower() column matrix[:, j] column_min np.min(column) column_max np.max(column) value_range column_max - column_min # 常量指标没有区分能力标准化后统一记为 0。 if np.isclose(value_range, 0.0): normalized[:, j] 0.0 elif kind benefit: normalized[:, j] (column - column_min) / value_range elif kind cost: normalized[:, j] (column_max - column) / value_range else: raise ValueError( f未知指标类型 {kind!r}应为 benefit 或 cost ) # 第二步用标准差表示各指标的对比强度。 standard_deviations np.std(normalized, axis0, ddof0)# ddof0 表示总体标准差 varying ~np.isclose(standard_deviations, 0.0) # 第三步计算指标间的皮尔逊相关系数。 # 常量列的相关系数没有定义这里将其冲突贡献记为 0避免影响其他指标。 n_indicators matrix.shape[1] correlation np.ones((n_indicators, n_indicators), dtypefloat)# 初始化相关系数矩阵为1 varying_indices np.flatnonzero(varying)# 找出数值有变化的指标 if len(varying_indices) 2: varying_correlation np.corrcoef(#皮尔逊相关系数 normalized[:, varying_indices], rowvarFalse ) correlation[np.ix_(varying_indices, varying_indices)] varying_correlation correlation np.clip(correlation, -1.0, 1.0) # 第四步相关性越弱指标之间的冲突越强。 conflicts np.sum(1.0 - correlation, axis1) # 第五步信息量 标准差 × 冲突性。 information standard_deviations * conflicts information_sum np.sum(information) if not np.isclose(information_sum, 0.0): weights information / information_sum#归一化 else: # 只有一个有效指标或有效指标完全正相关时CRITIC 信息量可能全为 0。 # 此时优先按照标准差赋权若所有指标均为常量则采用等权重。 deviation_sum np.sum(standard_deviations) if not np.isclose(deviation_sum, 0.0): weights standard_deviations / deviation_sum else: weights np.full(n_indicators, 1.0 / n_indicators) # 第六步对正向化数据加权求和并按综合得分从高到低排序。 scores normalized weights ranking np.argsort(-scores, kindstable) return CriticResult( weightsweights, normalized_matrixnormalized, standard_deviationsstandard_deviations, correlation_matrixcorrelation, conflictsconflicts, informationinformation, scoresscores, rankingranking, ) def main() - None: 运行一个供应商综合评价示例。 alternatives [供应商 A, 供应商 B, 供应商 C, 供应商 D] criteria [产品质量, 采购价格, 交付准时率, 售后响应时间] # 每行代表一个供应商每列依次对应上面的四项指标。 decision_matrix np.array( [ [92, 108, 96, 3.0], [88, 100, 91, 2.0], [95, 115, 98, 4.0], [90, 105, 94, 2.5], ], dtypefloat, ) indicator_types [benefit, cost, benefit, cost] result critic_weight(decision_matrix, indicator_types) print(CRITIC 法计算的指标权重) for criterion, weight in zip(criteria, result.weights): print(f {criterion}{weight:.4f}) print(\n方案综合得分与排名) for rank, index in enumerate(result.ranking, start1): print( f 第 {rank} 名{alternatives[index]} f得分 {result.scores[index]:.4f} ) if __name__ __main__: main()(base) PS D:\桌面\华为杯\code d:/Users/anaconda3/python.exe d:/桌面/华为杯/code/评价类/critic.py CRITIC 法计算的指标权重 产品质量0.2532 采购价格0.2462 交付准时率0.2501 售后响应时间0.2505 方案综合得分与排名 第 1 名供应商 A得分 0.5635 第 2 名供应商 D得分 0.5315 第 3 名供应商 C得分 0.5033 第 4 名供应商 B得分 0.4967