/// <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); }
/// <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 } }); } }