熵权法计算权重(java版)

前言:熵权法,也称为熵决法,客观求权重比,在评价类模型中相对比较简单。根据已知评价对象 指标的数值来确定每个指标所占的权重,在相对数据集合中,以算法的形式剔除主观因素,以客观的方式获取到相关权重。

适用场景:(纯个人经验)

1,每个对象会有几个指标。这几个指标哪个指标所占的权重最大呢?

(指标数相当或相差不大。最好是同类指标在不同源数据下形成的数据集合。)

2,指标数大于2.

一、算法结果展示: 

指标1指标1指标1加权平均法熵决法
65.00 64.71 100.00 76.57 9.360619
65.00 52.94 39.31 9.781944
100.00 65.00 55.00 9.781944
65.00 100.00 55.00 9.781944
30.00 100.00 64.00 64.67 4.154868
64.00 100.00 54.67 9.781944
65.00 85.00 50.00 9.781944
79.79 66.00 48.60 9.781944
40.00 99.00 46.33 9.781944
70.59 64.00 44.86 9.781944
65.00 60.00 70.00 65.00 4.11448
100.00 95.00 105.00 100.00 4.11448

二、算法理论

原文链接:https://blog.csdn.net/qq_41686130/article/details/81867400

2.1,数据标准化

假设给定了k个指标,其中。假设对各指标数据标准化后的值为

那么

                           

2.2,求各指标的信息熵

根据信息论中信息熵的定义,一组数据的信息熵

其中,如果,则定义    

2.3,确定各指标权重

根据信息熵的计算公式,计算出各个指标的信息熵为 。通过信息熵计算各指标的权重:

                                                     

2.4,指标缺失(为0)或为负问题

可以使用数据平移法,即所有指标都加上一个平移值x,再参与计算,平移值x不管大小,计算结果一样。

三、java代码

3.1,pom引入

        <!-- 集成hutool工具类简便操作 -->
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.3.10</version>
		</dependency>
        <dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-math3</artifactId>
			<version>3.6.1</version>
		</dependency>

3.2,核心类:


import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;

public class ShangFactory {
	private List<List<Double>> readyList;
	private Integer maxNum = 0; // 最大位数
	private Double pvg = 100.0; // 平移数值

	public ShangFactory(List<List<Double>> dataList) {
		getMaxNum(dataList);
		readyList = new ArrayList<List<Double>>();
		tranData(dataList);
	}

	public List<Double> listWeight() {
		System.err.println("平移标准化:" + readyList);
		// 完成数据标准化
		List<List<Double>> aveList = orderData(readyList);
		System.err.println("数据标准化:" + aveList);

		List<Double> shangList = listShang(readyList, aveList);
		// 获取信息熵
		System.err.println("信息熵:" + shangList);
		List<Double> weightList = makeWeight(shangList);
		return weightList;
	}

	// 获取最大位数和平移均值
	private void getMaxNum(List<List<Double>> dataList) {
		for (List<Double> list : dataList) {
			if (list.size() > maxNum) {
				maxNum = list.size();
			}
			double ws = 0.0;
			for (Double w : list) {
				if (w<pvg) {
					pvg=w;
				}
				ws = ws + w;
			}
			pvg = pvg + (ws / list.size());
		}
		pvg = pvg / dataList.size();
	}

	/**
	 * 用平移法,补全缺位数据
	 * 
	 * @param dataList
	 * @return
	 */
	private void tranData(List<List<Double>> dataList) {
		List<Double> dataNumList;
		for (List<Double> list : dataList) {
			dataNumList = new ArrayList<Double>();
			for (Double weight : list) {
				dataNumList.add(weight + pvg);
			}
			// 补全
			for (int i = 0; i < maxNum - list.size(); i++) {
				dataNumList.add(pvg);
			}
			readyList.add(dataNumList);
		}
	}
	
