学习pca的好资料集合

来源:互联网 发布:网上买电影票软件 编辑:程序博客网 时间:2024/06/05 16:25

首先了解特征向量的概念

然后,http://www.cad.zju.edu.cn/home/chenlu/pca.htm了解pca概念

http://jacobyuan.blog.sohu.com/148317731.html进一步解释

下面是转的代码

  1. /*  
  2.    PCA program (using covariance)  
  3.    Written by Y. Bin Mao  
  4.    Video and Image Processing and Analysis Group (VIPAG)  
  5.    School of Automation, NJUST  
  6.    Jan. 6, 2008  
  7.   
  8.    All rights reserved. (c)  
  9.   
  10.    Here is a matlab description of the algorithm  
  11.    % PCA1: Perform PCA using covariance.  
  12.    % data      --- MxN matrix of input data (M dimensions, N trials)  
  13.    % signals   --- MxN matrix of projected data  
  14.    % PC        --- each column is a PC  
  15.    % V         --- Mx1 matrix of variances  
  16.    %  
  17.    function [signals, PC, V] = pca1( data )  
  18.   
  19.     [M, N] = size( data );  
  20.     
  21.     % subtract off the mean for each dimension  
  22.     mn = mean( data, 2 );  
  23.     data = data - repmat( mn, 1, N );  
  24.       
  25.     % calculate the covariance matrix  
  26.     covariance = 1/ (N-1) * data * data';  
  27.         
  28.     % find the eigenvectors and eigenvalues  
  29.     [PC, V] = eig( covariance );  
  30.           
  31.     % extract diagonal of matrix as vector  
  32.     V = diag(V);  
  33.             
  34.     % sort the variances in decreasing order  
  35.     [junk, rindices] = sort(-1*V);  
  36.     V = V(rindices);  
  37.     PC = PC(:,rindices);  
  38.           
  39.     % project the original data set  
  40.     signals = PC' * data;  
  41.  */   
  42.   
  43. #include <stdio.h>  
  44. #include <stdlib.h>  
  45. #include <math.h>  
  46.    
  47. #define ALGO_DEBUG   
  48.    
  49. /*  
  50.    用豪斯荷尔德(Householder)变换将n阶实对称矩阵约化为对称三对角阵  
  51.    徐士良. 常用算法程序集(C语言描述),第3版. 清华大学出版社. 2004  
  52.   
  53.    double a[] --- 维数为nxn。存放n阶实对称矩阵A  
  54.    int n      --- 实对称矩阵A的阶数  
  55.    double q[] --- 维数nxn。返回Householder变换的乘积矩阵Q。当与  
  56.                   Tri_Symmetry_Diagonal_Eigenvector()函数联用,若将  
  57.                   Q矩阵作为该函数的一个参数时,可计算实对称阵A的特征  
  58.                   值与相应的特征向量  
  59.    double b[] --- 维数为n。返回对称三对角阵中的主对角线元素  
  60.    double c[] --- 长度n。前n-1个元素返回对称三对角阵中的次对角线元素。  
  61. */   
  62. void Householder_Tri_Symetry_Diagonal( double a[], int n, double q[],    
  63.                                        double b[], double c[] )   
  64. {    
  65.     int i, j, k, u;   
  66.     double h, f, g, h2;   
  67.    
  68.     for ( i = 0; i = n-1; i++ )   
  69.         for ( j = 0; j = n-1; j++ )   
  70.         {   
  71.             u = i * n + j;    
  72.             q[u] = a[u];   
  73.         }   
  74.     for ( i = n-1; i >= 1; i-- )   
  75.     {    
  76.         h = 0.0;   
  77.         if ( i > 1 )   
  78.             for ( k = 0; k = i-1; k++ )   
  79.             {    
  80.                 u = i * n + k;   
  81.                 h = h + q[u] * q[u];   
  82.             }   
  83.         if ( h + 1.0 == 1.0 )   
  84.         {    
  85.             c[i] = 0.0;   
  86.             if ( i == 1 ) c[i] = q[i*n+i-1];   
  87.             b[i] = 0.0;   
  88.         }   
  89.         else   
  90.         {    
  91.             c[i] = sqrt( h );   
  92.             u = i * n + i - 1;   
  93.             if ( q[u] > 0.0 ) c[i] = -c[i];   
  94.             h = h - q[u] * c[i];   
  95.             q[u] = q[u] - c[i];   
  96.             f = 0.0;   
  97.             for ( j = 0; j = i - 1; j++ )   
  98.             {    
  99.                 q[j*n+i] = q[i*n+j] / h;   
  100.                 g = 0.0;   
  101.                 for ( k = 0; k = j; k++ )   
  102.                     g = g + q[j*n+k] * q[i*n+k];   
  103.                 if ( j + 1 = i-1 )   
  104.                     for ( k = j+1; k = i-1; k++ )   
  105.                         g = g + q[k*n+j] * q[i*n+k];   
  106.                     c[j] = g / h;   
  107.                     f = f + g * q[j*n+i];   
  108.             }   
  109.             h2 = f / ( h + h );   
  110.             for ( j = 0; j = i-1; j++ )   
  111.             {    
  112.                 f = q[i*n+j];   
  113.                 g = c[j] - h2 * f;   
  114.                 c[j] = g;   
  115.                 for ( k = 0; k = j; k++ )   
  116.                 {    
  117.                     u = j * n + k;   
  118.                     q[u] = q[u] - f * c[k] - g * q[i*n+k];   
  119.                 }   
  120.             }   
  121.             b[i] = h;   
  122.         }   
  123.     }   
  124.     for ( i = 0; i = n-2; i++ ) c[i] = c[i+1];   
  125.     c[n-1] = 0.0;   
  126.     b[0] = 0.0;   
  127.     for ( i = 0; i = n-1; i++ )   
  128.     {    
  129.         if ( ( b[i] != 0.0 ) && ( i-1 >= 0 ) )   
  130.             for ( j = 0; j = i-1; j++ )   
  131.             {    
  132.                 g = 0.0;   
  133.                 for ( k = 0; k = i-1; k++ )   
  134.                     g = g + q[i*n+k] * q[k*n+j];   
  135.                 for ( k = 0; k = i-1; k++ )   
  136.                 {    
  137.                     u = k * n + j;   
  138.                     q[u] = q[u] - g * q[k*n+i];   
  139.                 }   
  140.             }   
  141.         u = i * n + i;   
  142.         b[i] = q[u]; q[u] = 1.0;   
  143.         if ( i - 1 >= 0 )   
  144.             for ( j = 0; j = i - 1; j++ )   
  145.             {    
  146.                 q[i*n+j] = 0.0; q[j*n+i] = 0.0;   
  147.             }   
  148.     }   
  149.    
  150.     return;   
  151. }   
  152.    
  153. /*  
  154.    计算实对称三对角阵的全部特征值与对应特征向量  
  155.    徐士良. 常用算法程序集(C语言描述),第3版. 清华大学出版社. 2004  
  156.   
  157.    int n    --- 实对称三对角阵的阶数  
  158.    double b --- 长度为n,存放n阶对称三对角阵的主对角线上的各元素;  
  159.                 返回时存放全部特征值  
  160.    double c --- 长度为n,前n-1个元素存放n阶对称三对角阵的次对角  
  161.                 线上的元素  
  162.    double q --- 维数为nxn,若存放单位矩阵,则返回n阶实对称三对角  
  163.                 阵T的特征向量组;若存放Householder_Tri_Symetry_Diagonal()  
  164.                 函数所返回的一般实对称矩阵A的豪斯荷尔得变换的乘  
  165.                 积矩阵Q,则返回实对称矩阵A的特征向量组。其中,q中  
  166.                 的的j列为与数组b中第j个特征值对应的特征向量  
  167.    double eps --- 本函数在迭代过程中的控制精度要求       
  168.    int l    --- 为求得一个特征值所允许的最大迭代次数  
  169.    返回值:  
  170.    若返回标记小于0,则说明迭代了l次还未求得一个特征值,并有fail  
  171.    信息输出;若返回标记大于0,则说明程序工作正常,全部特征值由一  
  172.    维数组b给出,特征向量组由二维数组q给出  
  173. */   
  174. int Tri_Symmetry_Diagonal_Eigenvector( int n, double b[], double c[],    
  175.                                        double q[], double eps, int l )   
  176. {    
  177.     int i, j, k, m, it, u, v;   
  178.     double d, f, h, g, p, r, e, s;   
  179.    
  180.     c[n-1] = 0.0; d = 0.0; f = 0.0;   
  181.     for ( j = 0; j = n-1; j++ )   
  182.     {    
  183.         it = 0;   
  184.         h = eps * ( fabs( b[j] ) + fabs( c[j] ) );   
  185.         if ( h > d ) d = h;   
  186.         m = j;   
  187.         while ( ( m = n-1 ) && ( fabs( c[m] ) > d ) ) m = m+1;   
  188.         if ( m != j )   
  189.         {    
  190.             do   
  191.             {    
  192.                 if ( it == l )   
  193.                 {    
  194.                     #ifdef ALGO_DEBUG   
  195.                     printf( "fail\n" );   
  196.                     #endif   
  197.                     return( -1 );   
  198.                 }   
  199.                 it = it + 1;   
  200.                 g = b[j];   
  201.                 p = ( b[j+1] - g ) / ( 2.0 * c[j] );   
  202.                 r = sqrt( p * p + 1.0 );   
  203.                 if ( p >= 0.0 )    
  204.                     b[j] = c[j] / ( p + r );   
  205.                 else    
  206.                     b[j] = c[j] / ( p - r );   
  207.                 h = g - b[j];   
  208.                 for ( i = j+1; i = n-1; i++ )   
  209.                     b[i] = b[i] - h;   
  210.                 f = f + h; p = b[m]; e = 1.0; s = 0.0;   
  211.                 for ( i = m-1; i >= j; i-- )   
  212.                 {    
  213.                     g = e * c[i]; h = e * p;   
  214.                     if ( fabs( p ) >= fabs( c[i] ) )   
  215.                     {    
  216.                         e = c[i] / p; r = sqrt( e * e + 1.0 );   
  217.                         c[i+1] = s * p * r; s = e / r; e = 1.0 / r;   
  218.                     }   
  219.                     else   
  220.                     {    
  221.                         e = p / c[i]; r = sqrt( e * e + 1.0 );   
  222.                         c[i+1] = s * c[i] * r;   
  223.                         s = 1.0 / r; e = e / r;   
  224.                     }   
  225.                     p = e * b[i] - s * g;   
  226.                     b[i+1] = h + s * ( e * g + s * b[i] );   
  227.                     for ( k = 0; k = n-1; k++ )   
  228.                     {    
  229.                         u = k * n + i + 1; v = u - 1;   
  230.                         h = q[u]; q[u] = s * q[v] + e * h;   
  231.                         q[v] = e * q[v] - s * h;   
  232.                     }   
  233.                 }   
  234.                 c[j] = s * p; b[j] = e * p;   
  235.             }   
  236.             while ( fabs( c[j] ) > d );   
  237.         }   
  238.         b[j] = b[j] + f;   
  239.     }   
  240.     for ( i = 0; i = n-1; i++ )   
  241.     {    
  242.         k = i; p = b[i];   
  243.         if ( i+1 = n-1 )   
  244.         {    
  245.             j = i+1;   
  246.             while ( ( j = n-1 ) && ( b[j] = p ) )   
  247.             {    
  248.                 k = j; p = b[j]; j = j+1;   
  249.             }   
  250.         }   
  251.         if ( k != i )   
  252.         {    
  253.             b[k] = b[i]; b[i] = p;   
  254.             for ( j = 0; j = n-1; j++ )   
  255.             {    
  256.                 u = j * n + i; v = j * n + k;   
  257.                 p = q[u]; q[u] = q[v]; q[v] = p;   
  258.             }   
  259.         }   
  260.     }   
  261.    
  262.     return( 1 );   
  263. }   
  264.    
  265. # define EPS    0.000001   /* 计算精度 */   
  266. # define Iteration    60   /* 求取特征量的最多迭代次数 */   
  267.    
  268. /*  
  269.    计算实对称阵的全部特征值与对应特征向量  
  270.    int n              --- 实对称阵的阶数  
  271.    double * CovMatrix --- 维数为nxn,存放n阶对称阵的各元素;  
  272.    double * Eigen     --- 长度为n,为n个特征值  
  273.    double * EigenVector --- 维数为nxn,返回n阶实对称阵的特征向量组其中,  
  274.                             EigenVector中的j列为与数组Eigen中第j个特征值  
  275.                             对应的特征向量  
  276.    返回值:  
  277.    若返回标记小于0,则说明迭代了Iteration次还未求得一个特征值;  
  278.    若返回标记大于0,则说明程序工作正常,全部特征值由一  
  279.    维数组Eigen给出,特征向量组由二维数组EigenVector给出  
  280. */   
  281. int SymmetricRealMatrix_Eigen( double CovMatrix[], int n,    
  282.                                double Eigen[], double EigenVector[] )   
  283. {   
  284.     int k;   
  285.     double * subDiagonal;   
  286.    
  287.     subDiagonal = ( double * )malloc( sizeofdouble ) * n );   
  288.     Householder_Tri_Symetry_Diagonal( CovMatrix, n, EigenVector, Eigen, subDiagonal );   
  289.     k = Tri_Symmetry_Diagonal_Eigenvector( n, Eigen, subDiagonal, EigenVector, EPS, Iteration );   
  290.     free( subDiagonal );   
  291.    
  292.     return( k );   
  293. }   
  294.    
  295. /*  
  296.   PCA1: Perform PCA using covariance.  
  297.   data     --- MxN matrix of input data ( M dimensions, N trials )  
  298.                行数为原始数据维数;每列数据为一个样本  
  299.   signals  --- MxN matrix of projected data   
  300.   PC       --- each column is a PC  
  301.   V        --- Mx1 matrix of variances  
  302.   row = M dimensions, col = N trials   
  303. */   
  304. int pca1( double * data, int row, int col,   
  305.           double * signals, double * PC, double * V )   
  306. {   
  307.     int x, y, k;   
  308.     double * mean;   
  309.     double * data1, * tPC, * tV;   
  310.     double * covariance, temp;   
  311.     int rvalue, * no, tp;   
  312.    
  313.     if ( row = 1 || col = 1 ) return( -1 );   
  314.     /* subtract off the mean for each dimension */   
  315.     mean = ( double * )malloc( sizeofdouble ) * row );   
  316.     data1 = ( double * )malloc( sizeofdouble ) * row * col );   
  317.     for ( y = 0; y  row; y++ ) /* calculate mean */   
  318.     {   
  319.         mean[y] = 0;   
  320.         for ( x = 0; x  col; x++ )   
  321.             mean[y] += data[y*col+x];   
  322.     }   
  323.     for ( y = 0; y  row; y++ ) mean[y] = mean[y]/col;   
  324.     for ( y = 0; y  row; y++ ) /* subtract mean */   
  325.         for ( x = 0; x  col; x++ )   
  326.         {   
  327.             data1[y*col+x] = data[y*col+x] - mean[y];   
  328.         }   
  329.     free( mean );   
  330.     /* calculate the covariance matrix */   
  331.     covariance = ( double * )malloc( sizeofdouble ) * row * row );   
  332.     for ( y = 0; y  row; y++ )   
  333.         for ( x = 0; x  row; x++ )   
  334.         {   
  335.             temp = 0;   
  336.             for ( k = 0; k  col; k++ )    
  337.                 temp += data1[y*col+k] * data1[x*col+k];   
  338.             temp = temp / ( col-1 );   
  339.             covariance[x*row+y] = temp;   
  340.         }   
  341.     /* find the eigenvectors and eigenvalues */   
  342.     rvalue = SymmetricRealMatrix_Eigen( covariance, row, V, PC );   
  343.     free( covariance );   
  344.     /* sort the variances in decreasing order */   
  345.     no = ( int * )malloc( sizeofint ) * row );   
  346.     for ( x = 0; x  row; x++ ) no[x] = x;   
  347.     for ( x = 0; x  row-1; x++ )   
  348.     {   
  349.         temp = V[x];   
  350.         for ( k = x; k  row; k++ )   
  351.             if ( temp  V[k] )   
  352.             {   
  353.                 tp = no[k];   
  354.                 no[k] = no[x];   
  355.                 no[x] = tp;   
  356.                 temp = V[k];   
  357.             }   
  358.     }   
  359.     /* exchange eigen value and vector in decreasing order */   
  360.     tV = ( double * )malloc( sizeofdouble ) * row );   
  361.     tPC = ( double * )malloc( sizeofdouble ) * row * row );   
  362.     for ( x = 0; x  row; x++ ) tV[x] = V[x];   
  363.     for ( x = 0; x  row; x++ )   
  364.         for ( y = 0; y  row; y++ )   
  365.             tPC[x*row+y] = PC[x*row+y];   
  366.     for ( x = 0; x  row; x++ )   
  367.     {   
  368.         if ( no[x] != x )   
  369.         {   
  370.             for ( y = 0; y  row; y++ )   
  371.                 PC[y*row+x] = tPC[y*row+no[x]];   
  372.             V[x] = tV[no[x]];   
  373.         }   
  374.     }   
  375.     free( no );   
  376.     free( tV );   
  377.     free( tPC );   
  378.    
  379.     /* project the original data: signals = PC' * data; */   
  380.     for ( y = 0; y  row; y++ )   
  381.         for ( x = 0; x  col; x++ )   
  382.         {   
  383.             signals[y*col+x] = 0;   
  384.             for ( k = 0; k  row; k++ )   
  385.                 signals[y*col+x] += PC[k*row+y] * data1[k*col+x];   
  386.         }   
  387.     free( data1 );   
  388.    
  389.     return( rvalue );   
  390. }   
  391.    
  392. /*  
  393.   投影到主元素向量上  
  394.   double * newdata --- 要投影到主元素分量上的数据矩阵  
  395.   int row, col     --- 数据矩阵的维数  
  396.                        row(行数)为主元向量维数(即特征数)  
  397.                        col(列数)为采样数  
  398.   double * PC      --- 主元特征向量(列向量)  
  399.   double * newsignals --- 投影后获得的信号的系数(row*col)  
  400.   double * ShiftValue --- 如果一个有row个元素的偏移量,如果改值为NULL  
  401.                           则计算均值,并减去均值,否则减去改值  
  402. */   
  403. int project2PCA( double * newdata, int row, int col,   
  404.                  double * PC, double * newsignals, double * ShiftValue )   
  405. {   
  406.     int x, y, k;   
  407.     double * mean, * data1;   
  408.    
  409.     /* subtract off the mean for each dimension */   
  410.     data1 = ( double * )malloc( sizeofdouble ) * row * col );   
  411.     /* if ShiftValue <> NULL */   
  412.     if ( ShiftValue != NULL )   
  413.     {   
  414.         for ( y = 0; y  row; y++ ) /* subtract ShiftValue */   
  415.             for ( x = 0; x  col; x++ )   
  416.             {   
  417.                 data1[y*col+x] = newdata[y*col+x] - ShiftValue[y];   
  418.             }   
  419.     }   
  420.     else   
  421.     {   
  422.         mean = ( double * )malloc( sizeofdouble ) * row );   
  423.         for ( y = 0; y  row; y++ ) /* calculate mean */   
  424.         {   
  425.             mean[y] = 0;   
  426.             for ( x = 0; x  col; x++ )   
  427.                 mean[y] += newdata[y*col+x];   
  428.         }   
  429.         if ( col = 1 )    
  430.             for ( y = 0; y  row; y++ ) mean[y] = 0;   
  431.         else   
  432.             for ( y = 0; y  row; y++ ) mean[y] = mean[y]/col;   
  433.         for ( y = 0; y  row; y++ ) /* subtract mean */   
  434.             for ( x = 0; x  col; x++ )   
  435.             {   
  436.                 data1[y*col+x] = newdata[y*col+x] - mean[y];   
  437.             }   
  438.         free( mean );          
  439.     }   
  440.     /* project the original data: signals = PC' * data; */   
  441.     for ( y = 0; y  row; y++ )   
  442.         for ( x = 0; x  col; x++ )   
  443.         {   
  444.             newsignals[y*col+x] = 0;   
  445.             for ( k = 0; k  row; k++ )   
  446.                 newsignals[y*col+x] += PC[k*row+y] * data1[k*col+x];   
  447.         }   
  448.     free( data1 );   
  449.    
  450.     return( 1 );   
  451. }   
  452.    
  453. /*  
  454.   test: main function  
  455. */   
  456. int main()   
  457. {   
  458.     double data[20] = { 2, 3, 8, 2, 3,   
  459.         7, 9, 29, 3, 5,   
  460.                        3, 8, 22, 12, 1,   
  461.                        3, 12, 12, 33, 2};   
  462.     int row = 4, col = 5;   
  463.     double signals[20], PC[16], V[4];   
  464.     int x, y;   
  465.        
  466.     pca1( data, row, col, signals, PC, V );   
  467.        
  468.     printf( "Project to Principal Component: \n" );   
  469.     for ( y = 0; y  row; y++ )   
  470.     {   
  471.         for ( x = 0; x  col; x++ )   
  472.         {   
  473.             printf( "%7.4f ", signals[y*col+x] );   
  474.         }   
  475.         printf( "\n" );   
  476.     }   
  477.     printf( "Eigen Values (in deceasing order): \n" );   
  478.     for ( y = 0; y  row; y++ )   
  479.         printf( "%7.4f ", V[y] );   
  480.     printf( "\n" );   
  481.     printf( "Eigen Vectors: \n" );   
  482.     for ( y = 0; y  row; y++ )   
  483.     {   
  484.         for ( x = 0; x  row; x++ )   
  485.         {   
  486.             printf( "%7.4f ", PC[y*row+x] );   
  487.         }   
  488.         printf( "\n" );   
  489.     }   
  490.        
  491.     return( 1 );   
  492. }  

原创粉丝点击