主成分分析求指标权重的C#实现


前言

 项目需要,研究了一下主成分分析的c#实现,这里记录一下,也供有需要的朋友学习,主要通过调用Accord.Math程序包实现主成分分析中特征值以及特征向量的计算。
 有关主成分分析计算指标权重的原理可以参考,链接: https://blog.csdn.net/qq_43517528/article/details/119578525.这里不做详细介绍。


一、安装需要的程序包

主要用到了Accord.Math以及Accord.Statistics程序包,安装方法如下:
第一步:打开VS的NuGet包管理器中的管理方案的NuGet程序包。如下图所示。
在这里插入图片描述
第二步,在浏览选项中,输入Accord,如下图所示。
在这里插入图片描述
第三步:选择Accord.Math,勾选右侧的项目后,点击安装。
在这里插入图片描述
第四步:在弹出的对话框中点击确定,等待安装完成。
在这里插入图片描述
第五步:用同样的方法安装Accord.Statistics

二、源程序

这里把主成分分析求指标权重的方法单独写在了一个类中,在主函数中去调用它。

1.PCA函数

代码如下:注意需要引用如下命名空间:
using Accord.Math;
using Accord.Math.Comparers;
using Accord.Math.Decompositions;
using Accord.Statistics;
using Accord.Statistics.Analysis;

using System;
using System.Collections.Generic;
using System.Text;
using Accord.Math;
using Accord.Math.Comparers;
using Accord.Math.Decompositions;
using Accord.Statistics;
using Accord.Statistics.Analysis;