	/**
	 * 2.1,数据标准化
	 * @param dataList
	 * @return
	 */
	private List<List<Double>> orderData(List<List<Double>> dataList) {
		List<List<Double>> aveList = new ArrayList<List<Double>>();
		// 数据归一化处理 (i-min)/(max-min)
		List<Double> numList;
		List<Double> dataNumList;
		double min, diff, temp;
		for (int i = 0; i < dataList.size(); i++) {
			numList = dataList.get(i);
			min = (double) CollUtil.min(numList);
			diff = CollUtil.max(numList) - min;
			dataNumList = new ArrayList<Double>();
			for (int j = 0; j < numList.size(); j++) {
				temp = ((double) numList.get(j) - min) / diff;
				dataNumList.add(j, temp);
			}
			aveList.add(dataNumList);
		}

		return aveList;
	}
	/**
	 * 2.2,求各指标的信息熵
	 * @param dataList
	 * @param aveList
	 * @return
	 */
	private List<Double> listShang(List<List<Double>> dataList, List<List<Double>> aveList) {
		List<Double> shangList = new ArrayList<Double>();
		for (int i = 0; i < aveList.size(); i++) {
			List<Double> aveNumList = aveList.get(i);
			double pSum = (double) aveNumList.stream().reduce((x, y) -> (double) x + (double) y).get();
			double sum = 0;
			for (int j = 0; j < aveList.get(i).size(); j++) {
				double p = (double) aveNumList.get(j) / pSum;
				if (p != 0) {
					sum = sum + p * Math.log(p);
				}
			}
			shangList.add((-1) / Math.log(dataList.get(i).size()) * sum);
		}
		return shangList;
	}
	/**
	 * 2.3,确定各指标权重
	 * @param shangList
	 * @return
	 */
	private static List<Double> makeWeight(List<Double> shangList) {
		List<Double> weightList = new ArrayList<Double>();
		Double shangSum = shangList.stream().reduce(Double::sum).get();
		double weight;
		for (int i = 0; i < shangList.size(); i++) {
			weight = (1 - shangList.get(i)) / (shangList.size() - shangSum);
			weight = weight * 100.0;
//			BigDecimal weightDec = NumberUtil.round(weight, 6);
			weightList.add(NumberUtil.round(weight, 6).doubleValue());
		}
		return weightList;
	}
}

3.3,测试类

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import cn.hutool.core.util.NumberUtil;

public class ShangTest {

	public static void main(String[] args) {
		List<List<Double>> dataList = readyData();
		ShangFactory shangFactory=new ShangFactory(dataList);
		List<Double> weightList = shangFactory.listWeight();

		// 获取权重
		System.err.println("权重:" + weightList);
		for (Double double1 : weightList) {
			System.out.println(double1);
		}
	}
	private static List<List<Double>> readyData() {
		String dataStr = "[100.0, 83.33, 75.0], [83.33, 72.86, 70.0], [85.0, 66.0, 64.53, 5.0], [99.0, 55.0, 40.0, 17.17], [75.0, 65.53, 52.18], [70.0, 64.53, 33.0, 23.19], [75.0, 70.53, 28.99], [85.0, 83.33], [75.0, 64.53, 28.13], [75.0, 66.53], [75.0, 57.97], [83.33, 25.0], [100.0], [64.53, 34.38], [66.67, 31.25], [66.67, 25.0], [85.71], [83.33], [83.33], [83.33], [75.0], [75.0], [75.0], [75.0], [71.43], [65.53], [65.53], [64.53], [34.38]";
		List<List<Double>> dataList = new ArrayList<List<Double>>();
		List<String> list = Arrays.asList(dataStr.split("],"));
		List<Double> dataNumList;
		for (String string : list) {
			string = string.replace("[", "");
			string = string.replace("]", "");
			dataNumList = new ArrayList<Double>();
			List<String> numList = Arrays.asList(string.split(","));
			for (String numStr : numList) {
				dataNumList.add(NumberUtil.parseNumber(numStr.trim()).doubleValue());
			}
			dataList.add(dataNumList);
		}
		return dataList;
	}
}

测试类中数据集是根据生产环境打印出来,也可以使用excle中导入,方便测试。

最后总结:因场景选择错误,此方法是一个失败案例。但是此方法相当不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冬山兄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值