Changeset 15064 for branches/EfficientGlobalOptimization/HeuristicLab.Algorithms.EGO/EfficientGlobalOptimizationAlgorithm.cs
- Timestamp:
- 06/26/17 09:10:56 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/EfficientGlobalOptimization/HeuristicLab.Algorithms.EGO/EfficientGlobalOptimizationAlgorithm.cs
r14833 r15064 24 24 using System.Linq; 25 25 using System.Threading; 26 using System.Windows.Forms;27 26 using HeuristicLab.Algorithms.DataAnalysis; 28 27 using HeuristicLab.Analysis; … … 35 34 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 36 35 using HeuristicLab.Problems.DataAnalysis; 37 using HeuristicLab.Problems.Instances.DataAnalysis; 38 using HeuristicLab.Problems.Instances.DataAnalysis.Views; 36 using HeuristicLab.Problems.Instances; 39 37 using HeuristicLab.Random; 40 38 … … 42 40 [StorableClass] 43 41 [Creatable(CreatableAttribute.Categories.Algorithms, Priority = 95)] 44 [Item("EfficientGlobalOptimizationAlgor tihm", "Solves a problem by sequentially learning a model, solving a subproblem on the model and evaluating the best found solution for this subproblem.")]42 [Item("EfficientGlobalOptimizationAlgorithm", "Solves a problem by sequentially learning a model, solving a subproblem on the model and evaluating the best found solution for this subproblem.")] 45 43 public class EfficientGlobalOptimizationAlgorithm : BasicAlgorithm, ISurrogateAlgorithm<RealVector> { 46 44 #region Basic-Alg-Essentials … … 84 82 #endregion 85 83 86 #region TransmissionResultNames87 public const string BestInfillSolutionResultName = "BestInfillSolution";88 public const string BestInfillQualityResultName = "BestInfillQuality";89 #endregion90 91 84 #region ParameterProperties 92 85 public IFixedValueParameter<IntValue> GenerationSizeParemeter => Parameters[GenerationSizeParameterName] as IFixedValueParameter<IntValue>; … … 108 101 109 102 #region Properties 110 111 103 public int GenerationSize => GenerationSizeParemeter.Value.Value; 112 104 public IInfillCriterion InfillCriterion => InfillCriterionParameter.Value; … … 123 115 ? Samples.Skip(Samples.Count - MaximalDatasetSize) 124 116 : Samples; 125 126 117 private bool RemoveDuplicates => RemoveDuplicatesParameter.Value.Value; 127 118 private RealVector BaselineVector => BaselineVectorParameter.Value; … … 161 152 private DataTable ResultsQualities => (DataTable)Results[QualitiesChartResultName].Value; 162 153 private DataRow ResultsQualitiesBest => ResultsQualities.Rows[BestQualitiesRowResultName]; 163 164 154 private DataRow ResultsQualitiesWorst => ResultsQualities.Rows[WorstQualitiesRowResultName]; 165 166 155 private DataRow ResultsQualitiesIteration => ResultsQualities.Rows[CurrentQualitiesRowResultName]; 167 168 156 private IRegressionSolution ResultsModel 169 157 { … … 177 165 protected EfficientGlobalOptimizationAlgorithm(bool deserializing) : base(deserializing) { } 178 166 [StorableHook(HookType.AfterDeserialization)] 179 pr ivatevoid AfterDeseialization() {167 protected void AfterDeseialization() { 180 168 RegisterEventhandlers(); 181 169 } 182 protected EfficientGlobalOptimizationAlgorithm(EfficientGlobalOptimizationAlgorithm original, Cloner cloner) 183 : base(original, cloner) { 170 protected EfficientGlobalOptimizationAlgorithm(EfficientGlobalOptimizationAlgorithm original, Cloner cloner) : base(original, cloner) { 184 171 Random = cloner.Clone(Random); 185 172 if (original.Samples != null) Samples = original.Samples.Select(x => new Tuple<RealVector, double>(cloner.Clone(x.Item1), x.Item2)).ToList(); 186 if (original.InitialSamples != null) Samples = original.InitialSamples.Select(x => new Tuple<RealVector, double>(cloner.Clone(x.Item1), x.Item2)).ToList();173 if (original.InitialSamples != null) InitialSamples = original.InitialSamples.Select(x => new Tuple<RealVector, double>(cloner.Clone(x.Item1), x.Item2)).ToList(); 187 174 RegisterEventhandlers(); 188 175 } 189 176 public override IDeepCloneable Clone(Cloner cloner) { return new EfficientGlobalOptimizationAlgorithm(this, cloner); } 190 177 public EfficientGlobalOptimizationAlgorithm() { 178 IProblemInstanceExporter dummy = new RegressionProblem(); //this variable is irrelevant 179 //the dummy variable enforces a using-Statement for HeuristicLab.Problems.Instances 180 //"new ValueParameter<IDataAnalysisAlgorithm<IRegressionProblem>>" requires no using using-Statement, but nontheless it requires HeuristicLab.Problems.Instances to be referenced 181 //Having HeuristicLab.Problems.Instances referenced but not used, causes the Essential-Unit-tests to fail. 182 191 183 var cmaes = new CMAEvolutionStrategy.CMAEvolutionStrategy { 192 184 MaximumGenerations = 300, … … 206 198 Parameters.Add(new FixedValueParameter<IntValue>(InfillOptimizationRestartsParameterName, "Number of restarts of the SubAlgortihm to avoid local optima", new IntValue(1))); 207 199 Parameters.Add(new FixedValueParameter<IntValue>(GenerationSizeParameterName, "Number points that are sampled every iteration (stadard EGO: 1)", new IntValue(1))); 208 Parameters.Add(new ConstrainedValueParameter<IInfillCriterion>(InfillCriterionParameterName, "Decision what value should decide the next sample"));209 InfillCriterionParameter.ValidValues.Add(new ExpectedImprovement());210 InfillCriterionParameter.ValidValues.Add(new AugmentedExpectedImprovement());211 InfillCriterionParameter.ValidValues.Add(new ExpectedQuality());212 var eqi = new ExpectedQuantileImprovement();213 InfillCriterionParameter.ValidValues.Add(eqi);214 eqi.MaxEvaluationsParameter.Value = MaximumEvaluationsParameter.Value;215 InfillCriterionParameter.ValidValues.Add(new MinimalQuantileCriterium());216 InfillCriterionParameter.ValidValues.Add(new RobustImprovement());217 InfillCriterionParameter.ValidValues.Add(new PluginExpectedImprovement());218 200 Parameters.Add(new FixedValueParameter<IntValue>(MaximalDataSetSizeParameterName, "The maximum number of sample points used to generate the model. Set 0 or less to use always all samples ", new IntValue(-1))); 219 201 Parameters.Add(new FixedValueParameter<BoolValue>(RemoveDuplicatesParamterName, "Wether duplicate samples should be replaced by a single sample with an averaged quality. This GREATLY decreases the chance of ill conditioned models (unbuildable models) but is not theoretically sound as the model ignores the increasing certainty in this region")); 220 202 Parameters.Add(new FixedValueParameter<FileValue>(InitialSamplesParameterName, "The file specifying some initial samples used to jump start the algorithm. These samples are not counted as evaluations. If InitialEvaluations is more than the samples specified in the file, the rest is uniformly random generated and evaluated.", new FileValue())); 221 203 Parameters.Add(new ValueParameter<RealVector>(BaselineVectorParameterName, "A vector used to create a baseline, this vector is evaluated once and is not part of the modeling process (has no influence on algorithm performance)")); 222 var intialSamplingPlans = new ItemSet<IInitialSampling> { new UniformRandomSampling(), new LatinHyperCubeDesign() }; 223 Parameters.Add(new ConstrainedValueParameter<IInitialSampling>(InitialSamplingPlanParamterName, intialSamplingPlans, intialSamplingPlans.First())); 224 204 var eqi = new ExpectedQuantileImprovement(); 205 eqi.MaxEvaluationsParameter.Value = MaximumEvaluationsParameter.Value; 206 var criteria = new ItemSet<IInfillCriterion> { new ExpectedImprovement(), new AugmentedExpectedImprovement(), new ExpectedQuality(), eqi, new MinimalQuantileCriterium(), new PluginExpectedImprovement() }; 207 Parameters.Add(new ConstrainedValueParameter<IInfillCriterion>(InfillCriterionParameterName, "Decision what value should decide the next sample", criteria, criteria.First())); 208 var intialSamplingPlans = new ItemSet<IInitialSampling> { new UniformRandomSampling(), new LatinHyperCubeDesignCreator() }; 209 Parameters.Add(new ConstrainedValueParameter<IInitialSampling>(InitialSamplingPlanParamterName, "Determies the initial samples from which the first model can be built.", intialSamplingPlans, intialSamplingPlans.First())); 225 210 SetInfillProblem(); 226 211 RegisterEventhandlers(); 227 212 } 228 213 #endregion 229 214 public void SetInitialSamples(RealVector[] individuals, double[] qualities) { 215 InitialSamples = individuals.Zip(qualities, (individual, d) => new Tuple<RealVector, double>(individual, d)).ToList(); 216 } 230 217 protected override void Initialize(CancellationToken cancellationToken) { 231 218 base.Initialize(cancellationToken); … … 235 222 var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem; 236 223 if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm has no InfillProblem. Troubles with Eventhandling?"); 237 infillProblem.Problem = Problem;238 239 224 240 225 //random … … 259 244 260 245 } 261 262 246 protected override void Run(CancellationToken cancellationToken) { 263 247 //initial samples … … 294 278 } 295 279 296 public void SetInitialSamples(RealVector[] individuals, double[] qualities) {297 InitialSamples = individuals.Zip(qualities, (individual, d) => new Tuple<RealVector, double>(individual, d)).ToList();298 }299 300 280 #region Eventhandling 301 281 private void RegisterEventhandlers() { … … 318 298 private void OnInfillOptimizationAlgorithmChanged(object sender, EventArgs args) { 319 299 SetInfillProblem(); 320 InfillOptimizationAlgorithm.ProblemChanged -= InfillOptimizationProblemChanged;321 300 InfillOptimizationAlgorithm.ProblemChanged += InfillOptimizationProblemChanged; 322 301 } … … 334 313 RegressionAlgorithm.Problem = new RegressionProblem(); 335 314 } 336 private void OnInitialSamplesChanged(object sender, EventArgs args) { 337 IRegressionProblemData samplesData = null; 338 using (var importTypeDialog = new RegressionImportTypeDialog()) { 339 if (importTypeDialog.ShowDialog() != DialogResult.OK) return; 340 samplesData = new RegressionCSVInstanceProvider().ImportData(importTypeDialog.Path, importTypeDialog.ImportType, importTypeDialog.CSVFormat); 341 InitialSamplesParameter.ToStringChanged -= OnInitialSamplesChanged; 342 InitialSamplesParameter.Value.Value = importTypeDialog.Path; 343 InitialSamplesParameter.ToStringChanged -= OnInitialSamplesChanged; 344 345 } 346 347 348 349 var solutions = new RealVector[samplesData.Dataset.Rows]; 350 var qualities = new double[samplesData.Dataset.Rows]; 351 var inputVariables = samplesData.InputVariables.CheckedItems.ToArray(); 352 for (var i = 0; i < solutions.Length; i++) { 353 qualities[i] = samplesData.Dataset.GetDoubleValue(samplesData.TargetVariable, i); 354 solutions[i] = new RealVector(inputVariables.Length); 355 for (var j = 0; j < inputVariables.Length; j++) solutions[i][j] = samplesData.Dataset.GetDoubleValue(inputVariables[j].Value.Value, i); 356 } 357 358 SetInitialSamples(solutions, qualities); 359 360 } 361 315 private void OnInitialSamplesChanged(object sender, EventArgs args) { } 362 316 protected override void OnExecutionTimeChanged() { 363 317 base.OnExecutionTimeChanged(); … … 376 330 base.Stop(); 377 331 } 378 protected override void OnProblemChanged() {379 base.OnProblemChanged();380 var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem;381 if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm has no InfillProblem. Troubles with Eventhandling?");382 infillProblem.Problem = Problem;383 }384 332 #endregion 385 333 386 334 #region helpers 387 private void SetInfillProblem() {388 var infillProblem = new InfillProblem {389 InfillCriterion = InfillCriterion,390 Problem = Problem391 };392 InfillOptimizationAlgorithm.Problem = infillProblem;393 }394 335 private IRegressionSolution BuildModel(CancellationToken cancellationToken) { 395 336 var dataset = EgoUtilities.GetDataSet(DataSamples.ToList(), RemoveDuplicates); … … 406 347 IRegressionSolution solution = null; 407 348 408 while (solution == null && i++ < 100) { //TODO: Question: Why does GP degenerate to NaN so often? Answer: There is not even the slightest mitigation strategy for "almost duplicates" that ill-condition the covariance matrix.349 while (solution == null && i++ < 100) { 409 350 var results = EgoUtilities.SyncRunSubAlgorithm(RegressionAlgorithm, Random.Next(int.MaxValue)); 410 351 solution = results.Select(x => x.Value).OfType<IRegressionSolution>().SingleOrDefault(); … … 451 392 //parameterize and check InfillProblem 452 393 var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem; 453 if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm does not have InfillProblem. Problem with Eventhandling?"); 454 if (infillProblem.InfillCriterion != InfillCriterion) throw new ArgumentException("InfillCiriterion for Problem is not correct. Problem with Eventhandling?"); 455 if (infillProblem.Problem != Problem) throw new ArgumentException("Expensive real problem is not correctly set in InfillProblem. Problem with Eventhandling?"); 456 InfillCriterion.Initialize(ResultsModel, Problem.Maximization, infillProblem.Encoding); 394 if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm does not have an InfillProblem."); 395 if (infillProblem.InfillCriterion != InfillCriterion) throw new ArgumentException("InfillCiriterion for Problem is not correctly set."); 396 var enc = Problem.Encoding as RealVectorEncoding; 397 infillProblem.Encoding.Bounds = enc.Bounds; 398 infillProblem.Encoding.Length = enc.Length; 399 infillProblem.Initialize(ResultsModel, Problem.Maximization); 400 401 457 402 458 403 RealVector bestVector = null; 459 404 var bestValue = infillProblem.Maximization ? double.NegativeInfinity : double.PositiveInfinity; 460 461 405 for (var i = 0; i < InfillOptimizationRestarts; i++) { 462 406 //optimize … … 464 408 cancellationToken.ThrowIfCancellationRequested(); 465 409 //extract results 466 if (!res.ContainsKey( BestInfillSolutionResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best solution");467 var v = res[ BestInfillSolutionResultName].Value as RealVector;468 if (!res.ContainsKey( BestInfillQualityResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best quality");469 var d = res[ BestInfillQualityResultName].Value as DoubleValue;410 if (!res.ContainsKey(InfillProblem.BestInfillSolutionResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best solution"); 411 var v = res[InfillProblem.BestInfillSolutionResultName].Value as RealVector; 412 if (!res.ContainsKey(InfillProblem.BestInfillQualityResultName)) throw new ArgumentException("The InfillOptimizationAlgorithm did not return a best quality"); 413 var d = res[InfillProblem.BestInfillQualityResultName].Value as DoubleValue; 470 414 if (d == null || v == null) throw new ArgumentException("The InfillOptimizationAlgorithm did not return the expected result types"); 471 472 415 //check for improvement 473 416 if (infillProblem.Maximization != d.Value > bestValue) continue; … … 475 418 bestVector = v; 476 419 } 477 478 420 InfillOptimizationAlgorithm.Runs.Clear(); 479 421 return bestVector; 480 422 } 481 private Tuple<RealVector, double> Evaluate(RealVector point) { 482 return new Tuple<RealVector, double>(point, Problem.Evaluate(GetIndividual(point), Random)); 483 } 423 484 424 private void Analyze() { 485 425 ResultsEvaluations = Samples.Count; … … 493 433 ResultsQualitiesWorst.Values.Add(Samples[Problem.Maximization ? min : max].Item2); 494 434 Problem.Analyze(Samples.Select(x => GetIndividual(x.Item1)).ToArray(), Samples.Select(x => x.Item2).ToArray(), Results, Random); 495 496 if (Samples.Count != 0 && Samples[0].Item1.Length == 2) { 497 var plotname = "DEBUG:Sample Distribution"; 498 var rowInit = "Initial Samples"; 499 var rowAll = "All Samples"; 500 if (!Results.ContainsKey(plotname)) Results.Add(new Result(plotname, new ScatterPlot())); 501 var plot = Results[plotname].Value as ScatterPlot; 502 if (!plot.Rows.ContainsKey(rowInit) && InitialSamples != null && InitialSamples.Count > 0) 503 plot.Rows.Add(new ScatterPlotDataRow(rowInit, "samples from inital file (already evaulated)", InitialSamples.Select(x => new Point2D<double>(x.Item1[0], x.Item1[1])))); 504 if (!plot.Rows.ContainsKey(rowAll)) plot.Rows.Add(new ScatterPlotDataRow(rowAll, "All samples", new Point2D<double>[0])); 505 else { plot.Rows[rowAll].Points.Clear(); } 506 plot.Rows[rowAll].Points.AddRange(Samples.Select(x => new Point2D<double>(x.Item1[0], x.Item1[1]))); 507 508 509 } 510 } 435 if (Samples.Count != 0 && Samples[0].Item1.Length == 2) AnalyzeSampleDistribution(); 436 AnalyzePredictionCorrelation(); 437 } 438 439 private void AnalyzeSampleDistribution() { 440 const string plotname = "DEBUG:Sample Distribution"; 441 const string rowInit = "Initial Samples"; 442 const string rowAll = "All Samples"; 443 if (!Results.ContainsKey(plotname)) Results.Add(new Result(plotname, new ScatterPlot())); 444 var plot = (ScatterPlot)Results[plotname].Value; 445 if (!plot.Rows.ContainsKey(rowInit) && InitialSamples != null && InitialSamples.Count > 0) 446 plot.Rows.Add(new ScatterPlotDataRow(rowInit, "samples from inital file (already evaulated)", InitialSamples.Select(x => new Point2D<double>(x.Item1[0], x.Item1[1])))); 447 if (!plot.Rows.ContainsKey(rowAll)) plot.Rows.Add(new ScatterPlotDataRow(rowAll, "All samples", new Point2D<double>[0])); 448 else { plot.Rows[rowAll].Points.Clear(); } 449 plot.Rows[rowAll].Points.AddRange(Samples.Select(x => new Point2D<double>(x.Item1[0], x.Item1[1]))); 450 } 451 452 private void AnalyzePredictionCorrelation() { 453 const string plotName = "Prediction"; 454 const string rowName = "Samples"; 455 const string lastrowName = "Last Sample"; 456 if (!Results.ContainsKey(plotName)) Results.Add(new Result(plotName, new ScatterPlot())); 457 var plot = (ScatterPlot)Results[plotName].Value; 458 if (!plot.Rows.ContainsKey(rowName)) plot.Rows.Add(new ScatterPlotDataRow(rowName, rowName, new List<Point2D<double>>())); 459 if (!plot.Rows.ContainsKey(lastrowName)) plot.Rows.Add(new ScatterPlotDataRow(lastrowName, lastrowName, new List<Point2D<double>>())); 460 var p = Samples[Samples.Count - 1]; 461 if (ResultsModel != null) plot.Rows[rowName].Points.Add(new Point2D<double>(ResultsModel.Model.GetEstimation(p.Item1), p.Item2, p.Item1)); 462 plot.VisualProperties.YAxisTitle = "True Objective Value"; 463 plot.VisualProperties.XAxisTitle = "Predicted Objective Value"; 464 465 } 466 511 467 private Individual GetIndividual(RealVector r) { 512 468 var scope = new Scope(); … … 514 470 return new SingleEncodingIndividual(Problem.Encoding, scope); 515 471 } 472 private Tuple<RealVector, double> Evaluate(RealVector point) { 473 return new Tuple<RealVector, double>(point, Problem.Evaluate(GetIndividual(point), Random)); 474 } 475 476 private void SetInfillProblem() { 477 InfillOptimizationAlgorithm.Problem = new InfillProblem { InfillCriterion = InfillCriterion }; 478 } 516 479 #endregion 517 480 }
Note: See TracChangeset
for help on using the changeset viewer.