利用熵权法进行数值评分计算——代码实现

1、前情回顾

之前的文章,我们详细介绍了熵权法的具体计算过程(不清楚的读者可点击此处的传送门《利用熵权法进行数值评分计算——算法过程》)。本篇文章我们展示熵权法的主要实现代码(Java版本,实际上Python、GoLang等逻辑是相同的,之后会提供GoLang版本的代码)。

2、具体计算过程

本文的介绍将通过以下示例场景进行:

// 指标数量
int pointNumber = 6;
// 行表示每个参与者的数据,列表示每一个评分指标
double points[][] = new double[][] {{0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 4.0},{1.0 , 2.0 , 0.0 , 0.0 , 0.0 , 3.0},{2.0 , 0.0 , 0.0 , 0.0 , 0.0 , 3.0},{1.0 , 0.0 , 1.0 , 0.0 , 2.0 , 4.0},{3.0 , 0.0 , 0.0 , 0.0 , 1.0 , 4.0},{1.0 , 1.0 , 0.0 , 1.0 , 0.0 , 4.0},{0.0 , 1.0 , 1.0 , 1.0 , 1.0 , 5.0}};
// 如果为true,表示是正向指标;反之则是负向指标
boolean forwards[] = new boolean [] {false , false , false , false , false , true};

从以上代码中我们知道了,评分参与者有7人(或者理解成7个品牌的车、7款电视信号,等等)。评分指标一共有6个,其中除了最后第6个指标外,其余指标都是负向指标。

2.1、首先进行数据标准化

/*** 数据标准化,主要是区分正向因子和负向因子,进行数据标准化,以便进行下一步计算* (这里修正了一下,保证结果不可能出现分母为0的情况)* @param points 原始数据数组* @param index 需要进行标准化的原始数据的索引位置* @param forward 是否是正向因子* @return 返回的标准化之后的数值*/
private static double standard(double points[] , int index , boolean forward) {if(index < 0 || index > points.length - 1) {throw new IllegalArgumentException("错误的参数");}double max = new Max().evaluate(points);double min = new Min().evaluate(points);// 正向指标double result = 0.0;if(forward) {result = (points[index] - min + 1) / (max - min + 1);} else {result = (max - points[index] + 1) / (max - min + 1);}return result;
}// 下面开始进行矩阵的标准化
// 数据标准化后的对应矩阵,存储在这里
double standards[][] = new double[points.length][pointNumber];
// 数据标准化,正向因子和负向因子的标准化要求不一样
for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(points, index);for(int matrixIndex = 0 ; matrixIndex < matrixs.length ; matrixIndex++) {double matrixStandard = standard(matrixs, matrixIndex, forwards[index]);standards[matrixIndex][index] = matrixStandard;}
}

请注意以上代码标段中得到的标准化之后的矩阵standards,后续的计算步骤主要就是使用这个standards矩阵进行。另外注意,为了程序员编码过程的方便,我们在进行每个指标数据标准化前,可以对矩阵的一部分进行翻转,代码片段如下:

/*** 矩阵翻转,矩阵翻转的目的,是确保计算方便* @param matrixs 原始数据矩阵(二维矩阵)* @param index 需要翻转的原始矩阵的索引号* @return*/
private static double[] matrixFlipping(double matrixs[][] , int index) {int matrixLen = matrixs.length;double flips[] = new double[matrixLen];for(int lenIndex = 0 ; lenIndex < matrixLen ; lenIndex++) {flips[lenIndex] = matrixs[lenIndex][index];}return flips;
}

数值矩阵的翻转只是为了保证程序员编写代码的便利性,和计算过程没有任何关系。

2.2、求各评分要素的数值比例

接下来,我们用经过数值标准化的矩阵,带入以下代码片段,进行数值比例的计算:

/*** 求数值比例* @param points* @param index 需要求值的原始数据的索引位置* @return */
private static double relatMatrix(double standards[] , int index) {double sum = new Sum().evaluate(standards);double result = standards[index] / sum;return result;
}// 对数值比例的调用执行,如以下代码片段所示
// 比例化后的数据存储在这里
double proportions[][] = new double[standards.length][pointNumber];
for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(standards, index);for(int matrixIndex = 0 ; matrixIndex < matrixs.length ; matrixIndex++) {double matrixStandard = relatMatrix(matrixs, matrixIndex);proportions[matrixIndex][index] = matrixStandard;}
}

