美文网首页程序员
选择困难?不存在的!把决策交给你的 Python

选择困难?不存在的!把决策交给你的 Python

作者: QuentinnYANG | 来源:发表于2018-11-27 00:19 被阅读0次

大选则愁眉苦脸,小选择焦躁烦心?NoNoNo...

阿白是从大学刚毕业准备进入社会的应届青年,在找工作的过程中,多个还不错的公司向他伸出的橄榄枝,这其中有高薪但辛苦的互联网职位,也有福利好但收入微薄的公务职位;有竞争激烈但光彩亮丽的金融岗位,也有默然无闻但前途无量的小小独角兽...
机会很多,但选择时间却只有短短的几周,然而阿白已经在纷杂的工作机会和复杂的交叉对比中迷失了自我...

而阿莲就不一样了,她是一个古灵精怪且向往爱情的大学生,因为天生一副娇美的容颜而受到众多男生的追捧;作为一个典型的选择困难症患者,阿莲经常问闺蜜的问题就是:“你觉得 A 好还是 B 好,A 家里条件好,长得帅,但是年龄比我小,B 虽然条件平平,但是幽默上进,而且对我特别温柔,诶呀诶呀,到底怎么选才好呢~。”

社会飞速发展,人们面临形形色色的困难的选择,有些人缺乏主见,所以听人言则轻信,在受人摇摆的道路上越走越远;而游戏而固执己见,逃避选择的困难,也逃避了自己真正想要的和想走的路。

那么问题来了,究竟有没有一种办法,能够让我们有方法,有逻辑的找到自己想要的东西,无论是事业爱情,还是设定爱好,只要你想认真的做出选择,不要 998,也不要 98,只要一个 click,你就能得到你想要的结果!这不是神话,也不是天方夜谭,而是科学!所以,今天就给大家带来一个非常好用的系统和用户分析方法——层级分析法,用来帮助那些选择困难症的患者获得来自科学的福音。

不相信?给你讲讲理论依托

其实做选择,思路很重要,很多人在选择过程中只是点状的关注不同选择之间的某些好处或缺点,然后在心中反复比较,心里的两个小人儿进行着说服和反说服的斗争,这种方法往往因为看问题的角度不够全面,从而在决定之后会产生各种后悔情绪。

正确的方法是,列出所有你关心的相关因素,对因素进行排序,然后在去看哪些决定性的因素影响了你的选择。这样的方法的基本逻辑为:

  1. 抽象选择问题
  2. 罗列关注因素
  3. 因素重要度排序
  4. 分析不同重要度的因素对决策的影响
  5. 做出满足更重要因素条件的选择

emmmmmmm...好的我补充一下人话以便大家理解:
比如说,我现在打算给我儿子选个小学(女朋友都没有选个什么小学,摔!),那么抽象出的选择问题就为:给娃选学校(这不是废话吗...),我们假设可选择的学校有三所(多了少了无所谓);下一步,我们来罗列一下关注因素,具体的关注因素可以包括但不限于:学费,离家远近,学校师资力量,学生质量,校园环境等等。然后呢,我们开始对因素进行重要度排序了,分析和决策了。emmmmm...到这里我们先按下不表,后面我们可以借助更专业的方法和工具完成剩下的三个步骤。

接下来的内容涉及较为专业的理论知识,如果不想了解那么细致可直接跳至文尾,有具体代码和操作的使用说明。

层级分析法

接下来我们简单讲解一下理论知识。层级分析法,又称 AHP,是美国运筹学家,匹兹堡大学教授 T.L.Saaty 在上世纪 70 年代初提出的一个分析方法,它最初的用途是用于研究如何为美国各工业部门按照对国家福利贡献度进行电力分配的课题,这个方法应用了网络系统理论和多目标综合评价方法,是一种层次权重决策分析方法。

层次分析法旨在解决多目标复杂问题的定性定量结合决策分析,可以用于社会、经济和管理领域等多种系统,这种系统往往是由相互关联,相互制约的多种因素构成,而决策者只要能够衡量各种因素之间的相对重要程度(相对权重),则该方法会合理的给出每个决策方案的各因素权重,从而帮助决策那些难以用定量方法解决的问题。

层级分析法的步骤

  1. 建立层次分析结构模型
  2. 构造判断矩阵(因素成对比较)
  3. 层次单排序和其一致性检验
  4. 层次总排序及其一致性检验

建立层次结构模型

建立模型的过程,就是将要决策的目标、目标涉及的因素(也称为决策准则)和决策选择按他们之间的关系分为最高层、中间层和底层,然后汇出结构图,例如:

AHP 层级

由上图可以看出,目标层和决策层只有一层,但是准则层可以有多层,其中下一层准则层是上一层的递进,这样的话我们就可以将准则的影响因素进行细分,并使用递归的方式进行逐层计算权重。

