⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pca1a.cpp

📁 实现pca功能的完整matlab程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
   double * Eigen     --- 长度为n,为n个特征值
   double * EigenVector --- 维数为nxn,返回n阶实对称阵的特征向量组其中,
                            EigenVector中的j列为与数组Eigen中第j个特征值
							对应的特征向量
   返回值:
   若返回标记小于0,则说明迭代了Iteration次还未求得一个特征值;
   若返回标记大于0,则说明程序工作正常,全部特征值由一
   维数组Eigen给出,特征向量组由二维数组EigenVector给出
*/
int SymmetricRealMatrix_Eigen( double CovMatrix[], int n, 
							   double Eigen[], double EigenVector[] )
{
	int k;
	double * subDiagonal;

	subDiagonal = ( double * )malloc( sizeof( double ) * n );
	Householder_Tri_Symetry_Diagonal( CovMatrix, n, EigenVector, Eigen, subDiagonal );
	k = Tri_Symmetry_Diagonal_Eigenvector( n, Eigen, subDiagonal, EigenVector, EPS, Iteration );
	free( subDiagonal );

	return( k );
}

/*
  PCA1: Perform PCA using covariance.
  data     --- MxN matrix of input data ( M dimensions, N trials )
               行数为原始数据维数;每列数据为一个样本
  signals  --- MxN matrix of projected data 
  PC       --- each column is a PC
  V        --- Mx1 matrix of variances
  row = M dimensions, col = N trials 
*/
int pca1( double * data, int row, int col,
	      double * signals, double * PC, double * V )
{
	int x, y, k;
	double * mean;
	double * data1, * tPC, * tV;
	double * covariance, temp;
	int rvalue, * no, tp;

	if ( row <= 1 || col <= 1 ) return( -1 );
	/* subtract off the mean for each dimension */
	mean = ( double * )malloc( sizeof( double ) * row );
	data1 = ( double * )malloc( sizeof( double ) * row * col );
	for ( y = 0; y < row; y++ ) /* calculate mean */
	{
		mean[y] = 0;
		for ( x = 0; x < col; x++ )
			mean[y] += data[y*col+x];
	}
	for ( y = 0; y < row; y++ ) mean[y] = mean[y]/col;
	for ( y = 0; y < row; y++ ) /* subtract mean */
		for ( x = 0; x < col; x++ )
		{
			data1[y*col+x] = data[y*col+x] - mean[y];
		}
	free( mean );
	/* calculate the covariance matrix */
	covariance = ( double * )malloc( sizeof( double ) * row * row );
	for ( y = 0; y < row; y++ )
		for ( x = 0; x < row; x++ )
		{
			temp = 0;
			for ( k = 0; k < col; k++ ) 
				temp += data1[y*col+k] * data1[x*col+k];
			temp = temp / ( col-1 );
			covariance[x*row+y] = temp;
		}
	/* find the eigenvectors and eigenvalues */
	rvalue = SymmetricRealMatrix_Eigen( covariance, row, V, PC );
	free( covariance );
	/* sort the variances in decreasing order */
	no = ( int * )malloc( sizeof( int ) * row );
	for ( x = 0; x < row; x++ ) no[x] = x;
	for ( x = 0; x < row-1; x++ )
	{
		temp = V[x];
		for ( k = x; k < row; k++ )
			if ( temp < V[k] )
			{
				tp = no[k];
				no[k] = no[x];
				no[x] = tp;
				temp = V[k];
			}
	}
	/* exchange eigen value and vector in decreasing order */
	tV = ( double * )malloc( sizeof( double ) * row );
	tPC = ( double * )malloc( sizeof( double ) * row * row );
	for ( x = 0; x < row; x++ ) tV[x] = V[x];
	for ( x = 0; x < row; x++ )
		for ( y = 0; y < row; y++ )
			tPC[x*row+y] = PC[x*row+y];
	for ( x = 0; x < row; x++ )
	{
		if ( no[x] != x )
		{
			for ( y = 0; y < row; y++ )
				PC[y*row+x] = tPC[y*row+no[x]];
			V[x] = tV[no[x]];
		}
	}
	free( no );
	free( tV );
	free( tPC );

	/* project the original data: signals = PC' * data; */
	for ( y = 0; y < row; y++ )
		for ( x = 0; x < col; x++ )
		{
			signals[y*col+x] = 0;
			for ( k = 0; k < row; k++ )
				signals[y*col+x] += PC[k*row+y] * data1[k*col+x];
		}
	free( data1 );

	return( rvalue );
}

