Python 实现的综合评价系统数学建模详解(灰色关联分析法2.0)

一、引言

        在当今数据驱动的时代,无论是商业决策、学术研究,还是日常生活中的选择,我们都面临着对各种复杂事物进行综合评估的需求。例如,企业在挑选供应商时,需要综合考量供应商的产品质量、交货及时性、价格优势以及售后服务等多个维度的指标;学校在评估学生的综合素质时,会涉及到学业成绩、课外活动参与度、品德表现等不同方面的因素。然而,这些用于评估的指标往往具有不同的性质和量纲。有些指标属于极大型,即数值越大越好,像产品的收益率、学生的考试成绩;有些是极小型,数值越小越理想,比如产品的次品率、完成任务的时间;还有中间值型指标,存在一个特定的最优中间值,离该值越近越优,例如人体的正常体温范围;以及区间型指标,在某个特定区间内的数值为最佳,比如电子产品的最佳工作温度区间。

        这种指标的多样性和复杂性使得直接对数据进行分析和比较变得困难重重。如果不进行有效的处理,不同指标之间无法在同一尺度上进行衡量,可能导致评估结果出现偏差,无法真实反映被评估对象的综合情况。为了解决这一问题,我们引入了一套全面的综合指标分析方法,并通过 Python 代码将其实现为一个功能强大的分析系统。这个系统能够有条不紊地将各种类型的指标统一为可比较的形式,对数据进行科学的预处理,消除量纲和数量级的影响,然后通过合理的算法计算出每个指标的权重,最终得出每个项目的综合得分。它为我们在复杂的数据环境中进行准确、高效的决策提供了有力的支持,让我们能够拨开数据的迷雾,清晰地洞察事物的本质,做出更加明智的选择。

二、综合指标分析方法概述

(一)指标类型转化

        在实际数据中,指标类型多样,包括极大型、极小型、中间值型和区间型。为了便于统一分析,需要将极小型、中间值型和区间型指标转化为极大型指标。

  • 极小型指标转化:对于极小型指标,通过计算指标中的最大值与每个数据的差值的绝对值,将其转化为极大值指标形式。例如,成本类指标通常是越小越好,转化后就变为越大越好的形式。
  • 中间值型指标转化:中间值型指标是存在一个最优中间值,离该值越近越好。通过计算每个数据与最优中间值的差值的绝对值,再经过一定的归一化处理,将其转化为极大值指标。
  • 区间型指标转化:区间型指标有一个最优区间,在该区间内的值为最优。对于小于区间最小值的数据和大于区间最大值的数据,分别通过特定公式进行转化,使整个指标转化为极大值指标。

(二)数据预处理

        数据预处理是为了消除不同指标之间量纲和数量级的影响,使数据具有可比性。常见的方法是计算每列数据的均值,然后将原始数据除以对应列的均值,实现数据的归一化。

(三)权重计算与得分计算

        在统一指标和预处理数据后,需要确定每个指标的权重,以反映其在综合评价中的相对重要性。通过构造母序列(通常取每个项目在所有指标中的最大值组成)和子序列(即预处理后的指标数据),计算它们之间的绝对差值,进而得出灰色关联系数。对灰色关联系数进行一定处理后得到每个指标的权重。最后,利用权重与预处理后的指标数据进行矩阵乘法运算,得到每个项目的综合得分,并进行归一化处理。

三、Python 代码实现综合指标分析系统

(一)代码结构分析

        代码通过定义IndexAnalysis类来实现整个综合指标分析流程。类中包含多个静态方法和实例方法,静态方法用于实现一些独立的功能,如指标类型转化、矩阵输入、数据预处理等;实例方法用于整合各个步骤,完成从输入数据到得出综合得分的全过程。

(二)代码详细解析

  1. 类的初始化方法
def __init__(self):
    pass

   IndexAnalysis类的初始化方法较为简单,目前未进行任何特定的初始化操作,后续若有需要可在此添加初始化属性等代码。

  1. 极小值指标转化为极大值指标
@staticmethod
def min_to_max(max_x, x):
    """
    极小值指标转化为极大值指标
    :param max_x: 最大值
    :param x: 输入数组
    :return: 转换后的数组
    """
    return np.abs(max_x - np.array(x))

        该静态方法接收当前指标中的最大值max_x和包含该指标所有数据的数组x。利用numpyabs函数计算max_x与数组x中每个元素的差值的绝对值,将极小型指标转化为极大值指标形式,返回转换后的numpy数组。

  1. 中间值指标转化为极大值指标
