Просмотр исходного кода

更新PCA

Signed-off-by: codeClown <zhaomengshou@126.com>
codeClown 1 год назад
Родитель
Сommit
dd3bed1b5c
2 измененных файлов с 53 добавлено и 10 удалено
  1. 44 9
      QFD/algorithm/PCA.cpp
  2. 9 1
      QFD/algorithm/PCA.h

+ 44 - 9
QFD/algorithm/PCA.cpp

@@ -60,8 +60,8 @@ static void computeEig(MatrixXd &C, MatrixXd &vec, MatrixXd &val)
     val = eig.eigenvalues();
 }
 
-// 计算压缩成多少维数据损失小于95%
-static int computeDim(MatrixXd &val)
+// 计算压缩成多少维数据损失小于thd
+static int computeDim(MatrixXd &val, double thd)
 {
     int dim;
     double sum = 0;
@@ -69,7 +69,7 @@ static int computeDim(MatrixXd &val)
         sum += val(i, 0);
         dim = i;
 
-        if (sum / val.sum() >= 0.95)
+        if (sum / val.sum() >= thd)
             break;
     }
     return val.rows() - dim;
@@ -109,20 +109,35 @@ void PCA::compute()
     // 计算特征值和特征向量
     computeEig(C, vec, val);
 
-    // 问题,特征顺序好像有问题,对不上指标顺序
-    //     std::cout << vec << std::endl;
-    //     std::cout << val << std::endl;
+    // 从小到大
+    //    std::cout << vec << std::endl;
+    //    std::cout << val << std::endl;
 
     // 计算损失率,确定降低维数(原本的n维向量即降低到dim维向量)
-    int k = computeDim(val);
+    int k = computeDim(val, variance_remain_);
+    //    qDebug() << "计算出压缩后的维度为:" << k;
 
-    qDebug() << "计算出压缩后的维度为:" << k;
+    contribution_rate_ = val / val.sum();
 
     // 定义投影矩阵V
     MatrixXd V(C.cols(), k);
     // 投影矩阵的值为特征向量矩阵的前k维
     V = vec.rightCols(k);
+    std::cout << "qian k wei: " << V << std::endl;
 
+    MatrixXd normalRate(k, contribution_rate_.cols());
+    normalRate = contribution_rate_.bottomRows(k);
+    // 归一化
+    normalRate = normalRate / normalRate.sum();
+
+    scores_  = MatrixXd::Zero(normalRate.rows(), 1);
+    scores_  = V * normalRate;
+    weights_ = MatrixXd::Zero(normalRate.rows(), 1);
+    weights_ = scores_ / scores_.sum();
+    //    std::cout << "scores_" << scores_ << std::endl;
+    //    std::cout << "weights_" << weights_ << std::endl;
+
+#if 0
     // 计算结果:把原始数据进行投影,每个数据点m维向量投影成k维向量
     MatrixXd res = X * V;
 
@@ -133,5 +148,25 @@ void PCA::compute()
     // 样本每个维度都加上均值就是解压缩样本
     Y.rowwise() += meanvecRow;
 
-    //    std::cout << Y << std::endl;
+#endif
+}
+
+QVector<double> PCA::weights() const
+{
+    QVector<double> res;
+    for (int r = 0; r < weights_.rows(); ++r) {
+        res << weights_(r, 0);
+    }
+
+    return res;
+}
+
+QVector<double> PCA::scores() const
+{
+    QVector<double> res;
+    for (int r = 0; r < scores_.rows(); ++r) {
+        res << scores_(r, 0);
+    }
+
+    return res;
 }

+ 9 - 1
QFD/algorithm/PCA.h

@@ -7,10 +7,14 @@
 class PCA
 {
 public:
-    PCA(const QVector<QVector<double>> &source, double thd);
+    PCA(const QVector<QVector<double>> &source, double thd = 0.85);
 
     void compute();
 
+    QVector<double> weights() const;
+
+    QVector<double> scores() const;
+
 private:
     Eigen::MatrixXd X;  // 输入矩阵
     Eigen::MatrixXd C;  // 协方差矩阵
@@ -18,6 +22,10 @@ private:
     double variance_remain_;
     int rows_;
     int cols_;
+
+    Eigen::MatrixXd contribution_rate_;  // 特征贡献率
+    Eigen::MatrixXd scores_;             // 指标综合得分系数
+    Eigen::MatrixXd weights_;            // 指标权重
 };
 
 #endif  // PCA_H