请注意以上代码片段中的proportions矩阵,求得的数值比例值就存储在这里,并且后续继续基于此矩阵进行计算。

2.3、求对数

求对数的方法如下代码片段所示:

// 求对数
double lnMatrixs[][] = new double[standards.length][pointNumber];
for(int index = 0 ; index < proportions.length ; index++) {double matrixItems[] = proportions[index];for(int matrixIndex = 0 ; matrixIndex < matrixItems.length ; matrixIndex++) {double lnResult = matrixItems[matrixIndex] * Math.log(matrixItems[matrixIndex]);lnMatrixs[index][matrixIndex] = lnResult;}
}

注意,以上求对数的过程引入了Java原生的求对数计算工具。另外,求得的对数值,被放置在lnMatrixs这个数值矩阵中。

2.4、求每一个评分要素的熵值


/*** 计算某一个数组的熵值* @param matrixs* @return*/
private static double entropyMatrix(double matrixs[]) {double result = (-1 * 1 / Math.log(matrixs.length)) * (new Sum().evaluate(matrixs));return result;
}// 计算熵值的代码如下所示
// 其中n表示参与评分的数据条数
double entropys[] = new double[pointNumber];
for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(lnMatrixs, index);double entropy = entropyMatrix(matrixs);entropys[index] = entropy;
}
// 根据熵求权值
double entropyWeights[] = new double[pointNumber];
for(int index = 0 ; index < pointNumber ; index++) {double weight = relatMatrix(entropys, index);entropyWeights[index] = weight;
}

注意以上代码片段中,除了调用了求每个要素熵值的matrixFlipping方法外,还调用了求数值比例的relatMatrix方法。这是因为熵值也要进行占比计算。

2.5、计算基准得分和使用者能看懂的百分制得分

现在开始计算基准得分,并基于基准得分计算得到百分制得分。

// 基于熵权进行每一个评分参与者的基准得分
double benchScores[] = new double[standards.length];
for(int index = 0 ; index < standards.length ; index++) {double standardItems[] = standards[index];double result = 0d;for(int weightIndex = 0 ; weightIndex < entropyWeights.length ; weightIndex++) {result += standardItems[weightIndex] * entropyWeights[weightIndex];}benchScores[index] = result;
}// 转换成百分数
Double percentageScores[] = new Double[standards.length];
for(int index = 0 ; index < standards.length ; index++) {percentageScores[index] = percentageScores(benchScores, index);
}
System.out.println("percentageScores = " + StringUtils.join(percentageScores, " | "));/*** 转换为100分制* @param benchScores* @param index 要将哪一个基准数转换为100分制* @return*/
private static double percentageScores(double benchScores[] , int index) {int len = benchScores.length;Double maxScore = new Max().evaluate(benchScores);Double maxScaleScore = new BigDecimal(maxScore.toString()).setScale(2, RoundingMode.UP).doubleValue();Double total = (100 * len) / (maxScaleScore * len) * benchScores[index];return new BigDecimal(total.toString()).setScale(2, RoundingMode.HALF_UP).doubleValue();
}

以下是针对最原始评分项,经过熵权法评分后的计算结果:

percentageScores = 98.99 | 84.68 | 92.72 | 81.45 | 87.93 | 87.78 | 82.91

以上计算结果中,第一个参与者的百分制得分是98.99;第二个参与者的百分制得分是84.68;以此类推。

3、总结说明

这里我们给出完整的代码片段,有需要的读者可直接复制粘贴