@staticmethod
def mid_to_max(best_x, x):
    """
    中间值指标转化为极大值指标
    :param best_x: 最优值
    :param x: 输入数组
    :return: 转换后的数组
    """
    h = np.abs(best_x - np.array(x))
    m = np.max(h)
    if m == 0:
        m = 1
    return 1 - h / m

        此静态方法接收指标的最优中间值best_x和指标数据数组x。首先使用numpyabs函数计算best_x与数组x中每个元素的差值的绝对值,得到数组h。然后找出h中的最大值m,若m为 0(表示所有数据都等于最优中间值),则将m设为 1。最后通过公式1 - h / m对数组h中的每个元素进行计算,得到转化后的数组并返回。

  1. 区间性指标转化为极大值指标
@staticmethod
def reg_to_max(min_x, max_x, x):
    """
    区间性指标转化为极大值指标
    :param min_x: 区间最小值
    :param max_x: 区间最大值
    :param x: 输入数组
    :return: 转换后的数组
    """
    x = np.array(x)
    m = max(min_x - np.min(x), np.max(x) - max_x)
    if m == 0:
        m = 1
    result = np.ones_like(x)
    mask_less = x < min_x
    mask_greater = x > max_x
    result[mask_less] = 1 - (min_x - x[mask_less]) / m
    result[mask_greater] = 1 - (x[mask_greater] - max_x) / m
    return result

        该静态方法接收区间最小值min_x、区间最大值max_x以及指标数据数组x。首先将输入数组x转换为numpy数组,计算数据与区间边界差值的最大值m,若m为 0 则设为 1。创建一个与x形状相同且元素全为 1 的数组result。通过布尔索引,对于小于min_x的数据,使用公式1 - (min_x - x[mask_less]) / m进行转化;对于大于max_x的数据,使用公式1 - (x[mask_greater] - max_x) / m进行转化,最终返回转化后的数组result

  1. 输入矩阵
@staticmethod
def input_matrix(n, m):
    """
    输入矩阵
    :param n: 行数
    :param m: 列数
    :return: 输入的矩阵
    """
    print('请输入矩阵(用","分隔):')
    np_array = np.zeros(shape=(n, m))
    for i in range(n):
        try:
            row = input().split(',')
            if len(row) != m:
                print(f"输入的第 {i + 1} 行元素数量不正确,请输入 {m} 个元素。")
                return None
            np_array[i] = [float(num) for num in row]
        except ValueError:
            print(f"输入的第 {i + 1} 行包含非数字元素,请重新输入。")
            return None
    print('输入的矩阵为:\n{}'.format(np_array))
    return np_array

        这是一个静态方法,用于获取用户输入的矩阵。它接收矩阵的行数n和列数m作为参数。首先提示用户输入矩阵数据,数据以逗号分隔。然后创建一个全零的numpy数组np_array,其形状为(n, m)。通过循环逐行获取用户输入的数据,将输入的字符串以逗号分隔并转换为浮点数列表,赋值给np_array的对应行。若输入的行元素数量不正确或包含非数字元素,会给出相应提示并返回None。最后打印输入的矩阵并返回。

  1. 统一指标矩阵
def unified_matrix(self):
    """
    统一指标矩阵
    :return: 统一指标后的矩阵
    """
    try:
        print('请输入参评的项目数:')
        n = int(input())
        print('请输入参评指标数:')
        m = int(input())
        a = self.input_matrix(n, m)
        if a is None:
            print("矩阵输入有误,程序退出。")
            return None
        print('请依次输入每一个参评指标的类型(用","分隔):1 极大型,2 极小型,3 中立型,4 区间型')
        kind = input().split(',')
        if len(kind) != m:
            print("类型矩阵的长度与指标数不匹配,程序退出。")
            return None
        x = np.zeros(shape=(n, 1))
        for i in range(m):
            if kind[i] == '1':
                v = a[:, i]
            elif kind[i] == '2':
                max_x = np.max(a[:, i])
                v = self.min_to_max(max_x, a[:, i])
            elif kind[i] == '3':
                try:
                    best_x = float(input('请输入第{}个指标的最优值:'.format(i + 1)))
                    v = self.mid_to_max(best_x, a[:, i])
                except ValueError:
                    print("输入的最优值不是有效的数字,程序退出。")
                    return None
                elif kind[i] == '4':
                    try:
                        min_x = float(input('请输入第{}个指标的最小值:'.format(i + 1)))
                        max_x = float(input('请输入第{}个指标的最大值:'.format(i + 1)))
                        v = self.reg_to_max(min_x, max_x, a[:, i])
                    except ValueError:
                        print("输入的最小值或最大值不是有效的数字,程序退出。")
                        return None
                else:
                    print('输入的指标类型错误,程序退出。')
                    return None
                if i == 0:
                    x = v.reshape(-1, 1)
                else:
                    x = np.hstack([x, v.reshape(-1, 1)])
            print('统一指标后的矩阵为:\n{}'.format(x))
            return x
    except ValueError:
        print("输入的项目数或指标数不是有效的整数,程序退出。")
        return None

        该实例方法负责将不同类型的指标统一为极大值指标类型。首先提示用户输入参评项目数n和参评指标数m,并调用input_matrix方法获取用户输入的矩阵a。若矩阵输入有误则打印错误信息并退出程序。接着提示用户输入每个指标的类型,将输入的字符串以逗号分隔存储在kind列表中。检查kind列表的长度是否与指标数m一致,不一致则打印错误信息并退出程序。通过循环遍历每个指标,根据指标类型调用相应的转化方法(极大型指标直接使用原数据,极小型、中间值型、区间型指标分别调用对应的转化方法)。将转化后的数据逐列合并成一个新的矩阵x,最后打印统一指标后的矩阵并返回。

  1. 对矩阵进行预处理
