//--------------------------------------------- #region Public Methods /// <summary>Computes the Principal Component Analysis algorithm.</summary> public void Compute() { // Create a copy of the original matrix to work upon Matrix matrix = this.m_sourceMatrix.Clone(); // Calculate common measures to speedup other calculations this.m_mean = Tools.Mean(matrix); this.m_stdDev = Tools.StandardDeviation(matrix, m_mean); // Normalize the data if (this.Center) { Statistics.Tools.Center(matrix, m_mean); } if (this.Standardize) { Statistics.Tools.Standardize(matrix, m_stdDev); } if (Method == AnalysisMethod.SingularDefault || Method == AnalysisMethod.SingularStandard) { // Perform the Singular Value Decomposition (SVD) of the standardized matrix SingularValueDecomposition singularDecomposition = new SingularValueDecomposition(matrix); this.m_singularValues = new Vector(singularDecomposition.Diagonal); // Eigen values are the square of the singular values this.m_eigenValues = Vector.Pow(this.m_singularValues, 2); /* The principal components of 'sourceMatrix' are the eigenvectors of Cov(sourceMatrix). If we * calculate the SVD of 'matrix' (which is sourceMatrix standardized), the columns of matrix V * (right side of SVD) are the principal components of sourceMatrix. */ // The right singular vectors contains the principal components of the data matrix this.m_eigenVectors = singularDecomposition.RightSingularVectors; // The left singulare vectors contains the scores of the principal components } else { // Generate covariance matrix // (if data has already been standardized, this will be the correlation matrix) Matrix covarianceMatrix = Statistics.Tools.Covariance(matrix, m_mean); // Perform the Eigen Value Decomposition (EVD) of the covariance (or correlation) matrix EigenValueDecomposition eigenDecomposition = new EigenValueDecomposition(covarianceMatrix); this.m_eigenValues = eigenDecomposition.RealEigenValues; this.m_eigenVectors = eigenDecomposition.EigenVectors; // Now we have to sort EigenValues and EigenVectors in descending order of Eigen Values, // from left to right. (Higher eigenvalues <----> Lower eigenvalues). // EigenValueDecomposition already returned its vectors and values in reverse // order, so we just have to reverse our arrays. this.m_eigenValues.Reverse(); this.m_eigenVectors.ReverseColumns(); // Because Sigular Values have not been computed, create a empty vector // to avoid Null reference exceptions. this.m_singularValues = new Vector(m_eigenValues.Length); } // Calculate proportions and cumulative proportions this.m_proportions = this.m_eigenValues * (1.0 / this.m_eigenValues.Sum); this.m_cumulativeProportions = new Vector(this.m_sourceMatrix.Columns); this.m_cumulativeProportions[0] = this.m_proportions[0]; for (int i = 1; i < this.m_cumulativeProportions.Length; i++) { this.m_cumulativeProportions[i] = this.m_cumulativeProportions[i - 1] + this.m_proportions[i]; } // Creates the object-oriented structure to hold the principal components PrincipalComponent[] components = new PrincipalComponent[m_singularValues.Length]; for (int i = 0; i < components.Length; i++) { components[i] = new PrincipalComponent(this, i); } this.m_componentCollection = new PrincipalComponentCollection(components); // Calculate the orthogonal projected data matrix (using all available components) this.m_resultMatrix = matrix * this.m_eigenVectors; }
//--------------------------------------------- #region Public Methods /// <summary>Computes the Kernel Principal Component Analysis algorithm.</summary> public override void Compute() { int rows = Source.GetLength(0); int cols = Source.GetLength(1); // Center (adjust) the source matrix sourceCentered = adjust(Source); // Create the Gram (Kernel) Matrix double[,] K = new double[rows, rows]; for (int i = 0; i < rows; i++) { for (int j = i; j < rows; j++) { double k = kernel.Kernel(sourceCentered.GetRow(i), sourceCentered.GetRow(j)); K[i, j] = k; // Kernel matrix is symmetric K[j, i] = k; } } // Center the Gram (Kernel) Matrix if (centerFeatureSpace) { K = centerKernel(K); } // Perform the Eigen Value Decomposition (EVD) of the Kernel matrix EigenValueDecomposition evd = new EigenValueDecomposition(K); // Gets the eigenvalues and corresponding eigenvectors double[] evals = evd.RealEigenValues; double[,] eigs = evd.EigenVectors; // Sort eigen values and vectors in ascending order int[] indices = new int[rows]; for (int i = 0; i < rows; i++) { indices[i] = i; } Array.Sort(evals, indices, new AbsoluteComparer(true)); eigs = eigs.Submatrix(0, rows - 1, indices); // Normalize eigenvectors if (centerFeatureSpace) { for (int j = 0; j < rows; j++) { double eig = System.Math.Sqrt(System.Math.Abs(evals[j])); for (int i = 0; i < rows; i++) { eigs[i, j] = eigs[i, j] / eig; } } } // Set analysis properties this.SingularValues = new double[rows]; this.EigenValues = evals; this.ComponentMatrix = eigs; // Project the original data into principal component space double[,] result = new double[rows, rows]; for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { for (int k = 0; k < rows; k++) { result[i, j] += K[i, k] * eigs[k, j]; } } } this.Result = result; // Computes additional information about the analysis and creates the // object-oriented structure to hold the principal components found. createComponents(); }