EntropyWeights.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //
  2. // Created by Austin on 2023/10/10.
  3. //
  4. #include "EntropyWeights.h"
  5. #include <QDebug>
  6. #include <numeric>
  7. #include <cmath>
  8. /**
  9. QVector<QVector<double>> pdata = { { 4.1, 3.9, 5.9, 4.9, 4, 6.1, 8.2, 6.5, 7.5, 6.8,
  10. 7.4, 5.7, 2.4, 2.2, 1.9, 1.8, 15.9, 18.9, 18.8, 16.8 },
  11. { 0.04, 0.08, 0.07, 0.23, 0.14, 0.23, 0.21, 0.13, 0.16, 0.04,
  12. 0.05, 0.08, 0.14, 0.24, 0.11, 0.06, 0.2, 0.09, 0.12, 0.27 },
  13. { 0.19, 0.38, 0.23, 1.03, 0.57, 1.19, 0.88, 0.8, 1.28, 0.17,
  14. 0.33, 0.6, 0.23, 0.35, 0.3, 0.28, 1.05, 0.82, 0.8, 1.74 },
  15. { 0.01, 0.18, 0.04, 0.3, 0.11, 0.47, 0.2, 0.26, 0.88, 0.02,
  16. 0.06, 0.47, 0.04, 0.06, 0.1, 0.1, 0.21, 0.34, 0.39, 1.51 },
  17. { 0.36, 0.19, 0.36, 1.4, 1.12, 0.93, 0.97, 0.52, 0.8, 0.24,
  18. 0.39, 0.46, 0.94, 1.78, 0.5, 0.29, 1.84, 0.58, 0.76, 1.78 },
  19. { 0.05, 0.04, 0.07, 0.09, 0.05, 0.07, 0.1, 0.09, 0.12, 0.11,
  20. 0.1, 0.08, 0.02, 0.02, 0.04, 0.03, 0.12, 0.36, 0.26, 0.32 } };
  21. EntropyWeights ew(pdata);
  22. QVector<double> weights;
  23. QVector<double> score;
  24. ew.compute(weights, score);
  25. qDebug() << score;
  26. qDebug() << weights;
  27. */
  28. EntropyWeights::EntropyWeights(const EntropyMat &mat, const QVector<bool> &direction)
  29. : ymin_(0.002), ymax_(0.996), mat_(mat), direction_(direction)
  30. {
  31. index_num_ = mat_.count();
  32. if (index_num_ == 0) {
  33. sample_num_ = 0;
  34. } else {
  35. sample_num_ = mat_.at(0).count();
  36. }
  37. }
  38. void EntropyWeights::setYMin(double ymin)
  39. {
  40. if (ymin < 0.002) {
  41. ymin_ = 0.002;
  42. } else if (ymin > ymax_) {
  43. return;
  44. }
  45. ymin_ = ymin;
  46. }
  47. void EntropyWeights::setYMax(double ymax)
  48. {
  49. if (ymax > 0.996) {
  50. ymax_ = 0.996;
  51. } else if (ymax < ymin_) {
  52. return;
  53. }
  54. ymax_ = ymax;
  55. }
  56. void EntropyWeights::getWeights(QVector<double> &weights, QVector<double> &score)
  57. {
  58. // 计算第j个指标下,第i个样本占该指标的比重p
  59. EntropyMat pMat;
  60. for (int i = 0; i < mat_.count(); i++) {
  61. pMat.append(QVector<double>(mat_.at(i).count(), 0));
  62. double sum = std::accumulate(mat_.at(i).begin(), mat_.at(i).end(), 0.0);
  63. for (int j = 0; j < mat_.at(i).count(); j++) {
  64. pMat[i][j] = mat_[i][j] / sum;
  65. }
  66. }
  67. double k = 1 / std::log(sample_num_);
  68. // 计算第j个指标熵值
  69. QVector<double> e(mat_.count(), 0);
  70. for (int i = 0; i < mat_.count(); i++) {
  71. // QVector<double> f(mat_.at(i).count(), 0.0);
  72. double fSum = 0;
  73. for (int j = 0; j < mat_.at(i).count(); j++) {
  74. fSum += pMat[i][j] * std::log(pMat[i][j]);
  75. }
  76. e[i] = -k * fSum;
  77. }
  78. // qDebug() << e;
  79. // 计算信息熵冗余度
  80. QVector<double> d(mat_.count(), 0);
  81. for (int i = 0; i < e.count(); i++) {
  82. d[i] = 1 - e[i];
  83. }
  84. // 求权值
  85. double dSum = std::accumulate(d.begin(), d.end(), 0.0);
  86. for (auto v : d) {
  87. weights.append(v / dSum);
  88. }
  89. for (int i = 0; i < sample_num_; ++i) {
  90. double s = 0;
  91. for (int j = 0; j < index_num_; j++) {
  92. s += pMat[j][i] * weights[j];
  93. }
  94. score.append(s * 100);
  95. }
  96. }
  97. /**
  98. * 实现正向或负向指标归一化,返回归一化后的数据矩阵
  99. */
  100. void EntropyWeights::normalization()
  101. {
  102. for (int i = 0; i < mat_.count(); i++) {
  103. double minValue = 0;
  104. double maxValue = 0;
  105. getMinMax(mat_.at(i), minValue, maxValue);
  106. bool dir = true;
  107. if (!direction_.isEmpty()) {
  108. dir = direction_.at(i);
  109. }
  110. if (dir) {
  111. for (int j = 0; j < mat_.at(i).count(); j++) {
  112. mat_[i][j] = (ymax_ - ymin_) * (mat_.at(i).at(j) - minValue) / (maxValue - minValue) + ymin_;
  113. }
  114. } else {
  115. for (int j = 0; j < mat_.at(i).count(); j++) {
  116. mat_[i][j] = (ymax_ - ymin_) * (maxValue - mat_.at(i).at(j)) / (maxValue - minValue) + ymin_;
  117. }
  118. }
  119. }
  120. }
  121. void EntropyWeights::getMinMax(const QVector<double> &in, double &min, double &max)
  122. {
  123. if (in.count() > 0) {
  124. min = max = in.at(0);
  125. for (int i = 1; i < in.count(); i++) {
  126. if (in.at(i) < min) {
  127. min = in.at(i);
  128. } else if (in.at(i) > max) {
  129. max = in.at(i);
  130. }
  131. }
  132. }
  133. }
  134. void EntropyWeights::compute(QVector<double> &weights, QVector<double> &score)
  135. {
  136. normalization();
  137. // qDebug() << mat_;
  138. getWeights(weights, score);
  139. // qDebug() << "mat_" << mat_;
  140. }