@staticmethod
def preprocess_matrix(matrix):
    """
    对矩阵进行预处理,计算每列的均值并进行归一化。
    :param matrix: 输入的矩阵
    :return: 预处理后的矩阵
    """
    column_means = np.mean(matrix, axis=0)
    normalized_matrix = matrix / column_means
    print('预处理后的矩阵为:\n{}'.format(normalized_matrix))
    return normalized_matrix

        该静态方法接收一个矩阵matrix作为参数。使用numpymean函数计算矩阵每列的均值column_means,然后将矩阵的每个元素除以对应列的均值,实现数据的归一化,消除量纲和数量级的影响。打印预处理后的矩阵并返回。

  1. 构造母序列和子序列
@staticmethod
def construct_reference_and_comparison_sequences(a):
    """
    构造母序列和子序列。
    :param a: 统一指标后的矩阵
    :return: 母序列和子序列
    """
    reference_sequence = np.max(a, axis=1)
    comparison_sequences = a
    return reference_sequence, comparison_sequences

        此静态方法接收统一指标后的矩阵a。通过numpymax函数,沿轴 1(即每行)取最大值,得到母序列reference_sequence。子序列则直接使用统一指标后的矩阵a,最后返回母序列和子序列。

  1. 计算权重
@staticmethod
def calculate_weight(a):
    """
    计算权重。
    :param a: 统一指标后的矩阵
    :return: 权重
    """
    reference_sequence, comparison_sequences = IndexAnalysis.construct_reference_and_comparison_sequences(a)
    extended_reference = np.tile(reference_sequence.reshape(-1, 1), (1, comparison_sequences.shape[1]))
    absolute_difference = np.abs(comparison_sequences - extended_reference)
    min_difference = np.min(absolute_difference)
    max_difference = np.max(absolute_difference)
    rho = 0.5
    quantifier = (min_difference + rho * max_difference) / (absolute_difference + rho * max_difference)
    average_correlation = np.mean(quantifier, axis=0) / np.sum(np.mean(quantifier, axis=0))
    print('权重为:\n{}'.format(average_correlation))
    return average_correlation

        该静态方法用于计算指标的权重。首先调用construct_reference_and_comparison_sequences方法获取母序列和子序列。使用numpytile函数将母序列扩展为与子序列相同的形状,以便进行逐元素相减,得到绝对差值矩阵absolute_difference。接着计算绝对差值矩阵中的两级最小差min_difference和两级最大差max_difference。设定分辨系数rho为 0.5,根据公式计算每个子序列与母序列在各个时刻的量化值quantifier。对quantifier按列求均值,再将每列均值除以所有列均值之和,进行归一化处理,得到每个指标的权重average_correlation。打印权重并返回。

  1. 根据权重计算得分
@staticmethod
def calculate_score(a, weight):
    """
    根据权重计算得分。
    :param a: 统一指标后的矩阵
    :param weight: 权重
    :return: 得分
    """
    score = np.dot(a, weight)
    score = score / np.sum(score)
    print('得分为:\n{}'.format(score))
    return score

        该静态方法接收统一指标后的矩阵a和权重weight作为参数。使用numpydot函数进行矩阵乘法运算,将矩阵a与权重weight相乘,得到每个项目的初步得分。然后将初步得分除以所有得分之和,进行归一化处理,得到最终的得分score。打印得分并返回。

  1. 运行整个分析流程