/*
  投影到主元素向量上
  double * newdata --- 要投影到主元素分量上的数据矩阵
  int row, col     --- 数据矩阵的维数
                       row(行数)为主元向量维数(即特征数)
					   col(列数)为采样数
  double * PC      --- 主元特征向量(列向量)
  double * newsignals --- 投影后获得的信号的系数(row*col)
  double * ShiftValue --- 如果一个有row个元素的偏移量,如果改值为NULL
                          则计算均值,并减去均值,否则减去改值
*/
int project2PCA( double * newdata, int row, int col,
	             double * PC, double * newsignals, double * ShiftValue )
{
	int x, y, k;
	double * mean, * data1;

	/* subtract off the mean for each dimension */
	data1 = ( double * )malloc( sizeof( double ) * row * col );
	/* if ShiftValue <> NULL */
	if ( ShiftValue != NULL )
	{
		for ( y = 0; y < row; y++ ) /* subtract ShiftValue */
			for ( x = 0; x < col; x++ )
			{
				data1[y*col+x] = newdata[y*col+x] - ShiftValue[y];
			}
	}
	else
	{
		mean = ( double * )malloc( sizeof( double ) * row );
		for ( y = 0; y < row; y++ ) /* calculate mean */
		{
			mean[y] = 0;
			for ( x = 0; x < col; x++ )
				mean[y] += newdata[y*col+x];
		}
		if ( col <= 1 ) 
			for ( y = 0; y < row; y++ ) mean[y] = 0;
		else
			for ( y = 0; y < row; y++ ) mean[y] = mean[y]/col;
		for ( y = 0; y < row; y++ ) /* subtract mean */
			for ( x = 0; x < col; x++ )
			{
				data1[y*col+x] = newdata[y*col+x] - mean[y];
			}
		free( mean );		
	}
	/* project the original data: signals = PC' * data; */
	for ( y = 0; y < row; y++ )
		for ( x = 0; x < col; x++ )
		{
			newsignals[y*col+x] = 0;
			for ( k = 0; k < row; k++ )
				newsignals[y*col+x] += PC[k*row+y] * data1[k*col+x];
		}
	free( data1 );

	return( 1 );
}

