public static INDArray pca_factor(INDArray A, double variance, boolean normalize) {
        if (normalize) {
            // Normalize to mean 0 for each feature ( each column has 0 mean )
            INDArray mean = A.mean(0);
            A.subiRowVector(mean);
        }

        long m = A.rows();
        long n = A.columns();

        // The prepare SVD results, we'll decomp A to UxSxV'
        INDArray s = Nd4j.create(A.dataType(), m < n ? m : n);
        INDArray VT = Nd4j.create(A.dataType(), new long[]{n, n}, 'f');

        // Note - we don't care about U 
        Nd4j.getBlasWrapper().lapack().gesvd(A, s, null, VT);

        // Now convert the eigs of X into the eigs of the covariance matrix
        for (int i = 0; i < s.length(); i++) {
            s.putScalar(i, Math.sqrt(s.getDouble(i)) / (m - 1));
        }

        // Now find how many features we need to preserve the required variance
        // Which is the same percentage as a cumulative sum of the eigenvalues' percentages
        double totalEigSum = s.sumNumber().doubleValue() * variance;
        int k = -1; // we will reduce to k dimensions
        double runningTotal = 0;
        for (int i = 0; i < s.length(); i++) {
            runningTotal += s.getDouble(i);
            if (runningTotal >= totalEigSum) { // OK I know it's a float, but what else can we do ?
                k = i + 1; // we will keep this many features to preserve the reqd. variance
                break;
            }
        }
        if (k == -1) { // if we need everything
            throw new RuntimeException("No reduction possible for reqd. variance - use smaller variance");
        }
        // So now let's rip out the appropriate number of left singular vectors from
        // the V output (note we pulls rows since VT is a transpose of V)
        INDArray V = VT.transpose();
        INDArray factor = Nd4j.createUninitialized(A.dataType(), new long[]{n, k}, 'f');
        for (int i = 0; i < k; i++) {
            factor.putColumn(i, V.getColumn(i));
        }

        return factor;
    }
public static INDArray pca_factor ( INDArray A , double variance , boolean normalize ) { if ( normalize ) { INDArray mean = A . mean ( 0 ) ; A . subiRowVector ( mean ) ; } long m = A . rows ( ) ; long n = A . columns ( ) ; INDArray s = Nd4j . create ( A . dataType ( ) , m < n ? m : n ) ; INDArray VT = Nd4j . create ( A . dataType ( ) , new long [ ] { n , n } , 'f' ) ; Nd4j . getBlasWrapper ( ) . lapack ( ) . gesvd ( A , s , null , VT ) ; for ( int i = 0 ; i < s . length ( ) ; i ++ ) { s . putScalar ( i , Math . sqrt ( s . getDouble ( i ) ) / ( m - 1 ) ) ; } double totalEigSum = s . sumNumber ( ) . doubleValue ( ) * variance ; int k = - 1 ; double runningTotal = 0 ; for ( int i = 0 ; i < s . length ( ) ; i ++ ) { runningTotal += s . getDouble ( i ) ; if ( runningTotal >= totalEigSum ) { k = i + 1 ; break ; } } if ( k == - 1 ) { throw new RuntimeException ( "No reduction possible for reqd. variance - use smaller variance" ) ; } INDArray V = VT . transpose ( ) ; INDArray factor = Nd4j . createUninitialized ( A . dataType ( ) , new long [ ] { n , k } , 'f' ) ; for ( int i = 0 ; i < k ; i ++ ) { factor . putColumn ( i , V . getColumn ( i ) ) ; } return factor ; }
Calculates pca vectors of a matrix, for a given variance. A larger variance (99%)
will result in a higher order feature set.

To use the returned factor: multiply feature(s) by the factor to get a reduced dimension

INDArray Areduced = A.mmul( factor ) ;

The array Areduced is a projection of A onto principal components

@see pca(INDArray, double, boolean)

@param A the array of features, rows are results, columns are features - will be changed
@param variance the amount of variance to preserve as a float 0 - 1
@param normalize whether to normalize (set features to have zero mean)
@return the matrix to mulitiply a feature by to get a reduced feature set