熵值法



概述

熵值法是基於信息熵(或簡稱熵)的一種信息管理方法。根據熵的特性,可以據此判斷出一個事件的隨機性以及無序程度,也可以基於熵值判斷某個指標的離散程度。離散程度越大,即信息量越大,不確定性就越小,熵也就越小;信息量越小,不確定性越大,熵也越大。基於該思想,熵值法只考慮數據內部的信息量大小,有效地避免了人為主觀因素的影響。

熵值法原理及實例講解

參考:熵值法原理及實例講解

步驟:
(1). 數據的非負化處理;
(2). 計算第j個指標下第i個方案占該指標的比重;
(3). 計算第j箱指標的熵值
注:上述鏈接中存在一處錯去:這里的常數k=1/ln(n).n表示樣本個數,而不是指標個數。
(4). 計算第j項指標的差異系數;
(對於第j箱指標,指標值的差異越大,對方案評價的作用越大,熵值就越小。)
(5). 求權數:保證權重之和為1;
(6). 計算各方案的得分。


案例文獻鏈接

代碼實現

# -*- coding=utf-8-*-
# author :Han X.Y


import pandas as pd
from sklearn.preprocessing import MinMaxScaler
import math


class EntropyWeights:
    """
    這個類用來實現熵值法
    """

    def __init__(self, store_path=None, data=None, vars_num=None, maxValue_vars=None,
                 minValue_vars=None):
        """
        初始化
        :param store_path: 數據文件的存儲路徑
        :param data: 若無需導數據,則可指定到具體數據集
        :param vars_num: 變量個數,默認是從前往后看
        :param maxValue_vars: 高優指標個數
        :param minValue_vars: 低優指標個數
        """
        # 高優指標
        self.maxValue_vars = maxValue_vars
        # 低優指標
        self.minValue_vars = minValue_vars
        # 原始指標名稱
        self.raw_var_names = None
        # 原始指標個數
        self.vars_num = vars_num
        # 基礎數據集的存儲路徑
        self.raw_data_store_path = store_path
        self.raw_data = data

    def getReadData(self):
        """
        讀入原始數據
        :return:
        """
        if self.raw_data is None:
            data = pd.read_csv(self.raw_data_store_path, encoding='utf-8', index_col=0)
            self.raw_data = data
        data = self.raw_data
        data_colnames = data.columns
        if self.vars_num is None or \
                self.maxValue_vars is None or \
                self.minValue_vars is None:
            print("請輸入關鍵參數{vars_num,maxValue_vars,minValue_vars}")
        # 其他
        self.raw_var_names = data_colnames[:self.vars_num]  # 變量指標
        # self.maxValue_vars = self.raw_var_names[:2]  # 高優指標
        # self.minValue_vars = self.raw_var_names[2:]  # 低優指標
        # self.vars_num = len(data_colnames[:-1])  # 總的指標個數
        # 基礎數據
        self.raw_data = data
        # 非負化數據
        self.non_neg_data = None
        self.k = None
        # 熵值
        self.entropy_values = None
        # 變異系數
        self.G_values = None
        # 最終的權重
        self.final_weights = None

    def precess_1_to_NNeg(self):
        """
        進行非負化處理
        :return:
        """
        data = self.raw_data
        colnames = self.raw_var_names
        # tmp_data = data.copy()
        # for name in colnames:
        #     tmp_data = tmp_data[tmp_data[name] > 0]
        # if tmp_data.shape[0] == data.shape[0]:
        #     print(f"不存在負數,不需要進行非負化處理")
        #     self.non_neg_data = data[self.raw_var_names]
        # else:
        scaler = MinMaxScaler().fit(data[self.raw_var_names])
        tmp_data = pd.DataFrame(scaler.transform(data[self.raw_var_names]), columns=self.raw_var_names,
                                index=self.raw_data.index)
        print("tmp_data", tmp_data)
        # 低優指標的計算方法與高優指標的計算不同
        if len(self.minValue_vars) > 0:
            for name in self.minValue_vars:
                tmp_data[name] = tmp_data[[name]].apply(lambda x: 1 - x, axis=0)
            print("分高優指標、和低優指標進行非負化處理")
            self.non_neg_data = tmp_data
        else:
            self.non_neg_data = tmp_data

    def calElementsProAndEntropy(self):
        """
        計算各元素的比重和熵值
        :return:
        """
        self.k = 1 / math.log(self.raw_data.shape[0])  # 計算常數k
        data = self.non_neg_data.copy()
        for name in self.raw_var_names:
            data[name] = data[[name]].apply(lambda x: (x + 1) / sum(x + 1), axis=0)

        # 計算熵值
        for name in self.raw_var_names:
            data[name] = data[name].apply(lambda x: -(self.k * x * math.log(x)))

        # 不同指標的熵值
        entropy_list = data.apply(sum, axis=0).to_list()
        self.entropy_values = entropy_list
        print("".center(100, "="))
        print(f"熵值:\n \t {entropy_list}")
        print("".center(100, "="))

        # 變異系數
        G_list = [1 - i for i in entropy_list]
        self.G_values = G_list
        print("".center(100, "="))
        print(f"變異系數:\n \t {G_list}")
        print("".center(100, "="))

        # 最終的權重
        weights = [round(i / sum(G_list), 4) for i in G_list]
        self.final_weights = dict([(i, j) for i, j in zip(self.raw_var_names, weights)])
        print("".center(100, "="))
        print(f"最終的權重:\n \t {self.final_weights}")
        print("".center(100, "="))

    def calTotalScores(self):
        """
        計算綜合得分指標
        :return:
        """
        data = self.non_neg_data
        # scores = data.apply(lambda x, y: x, self.final_weights, axis=0)
        scores = data.apply(lambda x: sum([i * j for i, j in zip(x, self.final_weights.values())]), axis=1).to_list()
        # print(f'綜合得分:{scores}')
        self.raw_data['Total_Scores'] = scores
        print("熵值法計算完畢!".center(50, "*"))

    def main(self):
        """
        實現熵值法
        :return:
        """
        print("熵值法計算:".center(100, "*"))
        print("".center(100, "="))
        self.getReadData()
        self.precess_1_to_NNeg()
        self.calElementsProAndEntropy()
        self.calTotalScores()
        print("".center(100, "="))
        print("熵值法計算完畢!".center(100, "*"))

if __name__ == '__main__':
    test = EntropyWeights()
    test.main()




測試:測試數據來源於上述某參考文獻案例:

A=[[85,70,20,20],
  [70,70,60,50],
  [80,60,80,90]]
A=pd.DataFrame(A,index=['A',"B","C"],columns=['甲','乙','丙',''])
test2=EntropyWeights(data=A,vars_num=4,maxValue_vars=['甲','乙','丙','丁'],minValue_vars=[])
test2.main()

測試輸出:

***********************************************熵值法計算:***********************************************
====================================================================================================
熵值:[0.9657130652315669, 0.9602297178607612, 0.9657130652315666, 0.9648412112801078]
變異系數:[0.03428693476843314, 0.03977028213923883, 0.034286934768433364, 0.0351587887198922]
最終的權重:{'甲': 0.2389, '乙': 0.2771, '丙': 0.2389, '': 0.245}
綜合得分:[0.31812579451118506, 0.3255810212000094, 0.32017663843929145]
*********************熵值法計算完畢!*********************
====================================================================================================
**********************************************熵值法計算完畢!**********************************************




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM