#pragma once template void PCA::InitFromPointMatrix(DenseMatrix &B) { const UINT PointCount = B.ColCount(); const UINT Dimension = B.RowCount(); Console::WriteLine(String("Initializing PCA, ") + String(B.ColCount()) + String(" points, ") + String(B.RowCount()) + String(" dimensions")); _Means.Allocate(Dimension); _Means.Clear(0.0); for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] += B.Cell(DimensionIndex, PointIndex); } } for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] /= PointCount; } for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { B.Cell(DimensionIndex, PointIndex) -= _Means[DimensionIndex]; } } DenseMatrix C; Console::WriteLine("Building correlation matrix..."); DenseMatrix::MultiplyMMTranspose(C, B); DenseMatrix::MultiplyInPlace(C, T(1.0) / T(PointCount)); InitFromCorrelationMatrix(C); } template void PCA::InitFromDensePoints(const Vector &Points, UINT Dimension) { Console::WriteLine(String("Initializing PCA, ") + String(Points.Length()) + String(" points, ") + String(Dimension) + String(" dimensions")); const UINT PointCount = Points.Length(); DenseMatrix B(Dimension, PointCount); _Means.Allocate(Dimension); _Means.Clear(0.0); for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { const T *CurPoint = Points[PointIndex]; for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] += CurPoint[DimensionIndex]; } } for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { _Means[DimensionIndex] /= PointCount; } for(UINT PointIndex = 0; PointIndex < PointCount; PointIndex++) { const T *CurPoint = Points[PointIndex]; for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { B[DimensionIndex][PointIndex] = CurPoint[DimensionIndex] - _Means[DimensionIndex]; } } DenseMatrix C; Console::WriteLine("Building correlation matrix..."); DenseMatrix::MultiplyMMTranspose(C, B); DenseMatrix::MultiplyInPlace(C, T(1.0) / T(PointCount)); InitFromCorrelationMatrix(C); } template void PCA::InitFromCorrelationMatrix(const DenseMatrix &C) { const UINT Dimension = C.RowCount(); const bool OutputMatlabAndExit = false; if(OutputMatlabAndExit) { Console::WriteLine("Outputting MATLAB matrix and exiting..."); C.SaveToMATLAB("C:\\MATLAB7\\work\\PCA.txt"); _Means.SaveToASCIIFile("C:\\JReaderData\\RawMeanVector.txt"); exit(0); } else { Console::WriteLine("Computing eigensystem..."); C.EigenSystem(_Eigenvalues, _Eigenvectors); Console::WriteLine(C.EigenTest(_Eigenvalues, _Eigenvectors)); //_Eigenvectors.SaveToMATLAB("C:\\MATLAB7\\work\\MyEigenvectors.txt"); //_Eigenvalues.SaveToASCIIFile("C:\\MATLAB7\\work\\MyEigenvalues.txt"); } FinalizeFromEigenSystem(); } template void PCA::InitFromMATLAB(UINT Dimension, const String &EigenvectorFilename, const String &EigenvalueFilename, const String &MeanFilename) { Console::WriteLine(String("Initializing PCA from MATLAB eigensystem files...")); //M = load('PCA.txt'); //[Eigenvectors, Eigenvalues] = eig(M); //dlmwrite('Eigenvectors.txt', Eigenvectors, ' '); //dlmwrite('Eigenvalues.txt', diag(Eigenvalues), ' '); _Means.LoadFromASCIIFile("C:\\JReaderData\\RawMeanVector.txt"); _Eigenvectors.Allocate(Dimension, Dimension); _Eigenvalues.Allocate(Dimension); ifstream EigenvectorFile(EigenvectorFilename.CString()); for(UINT Row = 0; Row < Dimension; Row++) { for(UINT Col = 0; Col < Dimension; Col++) { EigenvectorFile >> _Eigenvectors.Cell(Row, Dimension - 1 - Col); } } ifstream EigenvalueFile(EigenvalueFilename.CString()); for(UINT Index = 0; Index < Dimension; Index++) { EigenvalueFile >> _Eigenvalues[Dimension - 1 - Index]; } //_Eigenvectors.SaveToMATLAB("C:\\MATLAB7\\work\\RepeatedEigenvectors.txt"); //_Eigenvalues.SaveToASCIIFile("C:\\MATLAB7\\work\\RepeatedEigenvalues.txt"); FinalizeFromEigenSystem(); } template void PCA::FinalizeFromEigenSystem() { const UINT Dimension = _Eigenvalues.Length(); double EigenvalueSum = 0.0; for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { EigenvalueSum += Math::Max(T(0.0), _Eigenvalues[DimensionIndex]); } double CumulativeEnergy = 0.0; for(UINT DimensionIndex = 0; DimensionIndex < Dimension; DimensionIndex++) { CumulativeEnergy += _Eigenvalues[DimensionIndex]; Console::WriteLine(String("Energy at ") + String(DimensionIndex + 1) + String(" terms: ") + String(CumulativeEnergy / EigenvalueSum * 100.0f) + String("%")); } } template UINT PCA::ReducedDimension(double EnergyPercent) { double EigenvalueSum = 0.0; for(UINT DimensionIndex = 0; DimensionIndex < _Eigenvalues.Length(); DimensionIndex++) { EigenvalueSum += _Eigenvalues[DimensionIndex]; } double CumulativeEnergy = 0.0; for(UINT DimensionIndex = 0; DimensionIndex < _Eigenvalues.Length(); DimensionIndex++) { CumulativeEnergy += _Eigenvalues[DimensionIndex]; if(CumulativeEnergy / EigenvalueSum >= EnergyPercent) { return DimensionIndex + 1; } } return _Eigenvalues.Length(); } template void PCA::Transform(Vector &Result, const Vector &Input, UINT ReducedDimension) { if(Result.Length() != ReducedDimension) { Result.Allocate(ReducedDimension); } Transform(Result.CArray(), Input.CArray(), ReducedDimension); } template void PCA::InverseTransform(Vector &Result, const Vector &Input) { const UINT Dimension = _Means.Length(); Result.Allocate(Dimension); InverseTransform(Result.CArray(), Input.CArray(), Input.Length()); } template void PCA::Transform(T *Result, const T *Input, UINT ReducedDimension) { const UINT Dimension = _Means.Length(); for(UINT Row = 0; Row < ReducedDimension; Row++) { T Total = 0.0; for(UINT Index = 0; Index < Dimension; Index++) { Total += _Eigenvectors[Row][Index] * (Input[Index] - _Means[Index]); } Result[Row] = Total; } } template void PCA::InverseTransform(T *Result, const T *Input, UINT ReducedDimension) { UINT Dimension = _Means.Length(); for(UINT Col = 0; Col < Dimension; Col++) { T Total = 0.0; for(UINT Index = 0; Index < ReducedDimension; Index++) { Total += _Eigenvectors[Index][Col] * Input[Index]; } Result[Col] = Total + _Means[Col]; } }