/// <summary> /// In order to also make use of historical data, <see cref="ReuseOldTreesStrategy"/> selects <see cref="KeepOldTreeRatio"/> * nTrees many <see cref="IEnsemblePredictor{TWeakPredictor}.InternalModels"/> (at random) and replaces them with (randomly chosen) models from the previous generation's <see cref="IEnsemblePredictor{TWeakPredictor}"/>. /// In the first iteration, this method only sets <see cref="OldEnsemble"/> to <paramref name="newModel"/>. /// </summary> /// <param name="newModel">The freshly trained predictor model, using data from <see cref="AggregateTargets"/>.</param> public void PostProcessModel(IEnsemblePredictor <IGenomePredictor> newModel) { // no old weak learners to reuse in 1st iteration if (this.OldEnsemble == null) { this.OldEnsemble = newModel; return; } // our RF stores the internal models as list. c# will not treat this as enumerable, but internally cast instead var numberToReuse = (int)Math.Ceiling(this.OldEnsemble.InternalModels.Length * this.KeepOldTreeRatio); var reusedTrees = Randomizer.Instance.ChooseRandomSubset(this.OldEnsemble.InternalModels, numberToReuse).ToArray(); var treeIndexToReplace = Randomizer.Instance.ChooseRandomSubset(Enumerable.Range(0, newModel.InternalModels.Length), numberToReuse) .ToArray(); // replace trees for (var replaceIndex = 0; replaceIndex < numberToReuse; replaceIndex++) { newModel.InternalModels[treeIndexToReplace[replaceIndex]] = reusedTrees[replaceIndex]; } // update previous ensemble this.OldEnsemble = newModel; }
/// <summary> /// Model is not altered. /// </summary> /// <param name="newModel"> /// Parameter is ignored. /// </param> public void PostProcessModel(IEnsemblePredictor <IGenomePredictor> newModel) { return; }