// 熵权法相关代码——可直接执行
public class EwmTest {public static void main(String[] args) {// 指标数量int pointNumber = 6;// 行表示每个参与者的数据,列表示每一个评分指标double points[][] = new double[][] {{0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 4.0},{1.0 , 2.0 , 0.0 , 0.0 , 0.0 , 3.0},{2.0 , 0.0 , 0.0 , 0.0 , 0.0 , 3.0},{1.0 , 0.0 , 1.0 , 0.0 , 2.0 , 4.0},{3.0 , 0.0 , 0.0 , 0.0 , 1.0 , 4.0},{1.0 , 1.0 , 0.0 , 1.0 , 0.0 , 4.0},{0.0 , 1.0 , 1.0 , 1.0 , 1.0 , 5.0}};// 如果为true,表示是正向指标;反之则是负向指标boolean forwards[] = new boolean [] {false , false , false , false , false , true};// 数据标准化后的对应矩阵,存储在这里double standards[][] = new double[points.length][pointNumber];// 数据标准化,正向因子和负向因子的标准化要求不一样for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(points, index);for(int matrixIndex = 0 ; matrixIndex < matrixs.length ; matrixIndex++) {double matrixStandard = standard(matrixs, matrixIndex, forwards[index]);standards[matrixIndex][index] = matrixStandard;}}// 接着求各列的数值比例,比例化后的数据存储在这里double proportions[][] = new double[standards.length][pointNumber];for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(standards, index);for(int matrixIndex = 0 ; matrixIndex < matrixs.length ; matrixIndex++) {double matrixStandard = relatMatrix(matrixs, matrixIndex);proportions[matrixIndex][index] = matrixStandard;}}// 求对数double lnMatrixs[][] = new double[standards.length][pointNumber];for(int index = 0 ; index < proportions.length ; index++) {double matrixItems[] = proportions[index];for(int matrixIndex = 0 ; matrixIndex < matrixItems.length ; matrixIndex++) {double lnResult = matrixItems[matrixIndex] * Math.log(matrixItems[matrixIndex]);lnMatrixs[index][matrixIndex] = lnResult;}}// 计算熵值,其中n表示参与评分的数据条数double entropys[] = new double[pointNumber];for(int index = 0 ; index < pointNumber ; index++) {double matrixs[] = matrixFlipping(lnMatrixs, index);double entropy = entropyMatrix(matrixs);entropys[index] = entropy;}// 根据熵求权值double entropyWeights[] = new double[pointNumber];for(int index = 0 ; index < pointNumber ; index++) {double weight = relatMatrix(entropys, index);entropyWeights[index] = weight;}// 基于熵权进行每一个评分参与者的基准得分double benchScores[] = new double[standards.length];for(int index = 0 ; index < standards.length ; index++) {double standardItems[] = standards[index];double result = 0d;for(int weightIndex = 0 ; weightIndex < entropyWeights.length ; weightIndex++) {result += standardItems[weightIndex] * entropyWeights[weightIndex];}benchScores[index] = result;}// 转换成百分数Double percentageScores[] = new Double[standards.length];for(int index = 0 ; index < standards.length ; index++) {percentageScores[index] = percentageScores(benchScores, index);}System.out.println("percentageScores = " + StringUtils.join(percentageScores, " | "));}/*** 转换为100分制* @param benchScores* @param index 要将哪一个基准数转换为100分制* @return*/private static double percentageScores(double benchScores[] , int index) {int len = benchScores.length;Double maxScore = new Max().evaluate(benchScores);Double maxScaleScore = new BigDecimal(maxScore.toString()).setScale(2, RoundingMode.UP).doubleValue();Double total = (100 * len) / (maxScaleScore * len) * benchScores[index];return new BigDecimal(total.toString()).setScale(2, RoundingMode.HALF_UP).doubleValue();}/*** 计算某一个数组的熵值* @param matrixs* @return*/private static double entropyMatrix(double matrixs[]) {double result = (-1 * 1 / Math.log(matrixs.length)) * (new Sum().evaluate(matrixs));return result;}/*** 求数值比例比例* @param points* @param index 需要求值的原始数据的索引位置* @return */private static double relatMatrix(double standards[] , int index) {double sum = new Sum().evaluate(standards);double result = standards[index] / sum;return result;}/*** 矩阵翻转,矩阵翻转的目的,是确保计算方便* @param matrixs 原始数据矩阵(二维矩阵)* @param index 需要翻转的原始矩阵的索引号* @return*/private static double[] matrixFlipping(double matrixs[][] , int index) {int matrixLen = matrixs.length;double flips[] = new double[matrixLen];for(int lenIndex = 0 ; lenIndex < matrixLen ; lenIndex++) {flips[lenIndex] = matrixs[lenIndex][index];}return flips;}/*** 数据标准化,主要是区分正向因子和负向因子,进行数据标准化,以便进行下一步计算(这里修正了一下,导致结果不可能为0)* @param points 原始数据数组* @param index 需要进行标准化的原始数据的索引位置* @param forward 是否是正向因子* @return 返回的标准化之后的数值*/private static double standard(double points[] , int index , boolean forward) {if(index < 0 || index > points.length - 1) {throw new IllegalArgumentException("错误的参数");}double max = new Max().evaluate(points);double min = new Min().evaluate(points);// 正向指标double result = 0.0;if(forward) {result = (points[index] - min + 1) / (max - min + 1);} else {result = (max - points[index] + 1) / (max - min + 1);}return result;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/53347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMq中交换机(Exchange)、队列(Queue)和路由键(Routing Key)

RabbitMQ 是一个消息代理系统&#xff0c;使用交换机&#xff08;Exchange&#xff09;、队列&#xff08;Queue&#xff09;和路由键&#xff08;Routing Key&#xff09;来管理消息的传递。它们分别起到不同的作用&#xff0c;构成了消息从生产者到消费者的传递路径。 以下是…

音视频入门基础:FLV专题(1)——FLV官方文档下载

一、FLV简介 Flash Video&#xff08;简称FLV&#xff09;&#xff0c;是一种网络视频格式&#xff0c;用作流媒体格式&#xff0c;它的出现有效地解决了视频文件导入Flash后&#xff0c;使导出的SWF文件体积庞大&#xff0c;不能在网络上有效使用等缺点。 一般FLV文件包在SW…

远程连接MySQL并操作

配置MySQL开发环境 如果你使用的是基于Debian的系统&#xff08;如Ubuntu&#xff09;&#xff0c;可以在终端通过如下步骤安装MySQL开发包。 更新软件包列表 运行以下命令以确保你拥有最新的软件包列表。 sudo apt-get update安装libmysqlclient-dev开发包 执行以下命令以…

【Java注解】

Java注解&#xff08;Annotation&#xff09;让其他程序根据注解信息来决定怎么执行该程序。 是Java 5中引入的一种特殊类型的注释&#xff0c;它可以被用来为代码添加元数据&#xff0c;即关于代码的数据。 注解不会改变程序的逻辑&#xff0c;但它们可以被其他程序使用&…

Datawhale X 南瓜书 task02学习笔记

算法原理引入 样本点通常应该在模型的2侧&#xff0c;原因&#xff1a;在实际中&#xff0c;因为某种不可控的因素&#xff0c;测出来的样本点肯定是有误差的。如果样本数据点都在模型上&#xff0c;则说明在建立模型时&#xff0c;把误差也考虑进去了&#xff0c;这就是我们说…

【技术解析】消息中间件MQ:从原理到RabbitMQ实战(深入浅出)

文章目录 【技术解析】消息中间件MQ&#xff1a;从原理到RabbitMQ实战(深入浅出)1.简介1.1 什么是消息中间件1.2 传统的http请求存在那些缺点1.3 Mq应用场景有那些1.4 为什么需要使用mq1.5 Mq与多线程之间区别1.6 Mq消息中间件名词1.7主流mq区别对比1.8 Mq设计基础知识 2.Rabbi…

前端框架Vue、React、Angular、Svelte对比

在对比 React、Vue.js、Angular 和 Svelte 时&#xff0c;除了在高层次的特性上有显著差异&#xff0c;它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架&#xff0c;我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…

Golang | Leetcode Golang题解之第415题字符串相加

题目&#xff1a; 题解&#xff1a; func addStrings(num1 string, num2 string) string {add : 0ans : ""for i, j : len(num1) - 1, len(num2) - 1; i > 0 || j > 0 || add ! 0; i, j i - 1, j - 1 {var x, y intif i > 0 {x int(num1[i] - 0)}if j &g…

【Unity链接数据库01】Unity使用Oracle 数据库完成登录注册功能

业务需求&#xff1a; 我现在需要在Unity 中创建一个登录功能我有以下业务需求&#xff1a; 1.用户可以注册账号密码 2.用户可以登录 3.使用Oracle 数据库表存储 4.我有一个服务器 地址已经安装了oracle 数据库 5.创建一个数据库用户 &#xff0c;账号密码 为Unity/ Unity …

Oracle 数据库常用命令与操作指南

Oracle 数据库是企业级系统中常用的数据库管理系统&#xff0c;掌握基础的命令可以让你在日常管理中更加高效。本指南将介绍几条常用的 Oracle 数据库命令&#xff0c;涵盖用户权限管理、修改用户密码、删除用户、以及其他日常操作。 目录 授权用户操作权限使用最高权限登录 O…

Spark SQL性能优化高频面试题及答案

目录 高频面试题及答案1. 如何通过分区(Partitioning)优化Spark SQL查询性能?2. 什么是数据倾斜(Data Skew)?如何优化?3. 如何使用广播(Broadcast)优化Join操作?4. 如何优化Spark SQL的Shuffle操作?5. 如何通过缓存(Cache)优化Spark SQL的性能?6. 如何使用合适的…

ChatGPT 4o 使用指南 (9月更新)

首先基础知识还是要介绍得~ 一、模型知识&#xff1a; GPT-4o&#xff1a;最新的版本模型&#xff0c;支持视觉等多模态&#xff0c;OpenAI 文档中已经更新了 GPT-4o 的介绍&#xff1a;128k 上下文&#xff0c;训练截止 2023 年 10 月&#xff08;作为对比&#xff0c;GPT-4…

深度学习自编码器 - 去噪自编码器篇

序言 在深度学习的广阔天地中&#xff0c;自编码器作为一种强大的无监督学习工具&#xff0c;通过重构输入数据的方式&#xff0c;不仅实现了数据的有效压缩&#xff0c;还探索了数据的内在表示。而去噪自编码器&#xff08; Denoising Autoencoder, DAE \text{Denoising Auto…

软件设计师——操作系统

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;软考——软件设计师&#x1f3c5;往期回顾&#x1f3c6;&#xff1a;C: 类和对象&#xff08;上&#xff09;&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱 一、操作系统…

mxnet 的显存分配机制

mxnet 的显存分配机制 MXNet 的显存分配机制在性能优化和资源管理方面起着至关重要的作用。它通过高效的内存管理和调度机制来分配和释放显存&#xff0c;确保在训练深度学习模型时最大限度地利用 GPU 的资源。MXNet 的显存分配机制类似于其他深度学习框架&#xff08;如 PyTo…

VGG16模型实现新冠肺炎图片多分类

1. 项目简介 本项目的目标是通过深度学习模型VGG16&#xff0c;实现对新冠肺炎图像的多分类任务&#xff0c;以帮助医疗人员对患者的影像进行快速、准确的诊断。新冠肺炎自爆发以来&#xff0c;利用医学影像如X光和CT扫描进行疾病诊断已成为重要手段之一。随着数据量的增加&am…

华为---以太网静态路由配置使用下一跳通信正常,而使用出接口无法通信

目录 1. 实验环境 2. 结果测试 3. 分析验证 3.1 以太网静态路由配置使用下一跳跨网段通信抓包分析 3.2 以太网静态路由配置使用出接口跨网段通信抓包分析 3.3 以太网静态路由配置使用出接口无法跨网段通信问题解决办法 1. 实验环境 以太网静态路由配置使用下一跳跨网段通…

网络丢包定位记录(二)

网卡驱动丢包 查看&#xff1a;ifconfig eth1/eth0 等接口 1.RX errors: 表示总的收包的错误数量&#xff0c;还包括too-long-frames错误&#xff0c;Ring Buffer 溢出错误&#xff0c;crc 校验错误&#xff0c;帧同步错误&#xff0c;fifo overruns 以及 missed pkg 等等。 …

Maven的详细解读和配置

目录 一、Maven 1.1 引言 1.2 介绍 1.3 下载安装 1.3.1 解压 1.3.2 配置环境变量 1.3.3 测试 1.4 仓库[了解] 1.5 Maven配置 1.5.1 修改仓库位置 1.5.2 设置镜像 二、IDEA - MAVEN 2.1 idea关联maven 2.2 为新项目设置 2.2 创建java项目[重点] 2.3 java项目结构…

Go-知识-定时器

Go-知识-定时器 1. 介绍2. Timer使用场景2.1 设定超时时间2.2 延迟执行某个方法 3. Timer 对外接口3.1 创建定时器3.2 停止定时器3.3 重置定时器3.4 After3.5 AfterFunc 4. Timer 的实现原理4.1 Timer数据结构4.1.1 Timer4.1.2 runtimeTimer 4.2 Timer 实现原理4.2.1 创建Timer…