Accord.Math.Decompositions.NonnegativeFactorization.init C# (CSharp) Метод

init() приватный Метод

Constructs a new non-negative matrix factorization.
private init ( double value, int k, NonnegativeFactorizationAlgorithm algorithm, double h0, double w0, int attempts, int maxIterations, double errorTolerance, double changeTolerance ) : void
value double
k int
algorithm NonnegativeFactorizationAlgorithm
h0 double
w0 double
attempts int
maxIterations int
errorTolerance double
changeTolerance double
Результат void
        private void init(double[,] value, int k, NonnegativeFactorizationAlgorithm algorithm,
                          double[,] h0, double[,] w0, int attempts, int maxIterations, double errorTolerance,
                          double changeTolerance)
        {
            #region Initial argument checking

            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (k < 0 || k > value.GetLength(1))
            {
                throw new ArgumentException(
                    "The approximation rank k should be a positive integer equal or less than the number of columns of the matrix to be decomposed.",
                    "k");
            }

            if (h0 != null)
            {
                if (h0.GetLength(0) != k || h0.GetLength(1) != value.GetLength(1))
                    throw new ArgumentException(
                        "The initial coefficient matrix should have the same number of columns as the value matrix and the same number of rows as the desired rank approximation.",
                        "h0");
            }

            if (w0 != null)
            {
                if (w0.GetLength(0) != value.GetLength(0) || w0.GetLength(1) != k)
                    throw new ArgumentException(
                        "The initial weight matrix should have the same number of rows as the value matrix and the same number of columns as the desired rank approximation.",
                        "w0");
            }

            if (attempts <= 0)
            {
                throw new ArgumentException("The number of parallel attempts should be greater than zero.", "attempts");
            }

            if (maxIterations <= 0)
            {
                throw new ArgumentException("The maximum number of iterations should be greater than zero.",
                                            "maxIterations");
            }

            if (errorTolerance <= 0)
            {
                throw new ArgumentException("The error tolerance convergence threshold should be greater than zero.",
                                            "errorTolerance");
            }

            if (changeTolerance <= 0)
            {
                throw new ArgumentException(
                    "The maximum absolute factor change convergence threshold should be greater than zero.",
                    "changeTolerance");
            }

            #endregion

            // Initialization
            double[,] X = value;
            n = X.GetLength(0);
            m = X.GetLength(1);
            this.k = k;
            W = w0;
            H = h0;


            // First, check for special case
            if (W == null && H == null)
            {
                // In the case both W and H are to
                // be found, the answer is direct.

                if (k == m)
                {
                    W = X;
                    H = Matrix.Identity(k);
                }
                else if (k == n)
                {
                    W = Matrix.Identity(k);
                    H = X;
                }
            }


            // Next we will attempt several factorizations
            //  and return the one which produces the best
            //  approximation norm.

            // TODO: This should be parallelized.

            double bestNorm = Double.PositiveInfinity;
            double[,] bestW = null;
            double[,] bestH = null;

            // Perform several parallel attempts
            for (int t = 0; t < attempts; t++)
            {
                // Perform round initialization to random values
                if (W == null || t > 0) W = Matrix.Random(n, k);
                if (H == null || t > 0) H = Matrix.Random(k, m);
                double norm = Double.PositiveInfinity;


                // Perform a factorization
                norm = nnmf(X, ref W, ref H, algorithm,
                            maxIterations, errorTolerance, changeTolerance);


                // Check if this has been the
                //  best factorization so far
                if (norm < bestNorm)
                {
                    bestNorm = norm;
                    bestW = W;
                    bestH = H;
                }
            }


            // Select the best factorization
            //  and normalize the results

            H = bestH;
            W = bestW;

            for (int i = 0; i < k; i++)
            {
                double norm = 0.0, v;
                for (int j = 0; j < m; j++)
                {
                    v = H[i, j];
                    norm += v*v;
                }

                if (norm == 0) // If any of the norms equals 0
                {
                    // Then the algorithm has converged to a solution
                    // with a different rank than the rank specified.
                    norm = 1;
                }
                else
                {
                    norm = System.Math.Sqrt(norm);
                }

                // Normalize H and re-scale W
                for (int j = 0; j < m; j++)
                    H[i, j] /= norm;

                for (int j = 0; j < n; j++)
                    W[j, i] *= norm;
            }

            // Then order by the norms of W
            var wnorm = new double[k];
            var index = new int[k];
            for (int j = 0; j < k; j++)
            {
                double norm = 0.0, d;
                for (int i = 0; i < n; i++)
                {
                    d = W[i, j];
                    norm += d*d;
                }

                // Set as minus to order
                //  in descending order
                wnorm[j] = -norm;
                index[j] = j;
            }

            Array.Sort(wnorm, index);

            W = W.Submatrix(null, index);
            H = H.Submatrix(index, null);
        }