/// <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 (if supported by the learning algorithm).</param>
        /// <returns>A model that has learned how to produce <paramref name="y" /> given <paramref name="x" />.</returns>
        /// <exception cref="System.InvalidOperationException">
        /// Please set the Learner property before calling the Learn(x, y) method.
        /// or
        /// Please set the Learner property before calling the Learn(x, y) method.
        /// </exception>
        public override SplitResult <TModel, TInput, TOutput> Learn(TInput[] x, TOutput[] y, double[] weights = null)
        {
            if (Learner == null)
            {
                throw new InvalidOperationException("Please set the Learner property before calling the Learn(x, y) method.");
            }

            if (Loss == null)
            {
                throw new InvalidOperationException("Please set the Learner property before calling the Learn(x, y) method.");
            }

            int n = x.Length;

            if (this.Indices == null || this.IndicesValidationSet == null || this.IndicesTrainingSet == null)
            {
                this.Indices = CreateValidationSplits(x, y);
                this.IndicesValidationSet = Indices.Find(i => i == 1);
                this.IndicesTrainingSet   = Indices.Find(i => i == 0);
            }
            else
            {
                this.ValidationSetProportion = this.IndicesValidationSet.Length / (double)this.Indices.Length;
            }

            var split = new TrainValDataSplit <TInput, TOutput>(0, x, y, weights, IndicesTrainingSet, IndicesValidationSet);

            SplitResult <TModel, TInput, TOutput> result = LearnSubset(split);

            return(result);
        }
예제 #2
0
        /// <summary>
        ///   Learns and evaluates a model in a single subset of the data.
        /// </summary>
        ///
        /// <param name="subset">The subset of the data containing the training and testing subsets where
        ///   a model should be trained and evaluated, respectively.</param>
        /// <param name="index">The index of this subset, if applicable.</param>
        ///
        /// <returns>A <see cref="SplitResult{TModel, TInput, TOutput}"/> object containing the created model
        ///   and its performance on the training and validation sets.</returns>
        ///
        protected SplitResult <TModel, TInput, TOutput> LearnSubset(TrainValDataSplit <TInput, TOutput> subset, int index = 0)
        {
            // Create the learning algorithm
            TLearner teacher = Learner(subset.Training);

            TInput[]  trainInputs  = subset.Training.Inputs;
            TOutput[] trainOutputs = subset.Training.Outputs;
            double[]  trainWeights = subset.Training.Weights;

            // Use the learning algorithm to learn a new model
            try
            {
                TModel model = Fit(teacher, trainInputs, trainOutputs, trainWeights);

                // Evaluate metrics using the created model
                TInput[]  valInputs  = subset.Validation.Inputs;
                TOutput[] valOutputs = subset.Validation.Outputs;
                double[]  valWeights = subset.Validation.Weights;

                var trainResult = new SetResult <TModel>(model, subset.Training.Indices, "Training", subset.Training.Proportion);
                var valResult   = new SetResult <TModel>(model, subset.Validation.Indices, "Validation", subset.Validation.Proportion);

                trainResult.Value = Loss(trainOutputs, model.Transform(trainInputs), trainResult);
                valResult.Value   = Loss(valOutputs, model.Transform(valInputs), valResult);

                return(new SplitResult <TModel, TInput, TOutput>(model, index: index)
                {
                    Training = trainResult,
                    Validation = valResult
                });
            }
            catch
            {
                if (!DefaultValue.HasValue)
                {
                    throw; // no default value has been set; we cannot do anything in this case
                }
                return(new SplitResult <TModel, TInput, TOutput>(null, index: index)
                {
                    Training = new SetResult <TModel>(null, subset.Training.Indices, "Training", subset.Training.Proportion)
                    {
                        Value = DefaultValue.Value
                    },

                    Validation = new SetResult <TModel>(null, subset.Validation.Indices, "Validation", subset.Validation.Proportion)
                    {
                        Value = DefaultValue.Value
                    }
                });
            }
        }