Beispiel #1
0
        /// <summary>
        /// Learns a model that can map the given inputs to the given outputs.
        /// </summary>
        /// <param name="x">The model inputs.</param>
        /// <param name="y">The desired outputs associated with each <paramref name="x">inputs</paramref>.</param>
        /// <param name="weights">The weight of importance for each input-output pair.</param>
        /// <returns>
        /// A model that has learned how to produce <paramref name="y" /> given <paramref name="x" />.
        /// </returns>
        public Pipeline Learn(double[][] x, int[] y, double[] weights = null)
        {
            Init(x, y);

            // Compute entire data set measures
            Means = Measures.Mean(x, dimension: 0);
            StandardDeviations = Measures.StandardDeviation(x, Means);

            // Initialize the scatter matrices
            var Sw = Jagged.Zeros(NumberOfInputs, NumberOfInputs);
            var Sb = Jagged.Zeros(NumberOfInputs, NumberOfInputs);

            // For each class
            for (int c = 0; c < Classes.Count; c++)
            {
                int[] idx = Matrix.Find(y, y_i => y_i == Classes[c].Number);

                // Get the class subset
                double[][] subset = x.Get(idx);
                int        count  = subset.GetLength(0);

                // Get the class mean
                double[] mean = Measures.Mean(subset, dimension: 0);

                // Continue constructing the Within-Class Scatter Matrix
                double[][] Swi = Measures.Scatter(subset, mean, (double)count);

                Sw.Add(Swi, result: Sw); // Sw = Sw + Swi

                // Continue constructing the Between-Class Scatter Matrix
                double[]   d   = mean.Subtract(Means);
                double[][] Sbi = Jagged.Outer(d, d);
                Sbi.Multiply((double)NumberOfInputs, result: Sbi);

                Sb.Add(Sbi, result: Sb); // Sb = Sb + Sbi

                // Store some additional information
                this.classScatter[c] = Swi;
                this.classCount[c]   = count;
                this.classMeans[c]   = mean;
                this.classStdDevs[c] = Measures.StandardDeviation(subset, mean);
            }


            // Compute the generalized eigenvalue decomposition
            var gevd = new JaggedGeneralizedEigenvalueDecomposition(Sb, Sw, sort: true);

            // Get the eigenvalues and corresponding eigenvectors
            double[]   evals = gevd.RealEigenvalues;
            double[][] eigs  = gevd.Eigenvectors;

            // Eliminate unwanted components
            int nonzero = x.Columns();

            if (Threshold > 0)
            {
                nonzero = Math.Min(gevd.Rank, GetNonzeroEigenvalues(evals, Threshold));
            }
            if (NumberOfInputs != 0)
            {
                nonzero = Math.Min(nonzero, NumberOfInputs);
            }
            if (NumberOfOutputs != 0)
            {
                nonzero = Math.Min(nonzero, NumberOfOutputs);
            }

            eigs  = eigs.Get(null, 0, nonzero);
            evals = evals.Get(0, nonzero);

            // Store information
            this.Eigenvalues         = evals;
            this.DiscriminantVectors = eigs.Transpose();
            base.ScatterBetweenClass = Sb;
            base.ScatterWithinClass  = Sw;
            base.NumberOfInputs      = x.Columns();
            base.NumberOfOutputs     = evals.Length;

            // Compute feature space means for later classification
            for (int c = 0; c < projectedMeans.Length; c++)
            {
                projectedMeans[c] = classMeans[c].Dot(eigs);
            }

            // Computes additional information about the analysis and creates the
            //  object-oriented structure to hold the discriminants found.
            CreateDiscriminants();

            this.Classifier = CreateClassifier();

            return(Classifier);
        }
        /// <summary>
        /// Learns a model that can map the given inputs to the given outputs.
        /// </summary>
        /// <param name="x">The model inputs.</param>
        /// <param name="y">The desired outputs associated with each <paramref name="x">inputs</paramref>.</param>
        /// <param name="weights">The weight of importance for each input-output pair.</param>
        /// <returns>
        /// A model that has learned how to produce <paramref name="y" /> given <paramref name="x" />.
        /// </returns>
        ///
        public Pipeline Learn(double[][] x, int[] y, double[] weights = null)
        {
            Init(x, y);

            // Create the Gram (Kernel) Matrix
            var K = kernel.ToJagged(x);

            // Compute entire data set measures
            base.Means = Measures.Mean(K, dimension: 0);
            base.StandardDeviations = Measures.StandardDeviation(K, Means);

            // Initialize the kernel analogous scatter matrices
            //int dimension = x.Columns();
            double[][] Sb = Jagged.Zeros(NumberOfSamples, NumberOfSamples);
            double[][] Sw = Jagged.Zeros(NumberOfSamples, NumberOfSamples);

            // For each class
            for (int c = 0; c < Classes.Count; c++)
            {
                var idx = Matrix.Find(y, y_i => y_i == c);

                // Get the Kernel matrix class subset
                double[][] Kc    = K.Get(idx);
                int        count = Kc.Rows();

                // Get the Kernel matrix class mean
                double[] mean = Measures.Mean(Kc, dimension: 0);

                // Construct the Kernel equivalent of the Within-Class Scatter matrix
                double[][] Swi = Measures.Scatter(Kc, dimension: 0, means: mean);
                Swi.Divide((double)count, result: Swi);
                Sw.Add(Swi, result: Sw); // Sw = Sw + Swi

                // Construct the Kernel equivalent of the Between-Class Scatter matrix
                double[]   d   = mean.Subtract(base.Means);
                double[][] Sbi = Jagged.Outer(d, d);
                Sbi.Multiply((double)NumberOfSamples, result: Sbi);

                Sb.Add(Sbi, result: Sb); // Sb = Sb + Sbi

                // Store additional information
                base.ClassScatter[c]            = Swi;
                base.ClassCount[c]              = count;
                base.ClassMeans[c]              = mean;
                base.ClassStandardDeviations[c] = Measures.StandardDeviation(Kc, mean);
            }

            // Add regularization to avoid singularity
            Sw.AddToDiagonal(regularization, result: Sw);

            // Compute the generalized eigenvalue decomposition
            var gevd = new JaggedGeneralizedEigenvalueDecomposition(Sb, Sw, sort: true);

            if (gevd.IsSingular) // check validity of the results
            {
                throw new SingularMatrixException("One of the matrices is singular. Please retry " +
                                                  "the method with a higher regularization constant.");
            }

            // Get the eigenvalues and corresponding eigenvectors
            double[]   evals = gevd.RealEigenvalues;
            double[][] eigs  = gevd.Eigenvectors;

            // Eliminate unwanted components
            int nonzero = x.Columns();

            if (Threshold > 0)
            {
                nonzero = Math.Min(gevd.Rank, GetNonzeroEigenvalues(evals, Threshold));
            }
            if (NumberOfInputs != 0)
            {
                nonzero = Math.Min(nonzero, NumberOfInputs);
            }
            if (NumberOfOutputs != 0)
            {
                nonzero = Math.Min(nonzero, NumberOfOutputs);
            }

            eigs  = eigs.Get(null, 0, nonzero);
            evals = evals.Get(0, nonzero);

            // Store information
            this.input               = x;
            base.Eigenvalues         = evals;
            base.DiscriminantVectors = eigs.Transpose();
            base.ScatterBetweenClass = Sb;
            base.ScatterWithinClass  = Sw;
            base.NumberOfOutputs     = evals.Length;

            // Compute feature space means for later classification
            for (int c = 0; c < Classes.Count; c++)
            {
                ProjectionMeans[c] = ClassMeans[c].Dot(eigs);
            }

            // Computes additional information about the analysis and creates the
            //  object-oriented structure to hold the discriminants found.
            CreateDiscriminants();

            this.Classifier = CreateClassifier();

            return(Classifier);
        }