Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/26/17 09:10:56 (7 years ago)
Author:
bwerth
Message:

#2745 implemented EGO as EngineAlgorithm + some simplifications in the IInfillCriterion interface

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/EfficientGlobalOptimization/HeuristicLab.Algorithms.EGO/EfficientGlobalOptimizationAlgorithm.cs

    r14833 r15064  
    2424using System.Linq;
    2525using System.Threading;
    26 using System.Windows.Forms;
    2726using HeuristicLab.Algorithms.DataAnalysis;
    2827using HeuristicLab.Analysis;
     
    3534using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    3635using HeuristicLab.Problems.DataAnalysis;
    37 using HeuristicLab.Problems.Instances.DataAnalysis;
    38 using HeuristicLab.Problems.Instances.DataAnalysis.Views;
     36using HeuristicLab.Problems.Instances;
    3937using HeuristicLab.Random;
    4038
     
    4240  [StorableClass]
    4341  [Creatable(CreatableAttribute.Categories.Algorithms, Priority = 95)]
    44   [Item("EfficientGlobalOptimizationAlgortihm", "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.")]
    4543  public class EfficientGlobalOptimizationAlgorithm : BasicAlgorithm, ISurrogateAlgorithm<RealVector> {
    4644    #region Basic-Alg-Essentials
     
    8482    #endregion
    8583
    86     #region TransmissionResultNames
    87     public const string BestInfillSolutionResultName = "BestInfillSolution";
    88     public const string BestInfillQualityResultName = "BestInfillQuality";
    89     #endregion
    90 
    9184    #region ParameterProperties
    9285    public IFixedValueParameter<IntValue> GenerationSizeParemeter => Parameters[GenerationSizeParameterName] as IFixedValueParameter<IntValue>;
     
    108101
    109102    #region Properties
    110 
    111103    public int GenerationSize => GenerationSizeParemeter.Value.Value;
    112104    public IInfillCriterion InfillCriterion => InfillCriterionParameter.Value;
     
    123115      ? Samples.Skip(Samples.Count - MaximalDatasetSize)
    124116      : Samples;
    125 
    126117    private bool RemoveDuplicates => RemoveDuplicatesParameter.Value.Value;
    127118    private RealVector BaselineVector => BaselineVectorParameter.Value;
     
    161152    private DataTable ResultsQualities => (DataTable)Results[QualitiesChartResultName].Value;
    162153    private DataRow ResultsQualitiesBest => ResultsQualities.Rows[BestQualitiesRowResultName];
    163 
    164154    private DataRow ResultsQualitiesWorst => ResultsQualities.Rows[WorstQualitiesRowResultName];
    165 
    166155    private DataRow ResultsQualitiesIteration => ResultsQualities.Rows[CurrentQualitiesRowResultName];
    167 
    168156    private IRegressionSolution ResultsModel
    169157    {
     
    177165    protected EfficientGlobalOptimizationAlgorithm(bool deserializing) : base(deserializing) { }
    178166    [StorableHook(HookType.AfterDeserialization)]
    179     private void AfterDeseialization() {
     167    protected void AfterDeseialization() {
    180168      RegisterEventhandlers();
    181169    }
    182     protected EfficientGlobalOptimizationAlgorithm(EfficientGlobalOptimizationAlgorithm original, Cloner cloner)
    183       : base(original, cloner) {
     170    protected EfficientGlobalOptimizationAlgorithm(EfficientGlobalOptimizationAlgorithm original, Cloner cloner) : base(original, cloner) {
    184171      Random = cloner.Clone(Random);
    185172      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();
    187174      RegisterEventhandlers();
    188175    }
    189176    public override IDeepCloneable Clone(Cloner cloner) { return new EfficientGlobalOptimizationAlgorithm(this, cloner); }
    190177    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
    191183      var cmaes = new CMAEvolutionStrategy.CMAEvolutionStrategy {
    192184        MaximumGenerations = 300,
     
    206198      Parameters.Add(new FixedValueParameter<IntValue>(InfillOptimizationRestartsParameterName, "Number of restarts of the SubAlgortihm to avoid local optima", new IntValue(1)));
    207199      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());
    218200      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)));
    219201      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"));
    220202      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()));
    221203      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()));
    225210      SetInfillProblem();
    226211      RegisterEventhandlers();
    227212    }
    228213    #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    }
    230217    protected override void Initialize(CancellationToken cancellationToken) {
    231218      base.Initialize(cancellationToken);
     
    235222      var infillProblem = InfillOptimizationAlgorithm.Problem as InfillProblem;
    236223      if (infillProblem == null) throw new ArgumentException("InfillOptimizationAlgorithm has no InfillProblem. Troubles with Eventhandling?");
    237       infillProblem.Problem = Problem;
    238 
    239224
    240225      //random
     
    259244
    260245    }
    261 
    262246    protected override void Run(CancellationToken cancellationToken) {
    263247      //initial samples
     
    294278    }
    295279
    296     public void SetInitialSamples(RealVector[] individuals, double[] qualities) {
    297       InitialSamples = individuals.Zip(qualities, (individual, d) => new Tuple<RealVector, double>(individual, d)).ToList();
    298     }
    299 
    300280    #region Eventhandling
    301281    private void RegisterEventhandlers() {
     
    318298    private void OnInfillOptimizationAlgorithmChanged(object sender, EventArgs args) {
    319299      SetInfillProblem();
    320       InfillOptimizationAlgorithm.ProblemChanged -= InfillOptimizationProblemChanged;
    321300      InfillOptimizationAlgorithm.ProblemChanged += InfillOptimizationProblemChanged;
    322301    }
     
    334313      RegressionAlgorithm.Problem = new RegressionProblem();
    335314    }
    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) { }
    362316    protected override void OnExecutionTimeChanged() {
    363317      base.OnExecutionTimeChanged();
     
    376330      base.Stop();
    377331    }
    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     }
    384332    #endregion
    385333
    386334    #region helpers
    387     private void SetInfillProblem() {
    388       var infillProblem = new InfillProblem {
    389         InfillCriterion = InfillCriterion,
    390         Problem = Problem
    391       };
    392       InfillOptimizationAlgorithm.Problem = infillProblem;
    393     }
    394335    private IRegressionSolution BuildModel(CancellationToken cancellationToken) {
    395336      var dataset = EgoUtilities.GetDataSet(DataSamples.ToList(), RemoveDuplicates);
     
    406347      IRegressionSolution solution = null;
    407348
    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) {
    409350        var results = EgoUtilities.SyncRunSubAlgorithm(RegressionAlgorithm, Random.Next(int.MaxValue));
    410351        solution = results.Select(x => x.Value).OfType<IRegressionSolution>().SingleOrDefault();
     
    451392      //parameterize and check InfillProblem
    452393      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
    457402
    458403      RealVector bestVector = null;
    459404      var bestValue = infillProblem.Maximization ? double.NegativeInfinity : double.PositiveInfinity;
    460 
    461405      for (var i = 0; i < InfillOptimizationRestarts; i++) {
    462406        //optimize
     
    464408        cancellationToken.ThrowIfCancellationRequested();
    465409        //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;
    470414        if (d == null || v == null) throw new ArgumentException("The InfillOptimizationAlgorithm did not return the expected result types");
    471 
    472415        //check for improvement
    473416        if (infillProblem.Maximization != d.Value > bestValue) continue;
     
    475418        bestVector = v;
    476419      }
    477 
    478420      InfillOptimizationAlgorithm.Runs.Clear();
    479421      return bestVector;
    480422    }
    481     private Tuple<RealVector, double> Evaluate(RealVector point) {
    482       return new Tuple<RealVector, double>(point, Problem.Evaluate(GetIndividual(point), Random));
    483     }
     423
    484424    private void Analyze() {
    485425      ResultsEvaluations = Samples.Count;
     
    493433      ResultsQualitiesWorst.Values.Add(Samples[Problem.Maximization ? min : max].Item2);
    494434      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
    511467    private Individual GetIndividual(RealVector r) {
    512468      var scope = new Scope();
     
    514470      return new SingleEncodingIndividual(Problem.Encoding, scope);
    515471    }
     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    }
    516479    #endregion
    517480  }
Note: See TracChangeset for help on using the changeset viewer.