/*
  test: main function
*/
int main()
{
	double data[37*8] = { 
	    3.0,    3.0,    3.0,    3.0,    3.0,    3.0,   35.0,   45.0,
       53.0,   55.0,   58.0,  113.0,  113.0,   86.0,   67.0,   90.0,
        3.5,    3.5,    4.0,    4.0,    4.5,    4.5,   46.0,   59.0,
       63.0,   58.0,   58.0,  125.0,  126.0,  110.0,   78.0,   97.0,
        4.0,    4.0,    4.5,    4.5,    5.0,    5.0,   48.0,   60.0,
       68.0,   65.0,   65.0,  123.0,  123.0,  117.0,   87.0,  108.0,
        5.0,    5.0,    5.0,    5.5,    5.5,    5.5,   46.0,   63.0,
       70.0,   64.0,   63.0,  116.0,  119.0,  115.0,   97.0,  112.0,
        6.0,    6.0,    6.0,    6.0,    6.5,    6.5,   51.0,   69.0,
       77.0,   70.0,   71.0,  120.0,  122.0,  122.0,   96.0,  123.0,
       11.0,   11.0,   11.0,   11.0,   11.0,   11.0,   64.0,   75.0,
       81.0,   79.0,   79.0,  112.0,  114.0,  113.0,   98.0,  115.0,
       20.0,   20.0,   20.0,   20.0,   20.0,   20.0,   76.0,   86.0,
       93.0,   92.0,   91.0,  104.0,  104.5,  107.0,   97.5,  104.0,
       30.0,   30.0,   30.0,   30.0,   30.1,   30.2,   84.0,   96.0,
       98.0,   99.0,   96.0,  101.0,  102.0,   99.0,   94.0,   99.0,
       30.0,   33.4,   36.8,   40.0,   43.0,   45.6,  100.0,  106.0,
      106.0,  108.0,  101.0,   99.0,   98.0,   99.0,   95.0,   95.0,
       42.0,   44.0,   46.0,   48.0,   50.0,   51.0,  109.0,  111.0,
      110.0,  110.0,  103.0,   95.5,   95.5,   95.0,   92.5,   92.0,
       60.0,   61.7,   63.5,   65.5,   67.3,   69.2,  122.0,  124.0,
      124.0,  121.0,  103.0,   93.2,   92.5,   92.2,   90.0,   90.8,
       70.0,   70.1,   70.2,   70.3,   70.4,   70.5,  137.0,  132.0,
      134.0,  128.0,  101.0,   91.7,   90.2,   88.8,   87.3,   85.8,
       78.0,   77.6,   77.2,   76.8,   76.4,   76.0,  167.0,  159.0,
      152.0,  144.0,  103.0,   89.8,   87.7,   85.7,   83.7,   81.8,
       98.9,   97.8,   96.7,   95.5,   94.3,   93.2,  183.0,  172.0,
      162.0,  152.0,  102.0,   87.5,   85.3,   83.3,   81.3,   79.3,
      160.0,  157.0,  155.0,  152.0,  149.0,  147.0,  186.0,  175.0,
      165.0,  156.0,  120.0,   87.0,   84.9,   82.8,   80.8,   79.0,
      272.0,  266.0,  260.0,  254.0,  248.0,  242.0,  192.0,  182.0,
      170.0,  159.0,  131.0,   88.0,   85.8,   83.7,   81.6,   79.6,
      382.0,  372.0,  362.0,  352.0,  343.0,  333.0,  205.0,  192.0,
      178.0,  166.0,  138.0,   86.2,   84.0,   82.0,   79.8,   77.5,
      770.0,  740.0,  710.0,  680.0,  650.0,  618.0,  226.0,  207.0,
      195.0,  180.0,  160.0,   82.9,   80.2,   77.7,   75.2,   72.7	
	};
	double newdata[37] = { 3.0, 53.0, 3.5, 63.0, 4.0, 68.0, 5.0, 70.0, 6.0, 
                          77.0, 11.0, 81.0, 20.0, 93.0, 30.0, 98.0, 30.0, 106.0, 
                          42.0, 110.0, 60.0, 124.0, 70.0, 134.0, 78.0, 152.0, 98.9, 
                         162.0, 160.0, 165.0, 272.0, 170.0, 382.0, 178.0, 770.0, 195.0 }; 
	double shiftvalue[37] = { 3.0, 50.0, 3.0, 60.0, 4.0, 60.0, 6.0, 60.0, 4.0, 
                          75.0, 10.0, 80.0, 22.0, 90.0, 20.0, 100.0, 28.0, 100.0, 
                          40.0, 110.0, 50.0, 120.0, 73.0, 130.0, 78.5, 152.0, 90.0, 
                         160.0, 150.0, 160.0, 270.0, 160.0, 372.0, 180.0, 700.0, 185.0 };
	int row = 37, col = 8;
	double signals[37*8], PC[37*37], V[37], newsignals[37];
	int x, y;

	pca1( data, row, col, signals, PC, V );

	printf( "Project to Principal Component: \n" );
	for ( y = 0; y < row; y++ )
	{
		for ( x = 0; x < col; x++ )
		{
			printf( "%7.4f ", signals[y*col+x] );
		}
		printf( "\n" );
	}
	printf( "Eigen Values (in deceasing order): \n" );
	for ( y = 0; y < row; y++ )
		printf( "%7.4f ", V[y] );
	printf( "\n" );
	printf( "Eigen Vectors: \n" );
	for ( y = 0; y < row; y++ )
	{
		for ( x = 0; x < row; x++ )
		{
			printf( "%7.4f ", PC[y*row+x] );
		}
		printf( "\n" );
	}
	
	printf( "Project a vector to PCA:\n" );
	/* project2PCA( newdata, row, 1, PC, newsignals, NULL ); */
	project2PCA( newdata, row, 1, PC, newsignals, shiftvalue );
	for ( y = 0; y < row; y++ )
		printf( "%7.4f ", newsignals[y] );
	printf( "\n" );

	return( 1 );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -