Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
02/08/22 13:06:49 (2 years ago)
Author:
dpiringe
Message:

#3138

  • reimplemented extended constraints with an interface and an implementation, because of project reference troubles
  • moved the extended shape constraints into IShapeConstrainedRegressionProblemData
  • added thresholds for shape constraints -> the error is linear between 0 and 1, error caps at 1 when error >= (intervalbound + thresholdbound)
    • adapted ShapeConstraint and ShapeConstraintsParser to identify and store thresholds
  • adapted IntervalUtil to work with thresholds
  • adapted NMSESingleObjectiveConstraintsEvaluator and ShapeConstraintsAnalyzer to work with extended constraints
  • added a new chart in ShapeConstraintsAnalyzer to show the average constraint violation
Location:
branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.csproj

    r18181 r18213  
    263263      <Private>False</Private>
    264264    </ProjectReference>
     265    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
     266      <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project>
     267      <Name>HeuristicLab.Random-3.3</Name>
     268    </ProjectReference>
    265269  </ItemGroup>
    266270  <ItemGroup>
  • branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ShapeConstraintsAnalyzer.cs

    r17958 r18213  
    2020#endregion
    2121
     22using System.Collections;
     23using System.Collections.Generic;
    2224using System.Linq;
    2325using HEAL.Attic;
     
    2830using HeuristicLab.Optimization;
    2931using HeuristicLab.Parameters;
     32using HeuristicLab.Random;
    3033
    3134namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
     
    3639    private const string ConstraintViolationsParameterName = "ConstraintViolations";
    3740    private const string InfeasibleSolutionsParameterName = "InfeasibleSolutions";
     41    private const string AverageConstraintViolationsParameterName = "AverageConstraintViolations";
     42    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
    3843
    3944    #region parameter properties
     
    4853      (IResultParameter<DataTable>)Parameters[InfeasibleSolutionsParameterName];
    4954
     55    public IResultParameter<DataTable> AverageConstraintViolationsParameter =>
     56      (IResultParameter<DataTable>)Parameters[AverageConstraintViolationsParameterName];
     57
     58    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter =>
     59      (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName];
     60   
    5061    #endregion
    5162
    52     #region properties
     63      #region properties
    5364    public IRegressionProblemData RegressionProblemData => RegressionProblemDataParameter.ActualValue;
    5465    public DataTable ConstraintViolations => ConstraintViolationsParameter.ActualValue;
    5566    public DataTable InfeasibleSolutions => InfeasibleSolutionsParameter.ActualValue;
     67    public DataTable AverageConstraintViolations => AverageConstraintViolationsParameter.ActualValue;
    5668    #endregion
    5769
     
    7587      Parameters.Add(new ResultParameter<DataTable>(InfeasibleSolutionsParameterName,
    7688        "The number of infeasible solutions."));
     89      Parameters.Add(new ResultParameter<DataTable>(AverageConstraintViolationsParameterName,
     90        "The average violations of each constraint."));
     91      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName,
     92        "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
     93
    7794
    7895
     
    90107        }
    91108      };
     109
     110      AverageConstraintViolationsParameter.DefaultValue = new DataTable(SymbolicDataAnalysisTreeInterpreterParameterName) {
     111        VisualProperties = {
     112          XAxisTitle = "Generations",
     113          YAxisTitle = "Average Constraint Violations"
     114        }
     115      };
    92116    }
    93117
    94118
    95119    [StorableHook(HookType.AfterDeserialization)]
    96     private void AfterDeserialization() { }
     120    private void AfterDeserialization() {
     121      if (!Parameters.ContainsKey(SymbolicDataAnalysisTreeInterpreterParameterName))
     122        Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName,
     123          "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
     124    }
    97125
    98126    public override IOperation Apply() {
    99127      var problemData = (IShapeConstrainedRegressionProblemData)RegressionProblemData;
    100128      var trees = SymbolicExpressionTree.ToArray();
    101 
     129     
    102130      var results = ResultCollection;
    103       var constraints = problemData.ShapeConstraints.EnabledConstraints;
     131      var modelConstraints = problemData.ShapeConstraints.EnabledConstraints;
     132      var extendedConstraints = problemData.CheckedExtendedConstraints;
    104133      var variableRanges = problemData.VariableRanges;
    105134      var constraintViolationsTable = ConstraintViolations;
     135      var averageConstraintViolations = AverageConstraintViolations;
     136      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
    106137      var estimator = new IntervalArithBoundsEstimator();
     138     
     139      if (!constraintViolationsTable.Rows.Any()) {
     140        foreach (var constraint in modelConstraints) {
     141          constraintViolationsTable.Rows.Add(new DataRow(constraint.ToString()));
     142          averageConstraintViolations.Rows.Add(new DataRow(constraint.ToString()));
     143        }
    107144
    108       if (!constraintViolationsTable.Rows.Any())
    109         foreach (var constraint in constraints)
    110           constraintViolationsTable.Rows.Add(new DataRow(constraint.ToString()));
     145        foreach (var extendedConstraint in extendedConstraints.SelectMany(x => x.ShapeConstraints.EnabledConstraints)) {
     146          constraintViolationsTable.Rows.Add(new DataRow(extendedConstraint.ToString()));
     147          averageConstraintViolations.Rows.Add(new DataRow(extendedConstraint.ToString()));
     148        }
     149      }
    111150
    112       foreach (var constraint in constraints) {
    113         var numViolations = trees.Count(tree => IntervalUtil.GetConstraintViolation(constraint, estimator, variableRanges, tree) > 0.0);
    114         constraintViolationsTable.Rows[constraint.ToString()].Values.Add(numViolations);
     151      var violationsPerTree = new Dictionary<ISymbolicExpressionTree, int>();
     152      var violationsPerConstraint = new Dictionary<string, IList<double>>();
     153
     154      foreach(var tree in trees) {
     155        var violations = NMSESingleObjectiveConstraintsEvaluator.CalculateShapeConstraintsViolations(problemData, tree, interpreter, estimator, new MersenneTwister());
     156        foreach(var violation in violations) {
     157          var constraint = violation.Item1;
     158          var error = violation.Item2;
     159          if (!violationsPerConstraint.ContainsKey(constraint.ToString()))
     160            violationsPerConstraint.Add(constraint.ToString(), new List<double>());
     161          violationsPerConstraint[constraint.ToString()].Add(error);
     162        }
     163        violationsPerTree.Add(tree, violations.Count(x => x.Item2 > 0));
     164      }
     165
     166      foreach (var constraint in modelConstraints) {
     167        var errors = violationsPerConstraint[constraint.ToString()];
     168        constraintViolationsTable.Rows[constraint.ToString()].Values.Add(errors.Count(x => x > 0));
     169        averageConstraintViolations.Rows[constraint.ToString()].Values.Add(errors.Sum() / errors.Count());
     170      }
     171
     172      foreach (var extendedConstraint in extendedConstraints.SelectMany(x => x.ShapeConstraints.EnabledConstraints)) {
     173        var errors = violationsPerConstraint[extendedConstraint.ToString()];
     174        constraintViolationsTable.Rows[extendedConstraint.ToString()].Values.Add(errors.Count(x => x > 0));
     175        averageConstraintViolations.Rows[extendedConstraint.ToString()].Values.Add(errors.Sum() / errors.Count());
    115176      }
    116177
     
    121182      infeasibleSolutionsDataTable.Rows[InfeasibleSolutionsParameterName]
    122183        .Values
    123         .Add(trees.Count(t => IntervalUtil.GetConstraintViolations(constraints, estimator, variableRanges, t).Any(x => x > 0.0)));
     184        .Add(trees.Count(t => violationsPerTree[t] > 0));
    124185
    125186      return base.Apply();
  • branches/3138_Shape_Constraints_Transformations/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs

    r18181 r18213  
    2121
    2222using System;
     23using System.Collections;
    2324using System.Collections.Generic;
    2425using System.Linq;
     
    2930using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    3031using HeuristicLab.Parameters;
     32using HeuristicLab.Random;
    3133
    3234namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
     
    4143    private const string BoundsEstimatorParameterName = "BoundsEstimator";
    4244    private const string PenaltyFactorParameterName = "PenaltyFactor";
    43     private const string ExtendedConstraintsParameterName = "ExtendedConstraints";
    4445
    4546
     
    5859      (IFixedValueParameter<DoubleValue>)Parameters[PenaltyFactorParameterName];
    5960
    60     public IFixedValueParameter<IItemList<ExtendedConstraint>> ExtendedConstraintsParameter =>
    61       (IFixedValueParameter<IItemList<ExtendedConstraint>>)Parameters[ExtendedConstraintsParameterName];
    6261
    6362
     
    8685      set => PenaltyFactorParameter.Value.Value = value;
    8786    }
    88 
    89     public IEnumerable<ExtendedConstraint> ExtendedConstraints {
    90       get => ExtendedConstraintsParameter.Value;
    91     }
    92      
    93 
    9487
    9588    public override bool Maximization => false; // NMSE is minimized
     
    116109      Parameters.Add(new FixedValueParameter<DoubleValue>(PenaltyFactorParameterName,
    117110        "Punishment factor for constraint violations for soft constraint handling (fitness = NMSE + penaltyFactor * avg(violations)) (default: 1.0)", new DoubleValue(1.0)));
    118       Parameters.Add(new FixedValueParameter<ItemList<ExtendedConstraint>>(ExtendedConstraintsParameterName, "", new ItemList<ExtendedConstraint>()));
    119111    }
    120112
     
    135127      var estimationLimits = EstimationLimitsParameter.ActualValue;
    136128      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
     129      var random = RandomParameter.ActualValue;
    137130
    138131      if (OptimizeParameters) {
     
    175168
    176169      var quality = Calculate(interpreter, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows,
    177         BoundsEstimator, UseSoftConstraints, PenalityFactor, ExtendedConstraints);
     170        BoundsEstimator, random, UseSoftConstraints, PenalityFactor);
    178171      QualityParameter.ActualValue = new DoubleValue(quality);
    179172
     
    186179      double lowerEstimationLimit, double upperEstimationLimit,
    187180      IRegressionProblemData problemData, IEnumerable<int> rows,
    188       IBoundsEstimator estimator,
    189       bool useSoftConstraints = false, double penaltyFactor = 1.0,
    190       IEnumerable<ExtendedConstraint> extendedConstraints = null) {
    191 
    192       var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
     181      IBoundsEstimator estimator, IRandom random,
     182      bool useSoftConstraints = false, double penaltyFactor = 1.0) {
     183
     184      var trainingEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
    193185      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
    194       var constraints = Enumerable.Empty<ShapeConstraint>();
     186
     187      var trainingBoundedEstimatedValues = trainingEstimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
     188      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, trainingBoundedEstimatedValues,
     189        out var errorState);
     190
     191      if (errorState != OnlineCalculatorError.None)
     192        return double.MaxValue;
     193
     194      var violations = Enumerable.Empty<double>();
    195195      if (problemData is ShapeConstrainedRegressionProblemData scProbData) {
    196         constraints = scProbData.ShapeConstraints.EnabledConstraints;
    197       }
    198       var intervalCollection = problemData.VariableRanges;
    199 
    200       var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
    201       var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues,
    202         out var errorState);
    203 
    204       if (errorState != OnlineCalculatorError.None) {
    205         return 1.0;
    206       }
    207 
    208       var constraintViolations = IntervalUtil.GetConstraintViolations(constraints, estimator, intervalCollection, tree);
    209 
    210       if (constraintViolations.Any(x => double.IsNaN(x) || double.IsInfinity(x))) {
    211         return 1.0;
    212       }
     196        violations = CalculateShapeConstraintsViolations(scProbData, tree, interpreter, estimator, random).Select(x => x.Item2);
     197      }
     198
     199      if (violations.Any(x => double.IsNaN(x) || double.IsInfinity(x)))
     200        return double.MaxValue;
    213201
    214202      if (useSoftConstraints) {
     
    216204          throw new ArgumentException("The parameter has to be >= 0.0.", nameof(penaltyFactor));
    217205
    218         var weightedViolationsAvg = constraints
    219           .Zip(constraintViolations, (c, v) => c.Weight * v)
    220           .Average();
    221 
    222         return Math.Min(nmse, 1.0) + penaltyFactor * weightedViolationsAvg;
    223       } else if (constraintViolations.Any(x => x > 0.0)) {
    224         return 1.0;
    225       }
    226 
    227       return nmse;
     206        return nmse + penaltyFactor * violations.Average();
     207      }
     208      return violations.Any(x => x > 0.0) ? 1.0 : nmse;
     209    }
     210
     211    public static IEnumerable<Tuple<ShapeConstraint, double>> CalculateShapeConstraintsViolations(
     212      IShapeConstrainedRegressionProblemData problemData, ISymbolicExpressionTree tree,
     213      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IBoundsEstimator estimator,
     214      IRandom random) {
     215      IList<Tuple<ShapeConstraint, double>> violations = new List<Tuple<ShapeConstraint, double>>();
     216     
     217      var baseConstraints = problemData.ShapeConstraints.EnabledConstraints;
     218      var intervalCollection = problemData.VariableRanges;
     219      var extendedShapeConstraints = problemData.CheckedExtendedConstraints;
     220      var allEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, problemData.AllIndices);
     221
     222      foreach (var constraint in baseConstraints)
     223        violations.Add(Tuple.Create(constraint, IntervalUtil.GetConstraintViolation(constraint, estimator, intervalCollection, tree) * constraint.Weight));
     224
     225      IDictionary<string, IList> dict = new Dictionary<string, IList>();
     226      foreach (var varName in problemData.Dataset.VariableNames) {
     227        if (varName != problemData.TargetVariable)
     228          dict.Add(varName, problemData.Dataset.GetDoubleValues(varName).ToList());
     229        else dict.Add(varName, allEstimatedValues.ToList());
     230      }
     231      var tmpDataset = new Dataset(dict.Keys, dict.Values);
     232
     233      foreach (var extendedConstraint in extendedShapeConstraints) {
     234        var enabledConstraints = extendedConstraint.ShapeConstraints.EnabledConstraints;
     235        if (enabledConstraints.Any()) {
     236          var extendedConstraintExprValues = interpreter.GetSymbolicExpressionTreeValues(extendedConstraint.Tree, tmpDataset, problemData.AllIndices);
     237          var extendedConstraintExprInterval = new Interval(extendedConstraintExprValues.Min(), extendedConstraintExprValues.Max());
     238
     239          foreach (var constraint in enabledConstraints) {
     240            if (constraint.Regions.Count > 0) {
     241              // adapt dataset
     242              foreach (var kvp in constraint.Regions.GetReadonlyDictionary()) {
     243                var lb = double.IsNegativeInfinity(kvp.Value.LowerBound) ? double.MinValue : kvp.Value.LowerBound;
     244                var ub = double.IsPositiveInfinity(kvp.Value.UpperBound) ? double.MaxValue : kvp.Value.UpperBound;
     245
     246                var vals = Enumerable.Range(0, dict[kvp.Key].Count - 2)
     247                                     .Select(x => UniformDistributedRandom.NextDouble(random, lb, ub))
     248                                     .ToList();
     249                vals.Add(lb);
     250                vals.Add(ub);
     251                vals.Sort();
     252                dict[kvp.Key] = vals;
     253              }
     254              // calc again with new regions
     255              tmpDataset = new Dataset(dict.Keys, dict.Values);
     256              // calc target again
     257              allEstimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, tmpDataset, problemData.AllIndices);
     258              dict[problemData.TargetVariable] = allEstimatedValues.ToList();
     259              tmpDataset = new Dataset(dict.Keys, dict.Values);
     260              extendedConstraintExprValues = interpreter.GetSymbolicExpressionTreeValues(extendedConstraint.Tree, tmpDataset, problemData.AllIndices);
     261              extendedConstraintExprInterval = new Interval(extendedConstraintExprValues.Min(), extendedConstraintExprValues.Max());
     262            }
     263            violations.Add(Tuple.Create(constraint, IntervalUtil.GetIntervalError(constraint.Interval, extendedConstraintExprInterval, constraint.Threshold) * constraint.Weight));
     264          }
     265        }
     266      }
     267      return violations;
    228268    }
    229269
     
    234274      EstimationLimitsParameter.ExecutionContext = context;
    235275      ApplyLinearScalingParameter.ExecutionContext = context;
     276      RandomParameter.ExecutionContext = context;
    236277
    237278      var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
    238279        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
    239         problemData, rows, BoundsEstimator, UseSoftConstraints, PenalityFactor, ExtendedConstraints);
     280        problemData, rows, BoundsEstimator, RandomParameter.Value, UseSoftConstraints, PenalityFactor);
    240281
    241282      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
    242283      EstimationLimitsParameter.ExecutionContext = null;
    243284      ApplyLinearScalingParameter.ExecutionContext = null;
     285      RandomParameter.ExecutionContext = null;
    244286
    245287      return nmse;
Note: See TracChangeset for help on using the changeset viewer.