def run_analysis(self):
    """
    运行整个分析流程
    :return: 得分
    """
    unified_matrix = self.unified_matrix()
    if unified_matrix is None:
        return None
    preprocessed_matrix = self.preprocess_matrix(unified_matrix)
    weight = self.calculate_weight(preprocessed_matrix)
    score = self.calculate_score(preprocessed_matrix, weight)
    return score

        该实例方法是整个分析流程的入口。首先调用unified_matrix方法获取统一指标后的矩阵,如果获取失败则返回None。接着对统一指标后的矩阵进行预处理,调用preprocess_matrix方法得到预处理后的矩阵preprocessed_matrix。然后使用预处理后的矩阵计算权重,调用calculate_weight方法得到权重weight。最后利用预处理后的矩阵和权重计算得分,调用calculate_score方法得到最终的得分score并返回。

四、代码使用示例

        假设我们要对几款手机进行综合评估,评估指标包括价格(极小型指标)、性能(极大型指标)、拍照质量(中间值型指标,最优值为 8 分)、电池续航(区间型指标,最优区间为 3000 - 4000 毫安时)。

  1. 输入矩阵:
请输入参评的项目数: 3
请输入参评指标数: 4
请输入矩阵(用","分隔):
1000,80,7,3500
1500,90,8,3800
1200,85,6,3200
  1. 输入指标类型:
请依次输入每一个参评指标的类型(用","分隔):2,1,3,4
  1. 输入中间值型指标的最优值:
请输入第3个指标的最优值: 8
  1. 输入区间型指标的最小值和最大值:
请输入第4个指标的最小值: 3000
请输入第4个指标的最大值: 4000

        运行代码后,程序将依次进行指标统一、数据预处理、权重计算和得分计算,并输出最终的得分。通过得分可以直观地比较几款手机的综合表现,为购买决策提供参考。

五、总结

        主成分分析法(PCA)作为一种强大的数据降维与综合分析工具,在众多领域有着广泛的适用场景。在高维数据处理场景中,例如基因数据分析领域,研究人员往往需要处理包含成千上万种基因表达数据的样本。这些数据维度极高,不仅增加了计算的复杂性,还可能引入噪声和冗余信息,干扰对关键因素的分析。此时,主成分分析法能够发挥其优势,将这些高维数据转换为少数几个综合指标(主成分),在保留大部分关键信息的同时,降低数据维度,使得后续的分析更加高效和准确。

        在市场调研与商业分析方面,企业收集消费者的大量数据,涵盖年龄、收入、消费习惯、品牌偏好等多个维度。运用主成分分析法,能够将这些复杂的数据浓缩为几个关键的主成分,帮助企业清晰洞察消费者行为模式和市场趋势,从而更精准地制定营销策略、优化产品设计。

        回到我们所构建的 Python 代码,它围绕综合指标分析展开,虽然未直接命名为主成分分析法的代码实现,但底层原理与主成分分析法有着相通之处。代码中的指标统一部分,如同主成分分析中对不同量纲数据的预处理,确保各类指标在同一尺度下进行比较,为后续分析奠定基础。通过将极小型、中间值型和区间型指标转化为极大型指标,使得所有指标能够在统一框架下参与综合评估,这类似于主成分分析对原始数据的标准化处理,消除量纲影响,突出数据间的相对关系。

        数据预处理环节,计算每列数据的均值并进行归一化,进一步强化了数据的可比性,这与主成分分析追求数据在同一基准上进行降维变换的理念一致。而在权重计算和得分计算部分,通过构造母序列和子序列,计算绝对差值和灰色关联系数来确定权重,进而得出综合得分,其本质也是从多个指标中提取关键信息,并根据各指标的相对重要性进行综合考量,这与主成分分析法提取主成分并赋予相应权重的思路相契合。

        在实际运用代码时,我们可以根据不同领域的具体需求,灵活调整输入数据和参数。以电商平台对商品的综合评估为例,将商品的价格、销量、好评率、退货率等指标作为输入,通过代码完成指标统一和预处理,再依据计算出的权重得出综合得分,以此筛选出优质商品,为平台推荐系统提供有力支持。在学术研究中,针对多因素影响的实验数据,也可借助该代码梳理各因素间的关系,确定关键影响因素。总之,这套代码为我们在不同场景下运用类似主成分分析的思想进行综合指标分析提供了实用的工具,帮助我们从复杂的数据中挖掘出有价值的信息,做出更具科学性的决策 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗蛋不是狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值