namespace 主成分分析法测试
{
    class PCA_V1
    {
        public bool PcaMethod(double[,] data,ref double []weight)
        {
            double[] temp = new double[data.Rows()];
            double[] temp1 = new double[data.Rows()];
            double[,] data1 = new double[data.Rows(), data.Columns()];//存储处理完后的数据,即各列数据减去均值后除以标准差
            double mean; //一列数据的均值
            double std;//一列数据的方差
            //对数据进行预处理:每一列数据减去均值后除以该列数据的标准差
            for (int i = 0; i < data.Columns(); i++)
            {
                for (int j = 0; j < data.Rows(); j++)
                {
                    temp[j] = data[j, i];
                }
                mean = temp.Mean();
                std = temp.StandardDeviation();
                temp1 = temp.Subtract(mean);
                temp = temp1.Divide(std);
                for (int j = 0; j < data.Rows(); j++)
                {
                    data1[j, i] = temp[j];
                }
            }
            //计算相关系数矩阵
            double[,] cov = data1.Correlation();
            //计算特征值以及特征向量
           try
            {
                var evd = new EigenvalueDecomposition(cov);
                double[] eigenvalues = evd.RealEigenvalues;
                double[,] eigenvectors = evd.Eigenvectors;
                // 对特征向量进行降序排列
                eigenvectors = Accord.Math.Matrix.Sort(eigenvalues, eigenvectors, new GeneralComparer(ComparerDirection.Descending, true));//eigenvalues没有实现降序排序
                //对特征值实现降序排序                                                                                                                           
                for (int i = 0; i < eigenvalues.Length; i++)
                {
                    for (int j = i + 1; j < eigenvalues.Length; j++)
                    {
                        double t = 0;
                        if (eigenvalues[i] < eigenvalues[j])
                        {
                            t = eigenvalues[i];
                            eigenvalues[i] = eigenvalues[j];
                            eigenvalues[j] = t;
                        }
                    }
                }
                //默认信息保留率为0.9,提取该信息保留率下的主成分
                double sum = eigenvalues.Sum();
                double sum1 = 0;
                int k = 0;
                for (int i = 0; i < eigenvalues.Length; i++)
                {
                    sum1 = sum1 + eigenvalues[i] / sum;
                    if (sum1 < 0.9)
                    {
                        k++;
                    }
                    else
                    {
                        k++;  //表示提取了K个主成分
                        break;
                    }
                }
                //计算各指标的权重(计算方法:对指标在各个主成分的线性组合的加权系数做平均)
                double[] weight1 = new double[eigenvalues.Length];
                for (int i = 0; i < eigenvectors.Rows(); i++)
                {
                    double sum_temp = 0;
                    for (int j = 0; j < k; j++)
                    {
                        sum_temp = sum_temp + eigenvectors[i, j] * eigenvalues[j] / sum;
                    }
                    weight1[i] = sum_temp / sum1;
                }
                //对各权重做归一化处理
                //对权重出现负值的处理(一般情况下不会出现负值),处理思路是:若有负权重,找到最小的那个负的权重,--
                //--所有权重值加上这个权重之后进行归一化处理。
                double min_weight;
                min_weight = weight1.Min();
                if (min_weight < 0)
                {
                    weight1 = weight1.Add(-min_weight + 0.01);
                }
                for (int i = 0; i < weight1.Length; i++)
                {
                    weight[i] = weight1[i] / weight1.Sum();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
    
}

2.主函数

在主函数中调用PCA函数,代码如下:

using System;
using Accord.Math;

namespace 主成分分析法测试
{
    class Program
    {
        static void Main(string[] args)
        {
            //一组模拟数据,二维数组的每一行为同一时间下不同气体的值,每一列为同一气体在不同时间下的值。
            double[,] data = new double[,] { { 54.86, 29.04,13.35,1}, { 0.1, 9.33,0.42,1}, { 101.67, 52.98,25.65,2}, { 3.08, 16.31,1.64,2}, { 0, 66.38,0,3} ,{ 1.36,52.89,0.57,3},{ 0.22,113.03,0.17,4},{0.18,86.35,0.13,4 },{ 0.16,76.32,0.11,5} ,{ 7,8,9,5},{ 2,3,4,6} };
            //生成一个PCA_V1对象 
            PCA_V1 pca = new PCA_V1();
            //由于用到了ref参数,在主函数中需要定义weight,其大小与原始数据data的列数一致
            double[] weight = new double[data.Columns()];
            //调用PcaMethod方法,若返回值为true,表示计算没有错误,weight的值可用,若为false,表示计算过程出现错误,weight的值不可用。
            bool IsTrue =pca.PcaMethod(data, ref weight); 
        }
    }
}

注意:data中每一列为一个指标的值随着时间的变化,即,有几列就有几个指标。


总结

源文件稍后上传。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
主成分分析(PCA)的目的是将高维数据降维到低维,同时尽可能地保留原本的信息。在PCA中,特征向量表示了数据的主要方向,而特征值表示了数据在这些方向上的重要性。 对于给定的数据集X,PCA的步骤如下: 1. 对数据集进行中心化,即将每一维的数据减去该维数据的均值,使得数据集的均值为0。 2. 计算协方差矩阵C,其元素为:Cij = cov(Xi, Xj) = E[(Xi - E[Xi])(Xj - E[Xj])],其中E[·]表示期望值。 3. 对协方差矩阵进行特征值分解,得到特征向量和特征值。 4. 将特征值从大到小排序,选择前k个特征值对应的特征向量作为新的基,其中k为降维后的维数。 5. 利用新的基将数据映射到新的空间中,即Y = XW,其中Y为降维后的数据,W为特征向量矩阵。 6. 计算每个特征向量的权重,即每个特征向量在新的空间中所占的比例。 以下是Python实现PCA并特征向量的权重的示例代码: ```python import numpy as np def PCA(X, k): # 中心化 X = X - np.mean(X, axis=0) # 计算协方差矩阵 cov = np.cov(X.T) # 特征值分解 eig_vals, eig_vecs = np.linalg.eig(cov) # 特征值排序 eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))] eig_pairs.sort(reverse=True) # 选择前k个特征向量 w = np.hstack((eig_pairs[i][1].reshape(X.shape[1],1)) for i in range(k)) # 计算特征向量的权重 weights = np.sum(w, axis=1) return weights # 示例数据 X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 特征向量的权重 weights = PCA(X, 2) print(weights) ``` 输出结果为: ``` [0.57735027 0.57735027 0.57735027] ``` 其中,weights表示每个特征向量在新的空间中所占的比例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值