Changeset 5736


Ignore:
Timestamp:
03/17/11 15:14:45 (11 years ago)
Author:
gkronber
Message:

#1418 implemented linear scaling for classification solutions, fixed bugs interactive simplifier view for classification solutions.

Location:
branches/DataAnalysis Refactoring
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • branches/DataAnalysis Refactoring/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs

    r5733 r5736  
    119119      IClassificationProblemData problemData,
    120120      IEnumerable<int> rows) {
    121       string targetVariable = problemData.TargetVariable;
    122       var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
    123       var targetClassValues = problemData.Dataset.GetEnumeratedVariableValues(targetVariable, rows);
    124 
    125       double[] classValues;
    126       double[] thresholds;
    127       NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(problemData, estimatedValues, targetClassValues, out classValues, out thresholds);
    128       return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
     121      return new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
    129122    }
    130123  }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs

    r5717 r5736  
    4848      ISymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
    4949      ISymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
    50       root.AddSubTree(start);
     50      root.AddSubtree(start);
    5151      tempTree = new SymbolicExpressionTree(root);
    5252    }
    5353
    5454    protected override void UpdateModel(ISymbolicExpressionTree tree) {
    55       var dataset = Content.ProblemData.Dataset;
    56       var interpreter = Content.Model.Interpreter;
    57       var rows = Content.ProblemData.TrainingIndizes;
    58       string targetVariable = Content.ProblemData.TargetVariable;
    59 
    60       var targetClassValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
    61       var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
    62         .ToArray();
    63       double[] classValues;
    64       double[] thresholds;
    65       NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, originalOutput, targetClassValues, out classValues, out thresholds);
    66       Content.Model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, classValues, thresholds);
     55      Content.Model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter);
     56      Content.SetClassDistibutionCutPointThresholds();
    6757    }
    6858
     
    8373      string targetVariable = Content.ProblemData.TargetVariable;
    8474      Dictionary<ISymbolicExpressionTreeNode, double> impactValues = new Dictionary<ISymbolicExpressionTreeNode, double>();
    85       List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubTree(0).GetSubTree(0).IterateNodesPostfix().ToList();
     75      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPostfix().ToList();
    8676
    8777      var targetClassValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
    8878      var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
     79        .LimitToRange(Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit)
    8980        .ToArray();
    9081      double[] classValues;
    9182      double[] thresholds;
    9283      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, originalOutput, targetClassValues, out classValues, out thresholds);
    93       var classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
     84      var classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
     85      classifier.SetThresholdsAndClassValues(thresholds, classValues);
    9486      double originalAccuracy = OnlineAccuracyEvaluator.Calculate(targetClassValues, classifier.GetEstimatedClassValues(dataset, rows));
    9587
     
    9991        ISymbolicExpressionTreeNode replacementNode = constantNode;
    10092        SwitchNode(parent, node, replacementNode);
    101         var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows);
     93        var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
     94          .LimitToRange(Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit)
     95          .ToArray();
    10296        NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(Content.ProblemData, newOutput, targetClassValues, out classValues, out thresholds);
    103         classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, classValues, thresholds);
     97        classifier = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
     98        classifier.SetThresholdsAndClassValues(thresholds, classValues);
    10499        double newAccuracy = OnlineAccuracyEvaluator.Calculate(targetClassValues, classifier.GetEstimatedClassValues(dataset, rows));
    105100
     
    114109
    115110    private double CalculateReplacementValue(ISymbolicExpressionTreeNode node) {
    116       var start = tempTree.Root.GetSubTree(0);
    117       while (start.SubTrees.Count() > 0) start.RemoveSubTree(0);
    118       start.AddSubTree((ISymbolicExpressionTreeNode)node.Clone());
     111      var start = tempTree.Root.GetSubtree(0);
     112      while (start.SubtreesCount > 0) start.RemoveSubtree(0);
     113      start.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
    119114      var interpreter = Content.Model.Interpreter;
    120115      var rows = Content.ProblemData.TrainingIndizes;
     
    124119
    125120    private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) {
    126       for (int i = 0; i < root.SubTrees.Count(); i++) {
    127         if (root.GetSubTree(i) == oldBranch) {
    128           root.RemoveSubTree(i);
    129           root.InsertSubTree(i, newBranch);
     121      for (int i = 0; i < root.SubtreesCount; i++) {
     122        if (root.GetSubtree(i) == oldBranch) {
     123          root.RemoveSubtree(i);
     124          root.InsertSubtree(i, newBranch);
    130125          return;
    131126        }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs

    r5717 r5736  
    2323namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
    2424  public interface ISymbolicDiscriminantFunctionClassificationModel : IDiscriminantFunctionClassificationModel, ISymbolicClassificationModel {
     25    double LowerEstimationLimit { get; }
     26    double UpperEstimationLimit { get; }
    2527  }
    2628}
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs

    r5722 r5736  
    9595    }
    9696
    97 
    9897    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
    99       double[] classValues;
    100       double[] thresholds;
    101       var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
    102         .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    103       var targetValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
    104       AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetValues, out classValues, out thresholds);
    105       var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    106       return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     98      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
     99      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     100      if (ApplyLinearScaling.Value) {
     101        solution.ScaleModel();
     102      }
     103      return solution;
    107104    }
    108105  }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs

    r5722 r5736  
    8181
    8282    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQualities) {
    83       double[] classValues;
    84       double[] thresholds;
    85       // calculate thresholds on the whole training set even for the validation best solution
    86       var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
    87         .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    88       var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
    89       AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetClassValues, out classValues, out thresholds);
    90       var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    91       return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     83      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
     84      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     85      if (ApplyLinearScaling.Value) {
     86        solution.ScaleModel();
     87      }
     88      return solution;
    9289    }
    9390  }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs

    r5722 r5736  
    9696
    9797    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    98       double[] classValues;
    99       double[] thresholds;
    100       var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
    101         .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    102       var targetValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
    103       AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetValues, out classValues, out thresholds);
    104       var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    105       return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     98      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
     99      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     100      if (ApplyLinearScaling.Value) {
     101        solution.ScaleModel();
     102      }
     103      return solution;
    106104    }
    107105  }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs

    r5722 r5736  
    8282
    8383    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    84       double[] classValues;
    85       double[] thresholds;
    86       // calculate thresholds on the whole training set even for the validation best solution
    87       var estimatedValues = SymbolicDataAnalysisTreeInterpreter.GetSymbolicExpressionTreeValues(bestTree, ProblemData.Dataset, ProblemData.TrainingIndizes)
    88         .LimitToRange(LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    89       var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
    90       AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, estimatedValues, targetClassValues, out classValues, out thresholds);
    91       var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, classValues, thresholds, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
    92       return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     84      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreter, LowerEstimationLimit.Value, UpperEstimationLimit.Value);
     85      var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemData);
     86      if (ApplyLinearScaling.Value) {
     87        solution.ScaleModel();
     88      }
     89      return solution;
    9390    }
    9491  }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolution.cs

    r5717 r5736  
    3939  [Item(Name = "SymbolicClassificationSolution", Description = "Represents a symbolic classification solution (model + data) and attributes of the solution like accuracy and complexity.")]
    4040  public sealed class SymbolicClassificationSolution : ClassificationSolution, ISymbolicClassificationSolution {
    41     #region ISymbolicClassificationSolution Members
     41    private const string ModelLengthResultName = "ModelLength";
     42    private const string ModelDepthResultName = "ModelDepth";
    4243
    4344    public new ISymbolicClassificationModel Model {
     
    4950      get { return (ISymbolicDataAnalysisModel)base.Model; }
    5051    }
     52    public int ModelLength {
     53      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
     54      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
     55    }
    5156
    52     #endregion
     57    public int ModelDepth {
     58      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
     59      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
     60    }
     61
    5362    [StorableConstructor]
    5463    private SymbolicClassificationSolution(bool deserializing) : base(deserializing) { }
     
    5867    public SymbolicClassificationSolution(ISymbolicClassificationModel model, IClassificationProblemData problemData)
    5968      : base(model, problemData) {
     69      Add(new Result(ModelLengthResultName, "Length of the symbolic classification model.", new IntValue()));
     70      Add(new Result(ModelDepthResultName, "Depth of the symbolic classification model.", new IntValue()));
     71      RecalculateResults();
    6072    }
    6173
     
    6375      return new SymbolicClassificationSolution(this, cloner);
    6476    }
     77
     78    protected override void OnModelChanged(EventArgs e) {
     79      base.OnModelChanged(e);
     80      RecalculateResults();
     81    }
     82
     83    private new void RecalculateResults() {
     84      ModelLength = Model.SymbolicExpressionTree.Length;
     85      ModelDepth = Model.SymbolicExpressionTree.Depth;
     86    }
    6587  }
    6688}
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs

    r5720 r5736  
    4444    public IEnumerable<double> Thresholds {
    4545      get { return (IEnumerable<double>)thresholds.Clone(); }
    46       set {
    47         thresholds = value.ToArray();
    48         OnThresholdsChanged(EventArgs.Empty);
    49       }
     46      private set { thresholds = value.ToArray(); }
    5047    }
    5148    [Storable]
     
    5350    public IEnumerable<double> ClassValues {
    5451      get { return (IEnumerable<double>)classValues.Clone(); }
    55       set { classValues = value.ToArray(); }
     52      private set { classValues = value.ToArray(); }
    5653    }
    5754    [Storable]
     
    7269    }
    7370    public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
    74       IEnumerable<double> classValues, IEnumerable<double> thresholds,
    7571      double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
    7672      : base(tree, interpreter) {
    77       this.classValues = classValues.ToArray();
    78       this.thresholds = thresholds.ToArray();
     73      thresholds = new double[] { double.NegativeInfinity };
     74      classValues = new double[] { 0.0 };
    7975      this.lowerEstimationLimit = lowerEstimationLimit;
    8076      this.upperEstimationLimit = upperEstimationLimit;
     
    8581    }
    8682
     83    public void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues) {
     84      var classValuesArr = classValues.ToArray();
     85      var thresholdsArr = thresholds.ToArray();
     86      if (thresholdsArr.Length != classValuesArr.Length) throw new ArgumentException();
     87
     88      this.classValues = classValuesArr;
     89      this.thresholds = thresholdsArr;
     90      OnThresholdsChanged(EventArgs.Empty);
     91    }
     92
    8793    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
    88       return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows);
     94      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows)
     95        .LimitToRange(lowerEstimationLimit, upperEstimationLimit);
    8996    }
    9097
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationSolution.cs

    r5717 r5736  
    3939  [Item(Name = "SymbolicDiscriminantFunctionClassificationSolution", Description = "Represents a symbolic classification solution (model + data) and attributes of the solution like accuracy and complexity.")]
    4040  public sealed class SymbolicDiscriminantFunctionClassificationSolution : DiscriminantFunctionClassificationSolution, ISymbolicClassificationSolution {
     41    private const string ModelLengthResultName = "ModelLength";
     42    private const string ModelDepthResultName = "ModelDepth";
    4143
    4244    public new ISymbolicDiscriminantFunctionClassificationModel Model {
     
    5254      get { return Model; }
    5355    }
     56    public int ModelLength {
     57      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
     58      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
     59    }
    5460
     61    public int ModelDepth {
     62      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
     63      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
     64    }
    5565    [StorableConstructor]
    5666    private SymbolicDiscriminantFunctionClassificationSolution(bool deserializing) : base(deserializing) { }
     
    6070    public SymbolicDiscriminantFunctionClassificationSolution(ISymbolicDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
    6171      : base(model, problemData) {
     72      Add(new Result(ModelLengthResultName, "Length of the symbolic classification model.", new IntValue()));
     73      Add(new Result(ModelDepthResultName, "Depth of the symbolic classification model.", new IntValue()));
     74      RecalculateResults();
    6275    }
    6376
     
    6578      return new SymbolicDiscriminantFunctionClassificationSolution(this, cloner);
    6679    }
     80
     81    protected override void OnModelChanged(EventArgs e) {
     82      base.OnModelChanged(e);
     83      RecalculateResults();
     84    }
     85
     86    private new void RecalculateResults() {
     87      ModelLength = Model.SymbolicExpressionTree.Length;
     88      ModelDepth = Model.SymbolicExpressionTree.Depth;
     89    }
     90
     91    public void ScaleModel() {
     92      var dataset = ProblemData.Dataset;
     93      var targetVariable = ProblemData.TargetVariable;
     94      var rows = ProblemData.TrainingIndizes;
     95      var estimatedValues = GetEstimatedValues(rows);
     96      var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
     97      double alpha;
     98      double beta;
     99      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
     100
     101      ConstantTreeNode alphaTreeNode = null;
     102      ConstantTreeNode betaTreeNode = null;
     103      // check if model has been scaled previously by analyzing the structure of the tree
     104      var startNode = Model.SymbolicExpressionTree.Root.GetSubtree(0);
     105      if (startNode.GetSubtree(0).Symbol is Addition) {
     106        var addNode = startNode.GetSubtree(0);
     107        if (addNode.SubtreesCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
     108          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
     109          var mulNode = addNode.GetSubtree(0);
     110          if (mulNode.SubtreesCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
     111            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
     112          }
     113        }
     114      }
     115      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
     116      if (alphaTreeNode != null && betaTreeNode != null) {
     117        betaTreeNode.Value *= beta;
     118        alphaTreeNode.Value *= beta;
     119        alphaTreeNode.Value += alpha;
     120      } else {
     121        var mainBranch = startNode.GetSubtree(0);
     122        startNode.RemoveSubtree(0);
     123        var scaledMainBranch = MakeSum(MakeProduct(beta, mainBranch), alpha);
     124        startNode.AddSubtree(scaledMainBranch);
     125      }
     126
     127      OnModelChanged(EventArgs.Empty);
     128    }
     129
     130    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
     131      if (alpha.IsAlmost(0.0)) {
     132        return treeNode;
     133      } else {
     134        var node = (new Addition()).CreateTreeNode();
     135        var alphaConst = MakeConstant(alpha);
     136        node.AddSubtree(treeNode);
     137        node.AddSubtree(alphaConst);
     138        return node;
     139      }
     140    }
     141
     142    private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
     143      if (beta.IsAlmost(1.0)) {
     144        return treeNode;
     145      } else {
     146        var node = (new Multiplication()).CreateTreeNode();
     147        var betaConst = MakeConstant(beta);
     148        node.AddSubtree(treeNode);
     149        node.AddSubtree(betaConst);
     150        return node;
     151      }
     152    }
     153
     154    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
     155      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
     156      node.Value = c;
     157      return node;
     158    }
    67159  }
    68160}
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs

    r5729 r5736  
    4848      ISymbolicExpressionTreeNode root = new ProgramRootSymbol().CreateTreeNode();
    4949      ISymbolicExpressionTreeNode start = new StartSymbol().CreateTreeNode();
    50       root.AddSubTree(start);
     50      root.AddSubtree(start);
    5151      tempTree = new SymbolicExpressionTree(root);
    5252    }
     
    7373      string targetVariable = Content.ProblemData.TargetVariable;
    7474      Dictionary<ISymbolicExpressionTreeNode, double> impactValues = new Dictionary<ISymbolicExpressionTreeNode, double>();
    75       List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubTree(0).GetSubTree(0).IterateNodesPostfix().ToList();
     75      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPostfix().ToList();
    7676      var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
    7777        .ToArray();
     
    9898
    9999    private double CalculateReplacementValue(ISymbolicExpressionTreeNode node) {
    100       var start = tempTree.Root.GetSubTree(0);
    101       while (start.SubTrees.Count() > 0) start.RemoveSubTree(0);
    102       start.AddSubTree((ISymbolicExpressionTreeNode)node.Clone());
     100      var start = tempTree.Root.GetSubtree(0);
     101      while (start.SubtreesCount > 0) start.RemoveSubtree(0);
     102      start.AddSubtree((ISymbolicExpressionTreeNode)node.Clone());
    103103      var interpreter = Content.Model.Interpreter;
    104104      var rows = Content.ProblemData.TrainingIndizes;
     
    108108
    109109    private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) {
    110       for (int i = 0; i < root.SubTrees.Count(); i++) {
    111         if (root.GetSubTree(i) == oldBranch) {
    112           root.RemoveSubTree(i);
    113           root.InsertSubTree(i, newBranch);
     110      for (int i = 0; i < root.SubtreesCount; i++) {
     111        if (root.GetSubtree(i) == oldBranch) {
     112          root.RemoveSubtree(i);
     113          root.InsertSubtree(i, newBranch);
    114114          return;
    115115        }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs

    r5733 r5736  
    3939  [Item(Name = "SymbolicRegressionSolution", Description = "Represents a symbolic regression solution (model + data) and attributes of the solution like accuracy and complexity.")]
    4040  public sealed class SymbolicRegressionSolution : RegressionSolution, ISymbolicRegressionSolution {
     41    private const string ModelLengthResultName = "ModelLength";
     42    private const string ModelDepthResultName = "ModelDepth";
     43
    4144    public new ISymbolicRegressionModel Model {
    4245      get { return (ISymbolicRegressionModel)base.Model; }
     
    4548    ISymbolicDataAnalysisModel ISymbolicDataAnalysisSolution.Model {
    4649      get { return (ISymbolicDataAnalysisModel)base.Model; }
     50    }
     51    public int ModelLength {
     52      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
     53      private set { ((IntValue)this[ModelLengthResultName].Value).Value = value; }
     54    }
     55
     56    public int ModelDepth {
     57      get { return ((IntValue)this[ModelDepthResultName].Value).Value; }
     58      private set { ((IntValue)this[ModelDepthResultName].Value).Value = value; }
    4759    }
    4860
     
    5466    public SymbolicRegressionSolution(ISymbolicRegressionModel model, IRegressionProblemData problemData)
    5567      : base(model, problemData) {
     68      Add(new Result(ModelLengthResultName, "Length of the symbolic regression model.", new IntValue()));
     69      Add(new Result(ModelDepthResultName, "Depth of the symbolic regression model.", new IntValue()));
     70      RecalculateResults();
    5671    }
    5772
    5873    public override IDeepCloneable Clone(Cloner cloner) {
    5974      return new SymbolicRegressionSolution(this, cloner);
     75    }
     76
     77    protected override void OnModelChanged(EventArgs e) {
     78      base.OnModelChanged(e);
     79      RecalculateResults();
     80    }
     81
     82    private new void RecalculateResults() {
     83      ModelLength = Model.SymbolicExpressionTree.Length;
     84      ModelDepth = Model.SymbolicExpressionTree.Depth;
    6085    }
    6186
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs

    r5729 r5736  
    9292
    9393        // automatically fold all branches with impact = 1
    94         List<ISymbolicExpressionTreeNode> nodeList = Content.Model.SymbolicExpressionTree.Root.GetSubTree(0).IterateNodesPrefix().ToList();
     94        List<ISymbolicExpressionTreeNode> nodeList = Content.Model.SymbolicExpressionTree.Root.GetSubtree(0).IterateNodesPrefix().ToList();
    9595        foreach (var parent in nodeList) {
    96           for (int subTreeIndex = 0; subTreeIndex < parent.SubTrees.Count(); subTreeIndex++) {
    97             var child = parent.GetSubTree(subTreeIndex);
     96          for (int subTreeIndex = 0; subTreeIndex < parent.SubtreesCount; subTreeIndex++) {
     97            var child = parent.GetSubtree(subTreeIndex);
    9898            if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(1.0)) {
    9999              SwitchNodeWithReplacementNode(parent, subTreeIndex);
     
    102102        }
    103103        // show only interesting part of solution
    104         this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubTree(0).GetSubTree(0));
     104        this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
    105105        this.PaintNodeImpacts();
    106106      }
     
    124124      var tree = Content.Model.SymbolicExpressionTree;
    125125      foreach (SymbolicExpressionTreeNode treeNode in tree.IterateNodesPostfix()) {
    126         for (int i = 0; i < treeNode.SubTrees.Count(); i++) {
    127           ISymbolicExpressionTreeNode subTree = treeNode.GetSubTree(i);
     126        for (int i = 0; i < treeNode.SubtreesCount; i++) {
     127          ISymbolicExpressionTreeNode subTree = treeNode.GetSubtree(i);
    128128          if (subTree == visualTreeNode.SymbolicExpressionTreeNode) {
    129129            SwitchNodeWithReplacementNode(treeNode, i);
     
    133133
    134134      // show only interesting part of solution
    135       this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubTree(0).GetSubTree(0));
     135      this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
    136136
    137137      UpdateModel(tree);
    138       this.PaintNodeImpacts();
    139138    }
    140139
    141140    private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) {
    142       ISymbolicExpressionTreeNode subTree = parent.GetSubTree(subTreeIndex);
    143       parent.RemoveSubTree(subTreeIndex);
     141      ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
     142      parent.RemoveSubtree(subTreeIndex);
    144143      if (replacementNodes.ContainsKey(subTree)) {
    145144        var replacementNode = replacementNodes[subTree];
    146         parent.InsertSubTree(subTreeIndex, replacementNode);
     145        parent.InsertSubtree(subTreeIndex, replacementNode);
    147146        // exchange key and value
    148147        replacementNodes.Remove(subTree);
    149148        replacementNodes.Add(replacementNode, subTree);
    150       } else {
    151         throw new InvalidOperationException("Could not find replacement value.");
    152149      }
    153150    }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/DiscriminantFunctionClassificationSolutionView.cs

    r5717 r5736  
    9898    }
    9999    private void Content_ModelChanged(object sender, EventArgs e) {
     100      Content.Model.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
    100101      UpdateChart();
    101102    }
    102     private void Content_ThresholdsChanged(object sender, EventArgs e) {
     103    private void Model_ThresholdsChanged(object sender, EventArgs e) {
    103104      AddThresholds();
    104105    }
     
    244245
    245246      thresholds[classIndex] = e.NewLocationY;
    246       Content.Model.Thresholds = thresholds;
     247      Content.Model.SetThresholdsAndClassValues(thresholds, Content.Model.ClassValues);
    247248    }
    248249
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ClassificationSolution.cs

    r5730 r5736  
    8282    }
    8383
    84     private void RecalculateResults() {
     84    protected void RecalculateResults() {
    8585      double[] estimatedTrainingClassValues = EstimatedTrainingClassValues.ToArray(); // cache values
    8686      IEnumerable<double> originalTrainingClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationModel.cs

    r5730 r5736  
    4040    [Storable]
    4141    private IRegressionModel model;
     42
    4243    [Storable]
    4344    private double[] classValues;
    44     // class values are not necessarily sorted in ascending order
    4545    public IEnumerable<double> ClassValues {
    4646      get { return (double[])classValues.Clone(); }
    47       set {
    48         if (value == null) throw new ArgumentException();
    49         double[] newValue = value.ToArray();
    50         if (newValue.Length != classValues.Length) throw new ArgumentException();
    51         classValues = newValue;
    52       }
     47      private set { classValues = value.ToArray(); }
    5348    }
     49
    5450    [Storable]
    5551    private double[] thresholds;
    5652    public IEnumerable<double> Thresholds {
    5753      get { return (IEnumerable<double>)thresholds.Clone(); }
    58       set {
    59         thresholds = value.ToArray();
    60         OnThresholdsChanged(EventArgs.Empty);
    61       }
     54      private set { thresholds = value.ToArray(); }
    6255    }
    6356
     
    7164      thresholds = (double[])original.thresholds.Clone();
    7265    }
    73     public DiscriminantFunctionClassificationModel(IRegressionModel model, IEnumerable<double> classValues, IEnumerable<double> thresholds)
     66
     67    public DiscriminantFunctionClassificationModel(IRegressionModel model)
    7468      : base() {
    7569      this.name = ItemName;
    7670      this.description = ItemDescription;
    7771      this.model = model;
    78       this.classValues = classValues.ToArray();
    79       this.thresholds = thresholds.ToArray();
     72      this.classValues = new double[] { 0.0 };
     73      this.thresholds = new double[] { double.NegativeInfinity };
    8074    }
    8175
    8276    public override IDeepCloneable Clone(Cloner cloner) {
    8377      return new DiscriminantFunctionClassificationModel(this, cloner);
     78    }
     79
     80    public void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues) {
     81      var classValuesArr = classValues.ToArray();
     82      var thresholdsArr = thresholds.ToArray();
     83      if (thresholdsArr.Length != classValuesArr.Length) throw new ArgumentException();
     84
     85      this.classValues = classValuesArr;
     86      this.thresholds = thresholdsArr;
     87      OnThresholdsChanged(EventArgs.Empty);
    8488    }
    8589
     
    96100          else break;
    97101        }
    98         yield return classValues.ElementAt(classIndex);
     102        yield return classValues.ElementAt(classIndex - 1);
    99103      }
    100104    }
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/DiscriminantFunctionClassificationSolution.cs

    r5730 r5736  
    4040    public new IDiscriminantFunctionClassificationModel Model {
    4141      get { return (IDiscriminantFunctionClassificationModel)base.Model; }
    42       protected set { base.Model = value; }
     42      protected set {
     43        if (value != null && value != Model) {
     44          if (Model != null) {
     45            Model.ThresholdsChanged -= new EventHandler(Model_ThresholdsChanged);
     46          }
     47          value.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
     48          base.Model = value;
     49        }
     50      }
    4351    }
    4452
     
    4755    protected DiscriminantFunctionClassificationSolution(DiscriminantFunctionClassificationSolution original, Cloner cloner)
    4856      : base(original, cloner) {
     57      RegisterEventHandler();
    4958    }
    50     public DiscriminantFunctionClassificationSolution(IRegressionModel model, IClassificationProblemData problemData, IEnumerable<double> classValues, IEnumerable<double> thresholds)
    51       : this(new DiscriminantFunctionClassificationModel(model, classValues, thresholds), problemData) {
     59    public DiscriminantFunctionClassificationSolution(IRegressionModel model, IClassificationProblemData problemData)
     60      : this(new DiscriminantFunctionClassificationModel(model), problemData) {
    5261    }
    5362    public DiscriminantFunctionClassificationSolution(IDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData)
    5463      : base(model, problemData) {
     64      RegisterEventHandler();
     65      SetAccuracyMaximizingThresholds();
     66    }
     67
     68    [StorableHook(HookType.AfterDeserialization)]
     69    private void AfterDeserialization() {
     70      RegisterEventHandler();
     71    }
     72
     73    private void RegisterEventHandler() {
     74      Model.ThresholdsChanged += new EventHandler(Model_ThresholdsChanged);
     75    }
     76    private void Model_ThresholdsChanged(object sender, EventArgs e) {
     77      OnModelThresholdsChanged(e);
     78    }
     79
     80    public void SetAccuracyMaximizingThresholds() {
     81      double[] classValues;
     82      double[] thresholds;
     83      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
     84      AccuracyMaximizationThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
     85
     86      Model.SetThresholdsAndClassValues(thresholds, classValues);
     87    }
     88
     89    public void SetClassDistibutionCutPointThresholds() {
     90      double[] classValues;
     91      double[] thresholds;
     92      var targetClassValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
     93      NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(ProblemData, EstimatedTrainingValues, targetClassValues, out classValues, out thresholds);
     94
     95      Model.SetThresholdsAndClassValues(thresholds, classValues);
     96    }
     97
     98    protected override void OnModelChanged(EventArgs e) {
     99      base.OnModelChanged(e);     
     100      SetAccuracyMaximizingThresholds();
     101    }
     102
     103    protected override void OnProblemDataChanged(EventArgs e) {
     104      base.OnProblemDataChanged(e);
     105      SetAccuracyMaximizingThresholds();
     106    }
     107    protected virtual void OnModelThresholdsChanged(EventArgs e) {
     108      RecalculateResults();
    55109    }
    56110
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/AccuracyMaximizationThresholdCalculator.cs

    r5730 r5736  
    6969      classValues = problemData.ClassValues.OrderBy(x => x).ToArray();
    7070      int nClasses = classValues.Length;
    71       thresholds = new double[nClasses + 1];
     71      thresholds = new double[nClasses];
    7272      thresholds[0] = double.NegativeInfinity;
    73       thresholds[thresholds.Length - 1] = double.PositiveInfinity;
     73      // thresholds[thresholds.Length - 1] = double.PositiveInfinity;
    7474
    7575      // incrementally calculate accuracy of all possible thresholds
    7676      int[,] confusionMatrix = new int[nClasses, nClasses];
    7777
    78       for (int i = 1; i < thresholds.Length - 1; i++) {
     78      for (int i = 1; i < thresholds.Length; i++) {
    7979        double lowerThreshold = thresholds[i - 1];
    8080        double actualThreshold = Math.Max(lowerThreshold, minEstimatedValue);
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Classification/ThresholdCalculators/NormalDistributionCutPointsThresholdCalculator.cs

    r5730 r5736  
    8888      thresholdList.Sort();
    8989      thresholdList.Insert(0, double.NegativeInfinity);
    90       thresholdList.Add(double.PositiveInfinity);
    9190
    9291      // determine class values for each partition separated by a threshold by calculating the density of all class distributions
    9392      // all points in the partition are classified as the class with the maximal density in the parition
    9493      List<double> classValuesList = new List<double>();
    95       for (int i = 0; i < thresholdList.Count - 1; i++) {
     94      for (int i = 0; i < thresholdList.Count; i++) {
    9695        double m;
    9796        if (double.IsNegativeInfinity(thresholdList[i])) {
    9897          m = thresholdList[i + 1] - 1.0; // smaller than the smalles non-infinity threshold
    99         } else if (double.IsPositiveInfinity(thresholdList[i + 1])) {
    100           m = thresholdList[i] + 1.0; // larger than the largest non-infinity threshold
     98        } else if (i == thresholdList.Count - 1) {
     99          // last threshold
     100          m = thresholdList[i] + 1.0; // larger than the last threshold
    101101        } else {
    102102          m = thresholdList[i] + (thresholdList[i + 1] - thresholdList[i]) / 2.0; // middle of partition
     
    135135        }
    136136      }
    137       filteredThresholds.Add(double.PositiveInfinity);
    138137      thresholds = filteredThresholds.ToArray();
    139138      classValues = filteredClassValues.ToArray();
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolution.cs

    r5730 r5736  
    111111    }
    112112
    113     private void RecalculateResults() {
     113    protected void RecalculateResults() {
    114114      double[] estimatedTrainingValues = EstimatedTrainingValues.ToArray(); // cache values
    115115      IEnumerable<double> originalTrainingValues = ProblemData.Dataset.GetEnumeratedVariableValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes);
  • branches/DataAnalysis Refactoring/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/Classification/IDiscriminantFunctionClassificationModel.cs

    r5717 r5736  
    2424namespace HeuristicLab.Problems.DataAnalysis {
    2525  public interface IDiscriminantFunctionClassificationModel : IClassificationModel {
    26     IEnumerable<double> Thresholds { get; set; }
    27     IEnumerable<double> ClassValues { get; set; }
     26    IEnumerable<double> Thresholds { get; }
     27    IEnumerable<double> ClassValues { get; }
     28    // class values and thresholds can only be assigned simultaniously
     29    void SetThresholdsAndClassValues(IEnumerable<double> thresholds, IEnumerable<double> classValues);
    2830    IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows);
    2931
Note: See TracChangeset for help on using the changeset viewer.