#region License Information
/* HeuristicLab
* Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Threading;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.MainForm;
using HeuristicLab.Problems.DataAnalysis.Symbolic.Views;
namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views {
public partial class InteractiveSymbolicRegressionSolutionSimplifierView : InteractiveSymbolicDataAnalysisSolutionSimplifierView {
public new SymbolicRegressionSolution Content {
get { return (SymbolicRegressionSolution)base.Content; }
set { base.Content = value; }
}
public InteractiveSymbolicRegressionSolutionSimplifierView()
: base(new SymbolicRegressionSolutionImpactValuesCalculator()) {
InitializeComponent();
this.Caption = "Interactive Regression Solution Simplifier";
}
protected override void SetEnabledStateOfControls() {
base.SetEnabledStateOfControls();
var tree = Content?.Model?.SymbolicExpressionTree;
btnOptimizeConstants.Enabled = tree != null && NonlinearLeastSquaresConstantOptimizationEvaluator.CanOptimizeConstants(tree);
btnVectorOptimizeConstants.Enabled = tree != null && TensorFlowConstantOptimizationEvaluator.CanOptimizeConstants(tree);
nudLearningRate.Enabled = tree != null && TensorFlowConstantOptimizationEvaluator.CanOptimizeConstants(tree);
btnUnrollingVectorOptimizeConstants.Enabled = tree != null && VectorUnrollingNonlinearLeastSquaresConstantOptimizationEvaluator.CanOptimizeConstants(tree);
#if INCLUDE_DIFFSHARP
btnDiffSharpOptimizeConstants.Enabled = tree != null && NonlinearLeastSquaresVectorConstantOptimizationEvaluator.CanOptimizeConstants(tree);
#endif
}
protected override void UpdateModel(ISymbolicExpressionTree tree) {
var model = new SymbolicRegressionModel(Content.ProblemData.TargetVariable, tree, Content.Model.Interpreter, Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit);
model.Scale(Content.ProblemData);
Content.Model = model;
}
protected override ISymbolicExpressionTree OptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
const int constOptIterations = 50;
const int maxRepetitions = 100;
const double minimumImprovement = 1e-10;
var regressionProblemData = Content.ProblemData;
var model = Content.Model;
progress.CanBeStopped = true;
double prevResult = 0.0, improvement = 0.0;
var result = 0.0;
int reps = 0;
do {
prevResult = result;
tree = NonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData, regressionProblemData.TrainingIndices,
applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true,
cancellationToken: cancellationToken, iterationCallback: (args, func, obj) => {
double newProgressValue = progress.ProgressValue + (1.0 / (constOptIterations + 2) / maxRepetitions); // (constOptIterations + 2) iterations are reported
progress.ProgressValue = Math.Min(newProgressValue, 1.0);
progress.Message = $"MSE: { func / regressionProblemData.TrainingPartition.Size }";
});
result = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(model.Interpreter, tree,
model.LowerEstimationLimit, model.UpperEstimationLimit, regressionProblemData, regressionProblemData.TrainingIndices, applyLinearScaling: true);
reps++;
improvement = result - prevResult;
} while (improvement > minimumImprovement && reps < maxRepetitions &&
progress.ProgressState != ProgressState.StopRequested &&
progress.ProgressState != ProgressState.CancelRequested);
return tree;
}
protected override ISymbolicExpressionTree VectorOptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
const int maxIterations = 1000;
var regressionProblemData = Content.ProblemData;
progress.CanBeStopped = true;
var learningRate = Math.Pow(10, (double)nudLearningRate.Value);
return TensorFlowConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData,
regressionProblemData.TrainingIndices,
//new int[]{ 0, 1 },
applyLinearScaling: false, updateVariableWeights: true, maxIterations: maxIterations, learningRate: learningRate,
cancellationToken: cancellationToken,
progress: new SynchronousProgress(cost => {
var newProgress = progress.ProgressValue + (1.0 / (maxIterations + 1));
progress.ProgressValue = Math.Min(newProgress, 1.0);
progress.Message = $"MSE: {cost}";
})
);
}
protected override ISymbolicExpressionTree UnrollingVectorOptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
const int constOptIterations = 50;
const int maxRepetitions = 100;
const double minimumImprovement = 1e-10;
var regressionProblemData = Content.ProblemData;
var model = Content.Model;
progress.CanBeStopped = true;
double prevResult = 0.0, improvement = 0.0;
var result = 0.0;
int reps = 0;
var interpreter = new SymbolicDataAnalysisExpressionTreeVectorInterpreter();
do {
prevResult = result;
tree = VectorUnrollingNonlinearLeastSquaresConstantOptimizationEvaluator.OptimizeTree(
tree, interpreter,
regressionProblemData,
regressionProblemData.TrainingIndices,
//new int[] { 0, 1 },
applyLinearScaling: false, maxIterations: constOptIterations, updateVariableWeights: true,
cancellationToken: cancellationToken, iterationCallback: (args, func, obj) => {
double newProgressValue = progress.ProgressValue + (1.0 / (constOptIterations + 2) / maxRepetitions); // (constOptIterations + 2) iterations are reported
progress.ProgressValue = Math.Min(newProgressValue, 1.0);
progress.Message = $"MSE: { func / regressionProblemData.TrainingPartition.Size }";
});
result = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(model.Interpreter, tree,
model.LowerEstimationLimit, model.UpperEstimationLimit, regressionProblemData, regressionProblemData.TrainingIndices, applyLinearScaling: true);
reps++;
improvement = result - prevResult;
} while (improvement > minimumImprovement && reps < maxRepetitions &&
progress.ProgressState != ProgressState.StopRequested &&
progress.ProgressState != ProgressState.CancelRequested);
return tree;
}
protected override ISymbolicExpressionTree DiffSharpVectorOptimizeConstants(ISymbolicExpressionTree tree, CancellationToken cancellationToken, IProgress progress) {
const int constOptIterations = 50;
const int maxRepetitions = 100;
const double minimumImprovement = 1e-10;
var regressionProblemData = Content.ProblemData;
var model = Content.Model;
progress.CanBeStopped = true;
double prevResult = 0.0, improvement = 0.0;
var result = 0.0;
int reps = 0;
#if INCLUDE_DIFFSHARP
do {
prevResult = result;
tree = NonlinearLeastSquaresVectorConstantOptimizationEvaluator.OptimizeTree(tree, regressionProblemData, regressionProblemData.TrainingIndices,
applyLinearScaling: true, maxIterations: constOptIterations, updateVariableWeights: true,
cancellationToken: cancellationToken, iterationCallback: (args, func, obj) => {
double newProgressValue = progress.ProgressValue + (1.0 / (constOptIterations + 2) / maxRepetitions); // (constOptIterations + 2) iterations are reported
progress.ProgressValue = Math.Min(newProgressValue, 1.0);
progress.Message = $"MSE: { func / regressionProblemData.TrainingPartition.Size }";
});
result = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(model.Interpreter, tree,
model.LowerEstimationLimit, model.UpperEstimationLimit, regressionProblemData, regressionProblemData.TrainingIndices, applyLinearScaling: true);
reps++;
improvement = result - prevResult;
} while (improvement > minimumImprovement && reps < maxRepetitions &&
progress.ProgressState != ProgressState.StopRequested &&
progress.ProgressState != ProgressState.CancelRequested);
#endif
return tree;
}
internal class SynchronousProgress : IProgress {
private readonly Action callback;
public SynchronousProgress(Action callback) {
this.callback = callback;
}
public void Report(T value) {
callback(value);
}
}
}
}