构造判断矩阵

为了确定个层次中各因素之间的权重,我们采用相对且两两独立的衡量指标,使用一致矩阵法来构造判断矩阵,即:

  • 将同一层的因素两两相互比较
  • 采用相对尺度,尽可能减少因为性质不同而产生的多个因素横向比较的困难

判断矩阵元素的标度方法:


判断矩阵

以选择 offer 的例子为例,我们可以构造出第一层的判断矩阵,这个矩阵需要你自己去衡量不同因素对你来说的重要程度,因为这个过程比较主观,所以才会出现最终不同决策对于不同人群的差异化现象。

判断矩阵示例

由上图可以看出,对于 Offer 的选择,我个人更看重职业的发展,它比其他三个因素都更重要,虽然程度不同,其次,与工作和生活环境相比,我更在意收入的多少,而在工作环境和生活环境中,我认为工作环境更值得考虑。

另外,为了防止因素太多而出现的对比中各权重填写混乱,或者在对比时思考不清楚(例如当 A 比 B 更重要,B 比 C 更重要,但是 A 却没有 C 重要)等情况出现,我们引入了判断矩阵的一致性分析,这个分析我们使用 Python 代码完成,感兴趣的可以参考代码。

走过路过,看不懂可以跳过

为了便于使用层级分析,我用 Python 写了这样一个程序,其输入是不同层级因素的判断矩阵,输出呢是不同决策的权重,例如,当有两个决策结果的时候,[0.48, 0.52] 即代表第一个选择的权重是0.48,第二个选择的权重是0.52,即程序在当前判断矩阵下更倾向于第二个选择。

另外需要注意的是,若出现判断矩阵一致性检验不通过的,则需要重新校验判断矩阵,看看是不是自己填写的时候出了什么问题。

以下是代码部分,感兴趣的朋友可以自己做个分析试试:

# 思路:
# 1. 首先输入每个指标下面对应的判断矩阵
# 2. 该矩阵中的值是通过大数据(或者专家)得到的每两个指标之间的相对重要程度值
# 3. 通过AHP计算这些判断矩阵是否通过一致性的检验,通过即合理
# 4. 不通过就说明矩阵中的两指标间的相对重要程度有过分矛盾的地方

import csv
import numpy as np
# import tensorflow as tf
# from sklearn.preprocessing import MinMaxScaler


class AHP:
    def __init__(self, array):
        self.row = len(array)
        self.col = len(array[0])

    def get_eigen(self, array):
        """
        获取特征值和特征向量
        :param array: 输入矩阵
        :return: 特征值和特征向量
        """
        eval, evector = np.linalg.eig(array)
        list1 = list(eval)
        print("特征值为:", eval)
        print("特征向量为:", evector)
        # 得到最大特征值对应的特征向量
        max_val = np.max(list1)
        index = list1.index(max_val)
        max_vector = evector[:, index]
        print("最大的特征值:" + str(max_val) + "   对应的特征向量为:" + str(max_vector))
        return max_val, max_vector

    def RImatrix(self, n):
        """
        选取一致性检验指标
        :param n: 输入参数个数
        :return: RI值
        """
        print("对比参数个数为:", n)
        n1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        n2 = [0, 0, 0.58, 0.90, 1.12, 1.24, 1.32, 1.41, 1.45]
        d = dict(zip(n1, n2))
        print("该矩阵在一致性检测时采用的RI值为:", d[n])
        return d[n]

    def test_consistence(self, max_val, RI):
        """
        测试一致性
        :param max_val: 对比参数个数
        :param RI: RI矩阵
        :return: 一致性检验结果
        """
        if self.row != 1:
            CI = (max_val - self.row) / (self.row - 1)
        if RI == 0:
            print("判断矩阵的RI值为  " + str(0) + "  通过一致性检验")
            return True
        else:
            CR = CI / RI
            if CR < 0.10:
                print("判断矩阵的CR值为  " + str(CR) + "  通过一致性检验")
                return True

            else:
                print("判断矩阵的CR值为  " + str(CR) + "  判断矩阵未通过一致性检验,请重新输入判断矩阵")
                return False

