首先感慨一下,查阅了大量资料,国内PCA的实现基本都是用Pthon,matable,c++来做,最后有幸看见国外一位教授在做机器学习算法时,提到了C#的实现。翻译了60张A4纸的英文教材终于解决这个代码问题。。。。。。
同时感谢一部分国内博主的贡献,参考如下:
按行还是按列
PCA主成分分析
PCA主成分分析原理分析和Matlable现实方法(三)
【线性代数】矩阵,向量,行列式,特征值与特征向量
PCA的思想是将N维的特征映射到K维上(K<N),K维特征称为主元,是重新构造出来的K维特征,而不是简单的从N维特征中除去其余N-K维特征。
数学计算过程。
准备一个二维数据x:2.5 0.5 2.2 1.9 3.1 2.3 2 1 1.5 1.1 y:2.4 0.7 2.9 2.2 3.0 2.7 1.6 1.1 1.6 0.9
1 分别求x和y的平均值,然后对于所有的样例,都减去对应的均值
2 求协方差矩阵
方差公式:
协方差公式
如果数据是3维,那么协方差矩阵为
本例中是二维,协方差矩阵为
由上述公式可以看出,对角线上时x和y的方差,非对角线上是协方差
3计算协方差矩阵的特征向量和特征值
因为协方差矩阵是矩形,我们能够计算特征向量和特征值,这是非常重要的,告诉了我们关于数据的重要信息。
需要注意的是,这些特征向量都是单位特征向量。它们的长度都是1,这对PCA很重要,但幸运的是,大多数数学包,当要求特征向量时,会给出单位特征向量。
4选择元素和组成特征向量
这就是数据压缩和降维概念的由来。如果你看上一节的特征向量和特征值,你会注意到特征值是完全不同的值。事实上,特征值最大的特征向量是数据集的主分量。当从协方差矩阵中得到特征向量,下一步就是按特征值从高到低排序。按照重要性对元素进行排序,现在,如果你喜欢,你可以决定忽略不那么重要的部分。准确的说,如果你原来的数据有N维,所以你可以计算出N维的特征向量和特征值,然后你选择p个特征向量,最后数据集只剩下p维。
本例中,我们可以选择两个特征向量组成一个特征向量
或者我们忽略不重要的元素,只保留一列。
5 实现PCA最后一步
一旦我们选择了我们想要保存在数据中的分量(特征向量)并形成了一个特征向量,我们只需对这个向量进行转置并将其乘以转置了的原始数据集的左边。
介绍matlab实现PCA
clc,clear
a=xlsread('C:\Users\yxz\Desktop\eng3\test.csv');%读文件
%y1(:,1)=a(:,1);
x1=a(:,1:end);
[coeff,score,latent,tsquared,explained]= pca(x1);
% k=100;
% Z = projectData(x1, U, 20);
%coeff 是主成分分量,即样本斜方差矩阵的特征向量
%score 主成分,是样本X在低纬度空间的表现形式,即样本X在主成分分量Coeff上的投影,络需要将K维,则只需要取前K列主成分分量即可
%latent 一个包含样本协方差矩阵特征值的向量
%explained 每个特征值所代表的特征向量在数据集所占的比重
介绍C#实现
下载安装Accord.NET,Accord.Math,Accord.Statistic,
安装上述文件的方法参考以前写过的博客
开始之前使用要引用这些dll文件
using Accord.Math;
using Accord.Math.Comparers;
using Accord.Math.Decompositions;
using Accord.Statistics;
using Accord.Statistics.Analysis;
代码如下
double[] data1 = { 2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2.0, 1.0, 1.5, 1.1 };
double[] data2 = { 2.4, 0.7, 2.9, 2.2, 3.0, 2.7, 1.6, 1.1, 1.6, 0.9 };
double mean1 = data1.Mean();
double[] dataAdjust1 = data1.Subtract(mean1);
double mean2 = data2.Mean();
double[] dataAdjust2 = data2.Subtract(mean2);
double[,] dataAdjust = {
{ dataAdjust1[0], dataAdjust2[0] },
{ dataAdjust1[1], dataAdjust2[1] },
{ dataAdjust1[2], dataAdjust2[2] },
{ dataAdjust1[3], dataAdjust2[3] },
{ dataAdjust1[4], dataAdjust2[4] },
{ dataAdjust1[5], dataAdjust2[5] },
{ dataAdjust1[6], dataAdjust2[6] },
{ dataAdjust1[7], dataAdjust2[7] },
{ dataAdjust1[8], dataAdjust2[8] },
{ dataAdjust1[9], dataAdjust2[9] },
};
//3calculate the covariance matrix
double[,] cov = dataAdjust.Covariance();
//double[] ydd = { 2.0, 3.0, 5.1, 1.0, 4.1, 9.2, 8.2, 6.2, 7.3 };
//ydd.Sort();
//4 Calculate the eigenvectors and eigenvalues of the covariance matrix
var evd = new EigenvalueDecomposition(cov);
double[] eigenvalues = evd.RealEigenvalues;
double[,] eigenvectors = evd.Eigenvectors;
// 5choosing components and forming a feature vector
// sort eigenvalues and vectors in descending order
eigenvectors= Accord.Math.Matrix.Sort(eigenvalues, eigenvectors, new GeneralComparer(ComparerDirection.Descending, true));//eigenvalues没有实现降序排序
//对eigenvalues实现降序排序
for(int i=0;i< eigenvalues.Count();i++)
{
for(int j=i+1;j < eigenvalues.Count();j++)
{
double temp = 0;
if(eigenvalues[i]< eigenvalues[j])
{
temp = eigenvalues[i];
eigenvalues[i] = eigenvalues[j];
eigenvalues[j] = temp;
}
}
}
//select all eigenvectors
double[,] featureVector = eigenvectors;
//select only the first eigenvector.将第一列转置
double[,] featureVector2 = eigenvectors.GetColumn(0).Transpose();
//6 deriving the new data set
double[,] finalData = Accord.Math.Matrix.Dot(dataAdjust, featureVector);//乘法
按行还是按列计算均值的问题
协方差矩阵计算的是不同维度之间的协方差,而不是不同样本之间,例如下所示10*3维的整数矩阵10为样本书,3为样本的维数。
根据公式,计算协方差需要计算均值。牢记,样本矩阵的每一行是一个样本,每列为一个维度,要按列计算均值。
matlab的实现可以查看我的另外一篇博客
点击这里,查看PCA的MATLAB实现