def main():
    weight_matrix = []
    level1 = []

    def process_input(file):
        """
        对输入的判别矩阵进行处理
        :param file: 输入文件流
        :return: 转存判别矩阵
        """
        level0 = []
        level1 = []
        leveli = []
        with open(file) as f:
            reader = csv.reader(f)
            for line in reader:
                # print(line)
                if line == []:
                    level1.append(level0)
                    level0 = []
                    continue
                for i in line:
                    if "/" in i:
                        b = i.split("/")
                        leveli.append(int(b[0]) / float(b[1]))
                    else:
                        leveli.append(float(i))
                level0.append(leveli)
                leveli = []
            level1.append(level0)
        # print(level1)
        return level1

    level1 = process_input(r"C:\Users\QuentinYang\Desktop\data.txt")
    print("输入的判断矩阵为:", level1)

    def normalize_vector(max_vector):
        """
        特征向量归一化
        :param max_vector: 判别矩阵的每一行
        :return: 归一化特征向量
        """
        vector_after_normalization = []
        sum0 = np.sum(max_vector)
        for i in range(len(max_vector)):
            vector_after_normalization.append(max_vector[i] / sum0)
        print("该级指标的权重矩阵为:  " + str(vector_after_normalization))

        # file = open(r"C:\Users\y00449927\Desktop\data.txt", 'a')
        # for i in vector_after_normalization:
        #     file.write(str(i))
        #     file.write("\n")

        return vector_after_normalization

    def to_input_matrix():
        """
        1. 获得判别矩阵的最大特征值和特征向量
        2. 判别矩阵的一致性检验
        3. 对特征向量进行归一化处理
        :return: 权重矩阵
        """
        for i in level1:
            length = len(level1)
            # print(i)
            a = AHP(i)
            max_val, max_vector = a.get_eigen(i)
            record_max_vector = max_vector
            RI = a.RImatrix(len(i)) # 随机一致性指标
            flag = a.test_consistence(max_val, RI)
            while not flag:
                print("判别矩阵未通过一致性检验,请重新输入判别矩阵!")
                break
            weight = normalize_vector(record_max_vector)  # 返回权重[[0.5, 0.5], [0.5, 0.5], [0.5, 0.5]]
            weight_matrix.append(weight)
        print("最终的权重矩阵为:", weight_matrix)
        return weight_matrix

    w00 = to_input_matrix()
    # print("w00", w00)

    def construct_weight_matrix(weight):
        """
        重构由各层级权重组成的权重矩阵
        :param weight: 权重矩阵
        :return: 重构后的权重矩阵
        """
        data = []
        for i in weight[0]:
            data.append(i.real)
        for i in weight[1:4]:
            for j in i:
                data.append(j.real)
        for i in weight[4:]:
            for j in i:
                data.append(j.real)
        print("重构后的权重矩阵: ", data)
        # print(len(data))
        return data

    d = construct_weight_matrix(w00)
    # print(d)

    def get_index(data):
        """
        层次总排序:确定某层所有因素对总目标的相对重要性排序权值
        -------------------------------------------------
        目标层(拟解决的总目标问题) O = 1
        准则层(为实现目标而采取的措施和方案)C = 5(此处为一层)
        方案层(解决问题的备选方案) P = 2
        -------------------------------------------------
        所以:
        1. 第一个矩阵 1*O,第二个矩阵 C*O。第三个矩阵 P*C
           即 1*1, 5*1, 2*5
        2. x 为默认自然数数组,表示该层因素个数
           y 为该层因素与上一层层级因素对应关系
        :param data: 构建的权重矩阵
        :return: 各层次的权重矩阵组成的总矩阵
        """
        # 注意:这里需要配合修改
        O = 1
        C = 9
        P = 2
        row = [O, C, P]
        column = [1, O, C]

        x1 = range(0, O)
        y1 = [0]

        x2 = []
        for i in range(O):
            x2 += range(0, C)
        y2 = [0, 0, 0, 0, 0, 0, 0, 0, 0]

        x3 = []
        for i in range(C):
            x3 += range(0, P)
        y3 = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]

        weight = []

        def transform(x, y, data, row, col):
            h = list(zip(x, y))
            # print("xxx", h)
            mat1 = np.zeros((row, col))
            # print(mat1)
            for i in range(len(data)):
                mat1[h[i]] = data[i]
            weight.append(mat1)

        transform(x1, y1, data[:O], row[0], column[0])
        transform(x2, y2, data[O:(O+C)], row[1], column[1])
        transform(x3, y3, data[(O+C):], row[2], column[2])
        print("各层次的权重矩阵组成的总矩阵: ", weight)
        return weight

    w1 = get_index(d)

    def get_final_weight(w):
        """
        方案层总层次排序
        :param w: 各层单排序矩阵
        :return: 各方案权重值矩阵
        """
        j = 0
        s = np.array([1])
        # print(np.dot(w[1], w[0]))

        while j < len(w):
            # print("weight0[i]", w[j])
            s = np.dot(w[j], s)
            # print("s", s)
            j += 1
        # print("s", s)
        return s

    # test1 = [[[1.]], [[0.22],
    #    [0.504],
    #    [0.143],
    #    [0.0961],
    #    [0.0361]], [[0.17, 0.88, 0.1, 0.5, 0.25],
    #    [0.83, 0.13, 0.9, 0.5, 0.75]]]

    s1 = get_final_weight(w1)
    print("总权重系数矩阵为: ", s1)

    def data_process():
        """
        处理数据
        :return:
        """
        i = 0
        data = []
        global name
        name = []
        with open(r'C:\Users\adm\Desktop\数据.csv') as f:
            reader = csv.reader(f)
            for row in reader:
                if i == 0:
                    i += 1
                    continue
                else:
                    data.append(row[:])
                    name.append(row[1])

        data = np.asarray(data)
        data1 = data[:, 3:].astype('float64')
        scaler = MinMaxScaler(feature_range=(0, 1))
        data1 = scaler.fit_transform(data1)
        print(len(data1))
        return data1

    def score_calculator():
        SCORE = []
        score = []
        value = data_process()
        # print(len(value))
        for i in range(len(value)):
            # print("i",len(value[i]))
            # print(len(s1))
            SCORE = np.sum([x * y for x, y in zip(value[i], s1)]) * 100
            score.append(SCORE)
        score = [i / np.max(score) * 100 for i in score]
        print(score)

        d = dict(zip(name, score))
        d1 = sorted(d.items(), key=lambda items: items[1], reverse=True)
        # print(d1)
        for key, value in d1[:80]:

            if value > 80:
                print(str(key) + "  最终得到的评分为: " + str(value) + "    合理")
            elif 70 < value < 80:
                print(str(key) + "  最终得到的评分为: " + str(value) + "    较为合理")
            elif 60 < value < 70:
                print(str(key) + "  最终得到的评分为: " + str(value) + "    一般合理")
            else:
                print(str(key) + "  最终得到的评分为: " + str(value) + "    不合理")

        print("所有指标权重的和", np.sum(s1))

    # score_calculator()
if __name__ == '__main__':
    main()

判别矩阵,可以写在 txt 文本中,然后用 Python 读入

# 注意:实际使用时请删除注释
# 目标层 Dummy number
1

# 第一层级判断矩阵
1,1/3,1/5,1,3,1/3,3,5,3
3,1,1/3,3,5,1,1/3,5,1/3
5,3,1,3,5,1,1,3,3
1,1/3,1/3,1,2,1/5,1/3,1/2,1/5
1/3,1/5,1/5,1/2,1,1/7,1/3,2,1/3
3,1,1,5,7,1,1,5,3
1/3,3,1,3,3,1,1,5,3
1/5,1/5,1/3,2,1/2,1/5,1/5,1,1/5
1/3,3,1/3,5,3,1/3,1/3,5,1

# 第二层级各判断矩阵
1,0.33
0.67,1

1,0.33
0.67,1

1,0.67
0.33,1

1,0.7
0.3,1

1,0.6
0.4,1

1,0.8
0.2,1

1,0.2
0.8,1

1,0.3
0.7,1

1,0.9
0.1,1

相关文章

  • 选择困难?不存在的!把决策交给你的 Python

    大选则愁眉苦脸,小选择焦躁烦心?NoNoNo... 阿白是从大学刚毕业准备进入社会的应届青年,在找工作的过程中,多...

  • 决策   晨读感悟  20170601

    1. 外在环境干扰 生活中,无处不存在选择,姑且把这种选择就定义为生活中的决策。选择何种积分卡,点怎样的菜,都...

  • 选择困难

    选择困难症,有人说选择困难是因为穷,如果有钱的话,全都要,不存在选择困难:只有大人才做选择题,小孩子全都要。好吧,...

  • 12.11号日课:决策树

    “决策树就是一种把决策节点画成树辅助决策工具,一种选择最优方案的决策方法。” 遇到事情要选择用决策树...

  • 4个自问自答,帮你不再纠结

    李翔及其团队 选择困难 我们常会听到有人说自己有“选择困难症”,很难快速做出决策。“今日心理学(Psycholog...

  • 给你

    我把并不拥有的四季给你 把并不完整的记忆给你 把并不灿烂的笑容给你 把并不快乐的幸福给你 我把并不存在的结果给你 ...

  • 皇帝选择也困难

    还在为选择困难症发愁?三个皇帝来教你 正在为选择困难症发愁?选择与决策从来都不是一件轻松的事,不仅个人如此,就连拥...

  • 做决策,要避免先入为主,兼听则明

    每日一?:《决断力》 ️从来都不存在所谓“正确的选择”,而只有对当下而言“最好的选择”。 1. 做决策≠做决定。做...

  • 22 从会计中的成本来谈谈如何做出明智的选择

    世界上最难的事情莫过于要作出选择,以至于现代社会很多人都患选择困难症。人们之所以觉得作出选择如此困难,是因为做决策...

  • 决策力

    我们在日常生活中有很多时候需要做出选择,也算是小的决策吧,而且有选择困难症的人大有人在,那么该如何去科学的做出决策...

网友评论

    本文标题:选择困难?不存在的!把决策交给你的 Python

    本文链接:https://www.haomeiwen.com/subject/gykwqqtx.html