Changeset 8594


Ignore:
Timestamp:
09/07/12 11:27:49 (7 years ago)
Author:
mkommend
Message:

#1940: Added support in symbolic classification for different methods to create the classification ModelCreator.

  • Added ModelCreators
  • Refactored SymbolicClassificationModel and SymbolicDiscriminantFunctionClassificationModel
  • Added ModelCreatorParameter to Analyzers and Evaluators if needed
  • Corrected wiring in symbolic classification problems (single- and multiobjective
  • Adapted simplifier
Location:
trunk/sources
Files:
6 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs

    r8550 r8594  
    111111      IClassificationProblemData problemData,
    112112      IEnumerable<int> rows) {
    113       var model = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter);
    114       model.SetAccuracyMaximizingThresholds(problemData);
     113      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, interpreter, new AccuracyMaximizationThresholdCalculator());
     114      model.RecalculateModelParameters(problemData, rows);
    115115      return model;
    116116    }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicDiscriminantFunctionClassificationSolutionSimplifierView.cs

    r8575 r8594  
    5050
    5151    protected override void UpdateModel(ISymbolicExpressionTree tree) {
    52       var model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit);
    53       // the default policy for setting thresholds in classification models is the accuarcy maximizing policy.
    54       // This is rather slow to calculate and can lead to a very laggy UI in the interactive solution simplifier.
    55       // However, since we automatically prune sub-trees based on the threshold reaching the maximum accuracy we must
    56       // also use maximum accuracy threshold calculation here in order to prevent incoherent behavior of the simplifier.
    57       model.SetAccuracyMaximizingThresholds(Content.ProblemData);
     52      var model = new SymbolicDiscriminantFunctionClassificationModel(tree, Content.Model.Interpreter, Content.Model.ThresholdCalculator, Content.Model.LowerEstimationLimit, Content.Model.UpperEstimationLimit);
     53      model.RecalculateModelParameters(Content.ProblemData, Content.ProblemData.TrainingIndices);
    5854      Content.Model = model;
    5955    }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification-3.4.csproj

    r8548 r8594  
    112112  </ItemGroup>
    113113  <ItemGroup>
     114    <Compile Include="Interfaces\ISymbolicClassificationModelCreatorOperator.cs" />
     115    <Compile Include="Interfaces\ISymbolicDiscriminantFunctionClassificationModelCreator.cs" />
     116    <Compile Include="Interfaces\ISymbolicClassificationModelCreator.cs" />
    114117    <Compile Include="Interfaces\ISymbolicDiscriminantFunctionClassificationModel.cs" />
     118    <Compile Include="ModelCreators\AccuracyMaximizingThresholdsModelCreator.cs" />
     119    <Compile Include="ModelCreators\NormalDistributedThresholdsModelCreator.cs" />
    115120    <Compile Include="MultiObjective\SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs" />
    116121    <Compile Include="Plugin.cs" />
     
    177182      <Private>False</Private>
    178183    </ProjectReference>
     184    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
     185      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
     186      <Name>HeuristicLab.Common.Resources-3.3</Name>
     187    </ProjectReference>
    179188    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
    180189      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicClassificationModel.cs

    r7259 r8594  
    2020#endregion
    2121
    22 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
     22using System.Collections.Generic;
    2323namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
    2424  public interface ISymbolicClassificationModel : IClassificationModel, ISymbolicDataAnalysisModel {
     25    double LowerEstimationLimit { get; }
     26    double UpperEstimationLimit { get; }
     27    void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows);
     28    new ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
    2529  }
    2630}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/Interfaces/ISymbolicDiscriminantFunctionClassificationModel.cs

    r7259 r8594  
    2020#endregion
    2121
    22 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2322namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Classification {
    2423  public interface ISymbolicDiscriminantFunctionClassificationModel : IDiscriminantFunctionClassificationModel, ISymbolicClassificationModel {
    25     double LowerEstimationLimit { get; }
    26     double UpperEstimationLimit { get; }
     24    IDiscriminantFunctionThresholdCalculator ThresholdCalculator { get; }
    2725  }
    2826}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveProblem.cs

    r8175 r8594  
    3636    private const string EstimationLimitsParameterName = "EstimationLimits";
    3737    private const string EstimationLimitsParameterDescription = "The lower and upper limit for the estimated value that can be returned by the symbolic classification model.";
     38    private const string ModelCreatorParameterName = "ModelCreator";
     39
    3840
    3941    #region parameter properties
     
    4143      get { return (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
    4244    }
     45    public IValueParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     46      get { return (IValueParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     47    }
    4348    #endregion
    4449    #region properties
    4550    public DoubleLimit EstimationLimits {
    4651      get { return EstimationLimitsParameter.Value; }
     52    }
     53    public ISymbolicClassificationModelCreator ModelCreator {
     54      get { return ModelCreatorParameter.Value; }
    4755    }
    4856    #endregion
     
    5866      : base(new ClassificationProblemData(), new SymbolicClassificationMultiObjectiveMeanSquaredErrorTreeSizeEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
    5967      Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
     68      Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
    6069
    6170      EstimationLimitsParameter.Hidden = true;
     
    7483    [StorableHook(HookType.AfterDeserialization)]
    7584    private void AfterDeserialization() {
     85      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     86        Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
    7687      RegisterEventHandlers();
    7788    }
     
    7990    private void RegisterEventHandlers() {
    8091      SymbolicExpressionTreeGrammarParameter.ValueChanged += (o, e) => ConfigureGrammarSymbols();
     92      ModelCreatorParameter.NameChanged += (o, e) => ParameterizeOperators();
    8193    }
    8294
     
    110122    }
    111123
    112     protected new void ParameterizeOperators() {
     124    protected override void ParameterizeOperators() {
    113125      base.ParameterizeOperators();
    114126      if (Parameters.ContainsKey(EstimationLimitsParameterName)) {
    115127        var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators);
    116         foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>()) {
    117           op.EstimationLimitsParameter.ActualName = EstimationLimitsParameterName;
    118         }
     128        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>())
     129          op.EstimationLimitsParameter.ActualName = EstimationLimitsParameter.Name;
     130        foreach (var op in operators.OfType<ISymbolicClassificationModelCreatorOperator>())
     131          op.ModelCreatorParameter.ActualName = ModelCreatorParameter.Name;
    119132      }
    120133    }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs

    r8550 r8594  
    3434  [StorableClass]
    3535  public sealed class SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer : SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer<ISymbolicClassificationSolution>,
    36     ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
     36    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
    3737    private const string ProblemDataParameterName = "ProblemData";
     38    private const string ModelCreatorParameterName = "ModelCreator";
    3839    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
    3940    private const string EstimationLimitsParameterName = "EstimationLimits";
     
    4344    public ILookupParameter<IClassificationProblemData> ProblemDataParameter {
    4445      get { return (ILookupParameter<IClassificationProblemData>)Parameters[ProblemDataParameterName]; }
     46    }
     47    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     48      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     49    }
     50    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     51      get { return ModelCreatorParameter; }
    4552    }
    4653    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
     
    6774      : base() {
    6875      Parameters.Add(new LookupParameter<IClassificationProblemData>(ProblemDataParameterName, "The problem data for the symbolic classification solution."));
     76      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    6977      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The symbolic data analysis tree interpreter for the symbolic expression tree."));
    7078      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
     
    7583    }
    7684
     85    [StorableHook(HookType.AfterDeserialization)]
     86    private void AfterDeserialization() {
     87      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     88        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     89    }
     90
    7791    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
    78       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    79       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     92      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     93      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    8094
    81       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    82       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     95      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     96      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    8397    }
    8498  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs

    r8550 r8594  
    3434  [StorableClass]
    3535  public sealed class SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer : SymbolicDataAnalysisMultiObjectiveValidationBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationMultiObjectiveEvaluator, IClassificationProblemData>,
    36   ISymbolicDataAnalysisBoundedOperator {
     36  ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
     37    private const string ModelCreatorParameterName = "ModelCreator";
    3738    private const string EstimationLimitsParameterName = "EstimationLimits";
    3839    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
     
    4445    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
    4546      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
     47    }
     48    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     49      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     50    }
     51    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     52      get { return ModelCreatorParameter; }
    4653    }
    4754    #endregion
     
    5966      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The loewr and upper limit for the estimated values produced by the symbolic classification model."));
    6067      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
     68      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    6169    }
    6270    public override IDeepCloneable Clone(Cloner cloner) {
     
    6472    }
    6573
     74    [StorableHook(HookType.AfterDeserialization)]
     75    private void AfterDeserialization() {
     76      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     77        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     78    }
     79
    6680    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQualities) {
    67       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    68       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     81      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     82      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    6983
    70       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    71       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     84      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     85      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    7286    }
    7387  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectivePenaltyScoreEvaluator.cs

    r8551 r8594  
    2525using HeuristicLab.Data;
    2626using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
     27using HeuristicLab.Parameters;
    2728using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    2829
     
    3031  [Item("Penalty Score Evaluator", "Calculates the penalty score of a symbolic classification solution.")]
    3132  [StorableClass]
    32   public class SymbolicClassificationSingleObjectivePenaltyScoreEvaluator : SymbolicClassificationSingleObjectiveEvaluator {
     33  public class SymbolicClassificationSingleObjectivePenaltyScoreEvaluator : SymbolicClassificationSingleObjectiveEvaluator, ISymbolicClassificationModelCreatorOperator {
     34    private const string ModelCreatorParameterName = "ModelCreator";
    3335    public override bool Maximization { get { return false; } }
     36
     37    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     38      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     39    }
     40    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     41      get { return ModelCreatorParameter; }
     42    }
    3443
    3544    [StorableConstructor]
    3645    protected SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(bool deserializing) : base(deserializing) { }
    3746    protected SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(SymbolicClassificationSingleObjectivePenaltyScoreEvaluator original, Cloner cloner) : base(original, cloner) { }
    38     public SymbolicClassificationSingleObjectivePenaltyScoreEvaluator() : base() { }
     47    public SymbolicClassificationSingleObjectivePenaltyScoreEvaluator()
     48      : base() {
     49      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     50    }
    3951
    4052    public override IDeepCloneable Clone(Cloner cloner) {
    4153      return new SymbolicClassificationSingleObjectivePenaltyScoreEvaluator(this, cloner);
    4254    }
     55
     56    [StorableHook(HookType.AfterDeserialization)]
     57    private void AfterDeserialization() {
     58      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     59        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     60    }
     61
    4362
    4463    public override IOperation Apply() {
     
    6685      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
    6786      EstimationLimitsParameter.ExecutionContext = context;
     87      ModelCreatorParameter.ExecutionContext = context;
    6888
    69       var model = new SymbolicDiscriminantFunctionClassificationModel(tree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    70       model.SetAccuracyMaximizingThresholds(problemData);
     89      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(tree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     90      model.RecalculateModelParameters(problemData, rows);
    7191      double penalty = Calculate(model, problemData, rows);
    7292
    7393      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
    7494      EstimationLimitsParameter.ExecutionContext = null;
     95      ModelCreatorParameter.ExecutionContext = null;
    7596
    7697      return penalty;
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveProblem.cs

    r8175 r8594  
    3535    private const string EstimationLimitsParameterName = "EstimationLimits";
    3636    private const string EstimationLimitsParameterDescription = "The lower and upper limit for the estimated value that can be returned by the symbolic classification model.";
     37    private const string ModelCreatorParameterName = "ModelCreator";
    3738
    3839    #region parameter properties
     
    4041      get { return (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName]; }
    4142    }
     43    public IValueParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     44      get { return (IValueParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     45    }
    4246    #endregion
    4347    #region properties
    4448    public DoubleLimit EstimationLimits {
    4549      get { return EstimationLimitsParameter.Value; }
     50    }
     51    public ISymbolicClassificationModelCreator ModelCreator {
     52      get { return ModelCreatorParameter.Value; }
    4653    }
    4754    #endregion
     
    5764      : base(new ClassificationProblemData(), new SymbolicClassificationSingleObjectiveMeanSquaredErrorEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
    5865      Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
     66      Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
    5967
    6068      EstimationLimitsParameter.Hidden = true;
     
    7179    [StorableHook(HookType.AfterDeserialization)]
    7280    private void AfterDeserialization() {
    73       RegisterEventHandlers();
    74       // compatibility
     81
     82      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     83        Parameters.Add(new ValueParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, "", new AccuracyMaximizingThresholdsModelCreator()));
     84
    7585      bool changed = false;
    7686      if (!Operators.OfType<SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer>().Any()) {
     
    8393      }
    8494      if (changed) ParameterizeOperators();
     95      RegisterEventHandlers();
    8596    }
    8697
    8798    private void RegisterEventHandlers() {
    8899      SymbolicExpressionTreeGrammarParameter.ValueChanged += (o, e) => ConfigureGrammarSymbols();
     100      ModelCreatorParameter.NameChanged += (o, e) => ParameterizeOperators();
    89101    }
    90102
     
    125137      if (Parameters.ContainsKey(EstimationLimitsParameterName)) {
    126138        var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators);
    127         foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>()) {
     139        foreach (var op in operators.OfType<ISymbolicDataAnalysisBoundedOperator>())
    128140          op.EstimationLimitsParameter.ActualName = EstimationLimitsParameter.Name;
    129         }
     141        foreach (var op in operators.OfType<ISymbolicClassificationModelCreatorOperator>())
     142          op.ModelCreatorParameter.ActualName = ModelCreatorParameter.Name;
    130143      }
    131144    }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs

    r8550 r8594  
    3434  [StorableClass]
    3535  public sealed class SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionAnalyzer<ISymbolicClassificationSolution>,
    36     ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator {
     36    ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
    3737    private const string ProblemDataParameterName = "ProblemData";
     38    private const string ModelCreatorParameterName = "ModelCreator";
    3839    private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
    3940    private const string EstimationLimitsParameterName = "UpperEstimationLimit";
     
    4243    public ILookupParameter<IClassificationProblemData> ProblemDataParameter {
    4344      get { return (ILookupParameter<IClassificationProblemData>)Parameters[ProblemDataParameterName]; }
     45    }
     46    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     47      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     48    }
     49    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     50      get { return ModelCreatorParameter; }
    4451    }
    4552    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
     
    6572      : base() {
    6673      Parameters.Add(new LookupParameter<IClassificationProblemData>(ProblemDataParameterName, "The problem data for the symbolic classification solution."));
     74      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    6775      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The symbolic data analysis tree interpreter for the symbolic expression tree."));
    6876      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
    6977      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
    7078    }
     79
    7180    public override IDeepCloneable Clone(Cloner cloner) {
    7281      return new SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer(this, cloner);
    7382    }
     83    [StorableHook(HookType.AfterDeserialization)]
     84    private void AfterDeserialization() {
     85      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     86        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     87    }
    7488
    7589    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    76       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    77       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     90      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     91      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    7892
    79       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    80       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     93      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     94      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    8195    }
    8296  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer.cs

    r8550 r8594  
    3333  [Item("SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer", "An operator that collects the training Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
    3434  [StorableClass]
    35   public sealed class SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<IClassificationProblemData, ISymbolicClassificationSolution> {
     35  public sealed class SymbolicClassificationSingleObjectiveTrainingParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveTrainingParetoBestSolutionAnalyzer<IClassificationProblemData, ISymbolicClassificationSolution>, ISymbolicClassificationModelCreatorOperator {
    3636    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
     37    private const string ModelCreatorParameterName = "ModelCreator";
    3738    #region parameter properties
    3839    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
    3940      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
     41    }
     42    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     43      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     44    }
     45    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     46      get { return ModelCreatorParameter; }
    4047    }
    4148    #endregion
     
    5360      : base() {
    5461      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
     62      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    5563    }
    5664    public override IDeepCloneable Clone(Cloner cloner) {
     
    5866    }
    5967
     68    [StorableHook(HookType.AfterDeserialization)]
     69    private void AfterDeserialization() {
     70      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     71        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     72    }
     73
    6074    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
    61       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    62       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     75      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     76      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    6377
    64       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    65       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     78      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     79      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    6680    }
    6781  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs

    r8550 r8594  
    3434  [StorableClass]
    3535  public sealed class SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData>,
    36   ISymbolicDataAnalysisBoundedOperator {
     36  ISymbolicDataAnalysisBoundedOperator, ISymbolicClassificationModelCreatorOperator {
    3737    private const string EstimationLimitsParameterName = "EstimationLimits";
    3838    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
     39    private const string ModelCreatorParameterName = "ModelCreator";
    3940
    4041    #region parameter properties
     
    4445    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
    4546      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
     47    }
     48    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     49      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     50    }
     51    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     52      get { return ModelCreatorParameter; }
    4653    }
    4754    #endregion
     
    5966      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The lower and upper limit for the estimated values produced by the symbolic classification model."));
    6067      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
     68      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    6169    }
    6270    public override IDeepCloneable Clone(Cloner cloner) {
     
    6472    }
    6573
     74    [StorableHook(HookType.AfterDeserialization)]
     75    private void AfterDeserialization() {
     76      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     77        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     78    }
     79
    6680    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    67       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    68       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     81      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     82      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    6983
    70       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    71       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     84      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     85      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    7286    }
    7387  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer.cs

    r8550 r8594  
    3333  [Item("SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer", "An operator that collects the validation Pareto-best symbolic classification solutions for single objective symbolic classification problems.")]
    3434  [StorableClass]
    35   public sealed class SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData> {
     35  public sealed class SymbolicClassificationSingleObjectiveValidationParetoBestSolutionAnalyzer : SymbolicDataAnalysisSingleObjectiveValidationParetoBestSolutionAnalyzer<ISymbolicClassificationSolution, ISymbolicClassificationSingleObjectiveEvaluator, IClassificationProblemData>, ISymbolicClassificationModelCreatorOperator {
    3636    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
     37    private const string ModelCreatorParameterName = "ModelCreator";
    3738    #region parameter properties
    3839    public IValueParameter<BoolValue> ApplyLinearScalingParameter {
    3940      get { return (IValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
     41    }
     42    public IValueLookupParameter<ISymbolicClassificationModelCreator> ModelCreatorParameter {
     43      get { return (IValueLookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
     44    }
     45    ILookupParameter<ISymbolicClassificationModelCreator> ISymbolicClassificationModelCreatorOperator.ModelCreatorParameter {
     46      get { return ModelCreatorParameter; }
    4047    }
    4148    #endregion
     
    5360      : base() {
    5461      Parameters.Add(new ValueParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the produced symbolic classification solution should be linearly scaled.", new BoolValue(false)));
     62      Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
    5563    }
    5664    public override IDeepCloneable Clone(Cloner cloner) {
     
    5866    }
    5967
     68    [StorableHook(HookType.AfterDeserialization)]
     69    private void AfterDeserialization() {
     70      if (!Parameters.ContainsKey(ModelCreatorParameterName))
     71        Parameters.Add(new ValueLookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName, ""));
     72    }
     73
    6074    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree) {
    61       var model = new SymbolicDiscriminantFunctionClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    62       if (ApplyLinearScaling.Value) SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
     75      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel((ISymbolicExpressionTree)bestTree.Clone(), SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
     76      if (ApplyLinearScaling.Value) SymbolicClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    6377
    64       model.SetAccuracyMaximizingThresholds(ProblemDataParameter.ActualValue);
    65       return new SymbolicDiscriminantFunctionClassificationSolution(model, (IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
     78      model.RecalculateModelParameters(ProblemDataParameter.ActualValue, ProblemDataParameter.ActualValue.TrainingIndices);
     79      return model.CreateClassificationSolution((IClassificationProblemData)ProblemDataParameter.ActualValue.Clone());
    6680    }
    6781  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationModel.cs

    r8528 r8594  
    3232  [StorableClass]
    3333  [Item(Name = "SymbolicClassificationModel", Description = "Represents a symbolic classification model.")]
    34   public class SymbolicClassificationModel : SymbolicDataAnalysisModel, ISymbolicClassificationModel {
     34  public abstract class SymbolicClassificationModel : SymbolicDataAnalysisModel, ISymbolicClassificationModel {
     35    [Storable]
     36    private double lowerEstimationLimit;
     37    public double LowerEstimationLimit { get { return lowerEstimationLimit; } }
     38    [Storable]
     39    private double upperEstimationLimit;
     40    public double UpperEstimationLimit { get { return upperEstimationLimit; } }
     41
    3542    [StorableConstructor]
    3643    protected SymbolicClassificationModel(bool deserializing) : base(deserializing) { }
    3744    protected SymbolicClassificationModel(SymbolicClassificationModel original, Cloner cloner)
    3845      : base(original, cloner) {
     46      lowerEstimationLimit = original.lowerEstimationLimit;
     47      upperEstimationLimit = original.upperEstimationLimit;
    3948    }
    40     public SymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter)
     49    protected SymbolicClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
    4150      : base(tree, interpreter) {
     51      this.lowerEstimationLimit = lowerEstimationLimit;
     52      this.upperEstimationLimit = upperEstimationLimit;
    4253    }
    4354
    44     public override IDeepCloneable Clone(Cloner cloner) {
    45       return new SymbolicClassificationModel(this, cloner);
    46     }
     55    public abstract IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows);
     56    public abstract void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows);
    4757
    48     public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
    49       return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows);
    50     }
     58    public abstract ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData);
    5159
    52     public ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
    53       return new SymbolicClassificationSolution(this, new ClassificationProblemData(problemData));
    54     }
    5560    IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
    5661      return CreateClassificationSolution(problemData);
    5762    }
    5863
     64    #region scaling
     65    public static void Scale(ISymbolicClassificationModel model, IClassificationProblemData problemData) {
     66      var dataset = problemData.Dataset;
     67      var targetVariable = problemData.TargetVariable;
     68      var rows = problemData.TrainingIndices;
     69      var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
     70      var targetValues = dataset.GetDoubleValues(targetVariable, rows);
     71      double alpha;
     72      double beta;
     73      OnlineCalculatorError errorState;
     74      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta, out errorState);
     75      if (errorState != OnlineCalculatorError.None) return;
    5976
     77      ConstantTreeNode alphaTreeNode = null;
     78      ConstantTreeNode betaTreeNode = null;
     79      // check if model has been scaled previously by analyzing the structure of the tree
     80      var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
     81      if (startNode.GetSubtree(0).Symbol is Addition) {
     82        var addNode = startNode.GetSubtree(0);
     83        if (addNode.SubtreeCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
     84          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
     85          var mulNode = addNode.GetSubtree(0);
     86          if (mulNode.SubtreeCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
     87            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
     88          }
     89        }
     90      }
     91      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
     92      if (alphaTreeNode != null && betaTreeNode != null) {
     93        betaTreeNode.Value *= beta;
     94        alphaTreeNode.Value *= beta;
     95        alphaTreeNode.Value += alpha;
     96      } else {
     97        var mainBranch = startNode.GetSubtree(0);
     98        startNode.RemoveSubtree(0);
     99        var scaledMainBranch = MakeSum(MakeProduct(mainBranch, beta), alpha);
     100        startNode.AddSubtree(scaledMainBranch);
     101      }
     102    }
     103
     104    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
     105      if (alpha.IsAlmost(0.0)) {
     106        return treeNode;
     107      } else {
     108        var addition = new Addition();
     109        var node = addition.CreateTreeNode();
     110        var alphaConst = MakeConstant(alpha);
     111        node.AddSubtree(treeNode);
     112        node.AddSubtree(alphaConst);
     113        return node;
     114      }
     115    }
     116
     117    private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode treeNode, double beta) {
     118      if (beta.IsAlmost(1.0)) {
     119        return treeNode;
     120      } else {
     121        var multipliciation = new Multiplication();
     122        var node = multipliciation.CreateTreeNode();
     123        var betaConst = MakeConstant(beta);
     124        node.AddSubtree(treeNode);
     125        node.AddSubtree(betaConst);
     126        return node;
     127      }
     128    }
     129
     130    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
     131      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
     132      node.Value = c;
     133      return node;
     134    }
     135    #endregion
    60136  }
    61137}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs

    r8550 r8594  
    3434  [StorableClass]
    3535  [Item(Name = "SymbolicDiscriminantFunctionClassificationModel", Description = "Represents a symbolic classification model unsing a discriminant function.")]
    36   public class SymbolicDiscriminantFunctionClassificationModel : SymbolicDataAnalysisModel, ISymbolicDiscriminantFunctionClassificationModel {
     36  public class SymbolicDiscriminantFunctionClassificationModel : SymbolicClassificationModel, ISymbolicDiscriminantFunctionClassificationModel {
    3737
    3838    [Storable]
     
    4848      private set { classValues = value.ToArray(); }
    4949    }
     50
     51    private IDiscriminantFunctionThresholdCalculator thresholdCalculator;
    5052    [Storable]
    51     private double lowerEstimationLimit;
    52     public double LowerEstimationLimit { get { return lowerEstimationLimit; } }
    53     [Storable]
    54     private double upperEstimationLimit;
    55     public double UpperEstimationLimit { get { return upperEstimationLimit; } }
     53    public IDiscriminantFunctionThresholdCalculator ThresholdCalculator {
     54      get { return thresholdCalculator; }
     55      private set { thresholdCalculator = value; }
     56    }
     57
    5658
    5759    [StorableConstructor]
     
    6163      classValues = (double[])original.classValues.Clone();
    6264      thresholds = (double[])original.thresholds.Clone();
    63       lowerEstimationLimit = original.lowerEstimationLimit;
    64       upperEstimationLimit = original.upperEstimationLimit;
     65      thresholdCalculator = cloner.Clone(original.thresholdCalculator);
    6566    }
    66     public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
     67    public SymbolicDiscriminantFunctionClassificationModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDiscriminantFunctionThresholdCalculator thresholdCalculator,
    6768      double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue)
    68       : base(tree, interpreter) {
     69      : base(tree, interpreter, lowerEstimationLimit, upperEstimationLimit) {
    6970      this.thresholds = new double[0];
    7071      this.classValues = new double[0];
    71       this.lowerEstimationLimit = lowerEstimationLimit;
    72       this.upperEstimationLimit = upperEstimationLimit;
     72      this.ThresholdCalculator = thresholdCalculator;
     73    }
     74
     75    [StorableHook(HookType.AfterDeserialization)]
     76    private void AfterDeserialization() {
     77      if (ThresholdCalculator == null) ThresholdCalculator = new AccuracyMaximizationThresholdCalculator();
    7378    }
    7479
     
    8792    }
    8893
    89     public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
    90       return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows).LimitToRange(lowerEstimationLimit, upperEstimationLimit);
     94    public override void RecalculateModelParameters(IClassificationProblemData problemData, IEnumerable<int> rows) {
     95      double[] classValues;
     96      double[] thresholds;
     97      var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
     98      var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, rows);
     99      thresholdCalculator.Calculate(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
     100      SetThresholdsAndClassValues(thresholds, classValues);
    91101    }
    92102
    93     public IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
     103    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
     104      return Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows).LimitToRange(LowerEstimationLimit, UpperEstimationLimit);
     105    }
     106
     107    public override IEnumerable<double> GetEstimatedClassValues(Dataset dataset, IEnumerable<int> rows) {
    94108      if (!Thresholds.Any() && !ClassValues.Any()) throw new ArgumentException("No thresholds and class values were set for the current symbolic classification model.");
    95109      foreach (var x in GetEstimatedValues(dataset, rows)) {
     
    104118    }
    105119
    106     public SymbolicDiscriminantFunctionClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
     120
     121    public override ISymbolicClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
     122      return CreateDiscriminantClassificationSolution(problemData);
     123    }
     124    public SymbolicDiscriminantFunctionClassificationSolution CreateDiscriminantClassificationSolution(IClassificationProblemData problemData) {
    107125      return new SymbolicDiscriminantFunctionClassificationSolution(this, new ClassificationProblemData(problemData));
    108126    }
    109127    IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
    110       return CreateClassificationSolution(problemData);
     128      return CreateDiscriminantClassificationSolution(problemData);
    111129    }
    112130    IDiscriminantFunctionClassificationSolution IDiscriminantFunctionClassificationModel.CreateDiscriminantFunctionClassificationSolution(IClassificationProblemData problemData) {
    113       return CreateClassificationSolution(problemData);
     131      return CreateDiscriminantClassificationSolution(problemData);
    114132    }
    115133
     
    121139    }
    122140    #endregion
    123 
    124     public void SetAccuracyMaximizingThresholds(IClassificationProblemData problemData) {
    125       double[] classValues;
    126       double[] thresholds;
    127       var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
    128       var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
    129       AccuracyMaximizationThresholdCalculator.CalculateThresholds(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
    130 
    131       SetThresholdsAndClassValues(thresholds, classValues);
    132     }
    133 
    134     public void SetClassDistributionCutPointThresholds(IClassificationProblemData problemData) {
    135       double[] classValues;
    136       double[] thresholds;
    137       var targetClassValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
    138       var estimatedTrainingValues = GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
    139       NormalDistributionCutPointsThresholdCalculator.CalculateThresholds(problemData, estimatedTrainingValues, targetClassValues, out classValues, out thresholds);
    140 
    141       SetThresholdsAndClassValues(thresholds, classValues);
    142     }
    143 
    144     public static void Scale(SymbolicDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData) {
    145       var dataset = problemData.Dataset;
    146       var targetVariable = problemData.TargetVariable;
    147       var rows = problemData.TrainingIndices;
    148       var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
    149       var targetValues = dataset.GetDoubleValues(targetVariable, rows);
    150       double alpha;
    151       double beta;
    152       OnlineCalculatorError errorState;
    153       OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta, out errorState);
    154       if (errorState != OnlineCalculatorError.None) return;
    155 
    156       ConstantTreeNode alphaTreeNode = null;
    157       ConstantTreeNode betaTreeNode = null;
    158       // check if model has been scaled previously by analyzing the structure of the tree
    159       var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
    160       if (startNode.GetSubtree(0).Symbol is Addition) {
    161         var addNode = startNode.GetSubtree(0);
    162         if (addNode.SubtreeCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
    163           alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
    164           var mulNode = addNode.GetSubtree(0);
    165           if (mulNode.SubtreeCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
    166             betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
    167           }
    168         }
    169       }
    170       // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
    171       if (alphaTreeNode != null && betaTreeNode != null) {
    172         betaTreeNode.Value *= beta;
    173         alphaTreeNode.Value *= beta;
    174         alphaTreeNode.Value += alpha;
    175       } else {
    176         var mainBranch = startNode.GetSubtree(0);
    177         startNode.RemoveSubtree(0);
    178         var scaledMainBranch = MakeSum(MakeProduct(mainBranch, beta), alpha);
    179         startNode.AddSubtree(scaledMainBranch);
    180       }
    181     }
    182 
    183     private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
    184       if (alpha.IsAlmost(0.0)) {
    185         return treeNode;
    186       } else {
    187         var addition = new Addition();
    188         var node = addition.CreateTreeNode();
    189         var alphaConst = MakeConstant(alpha);
    190         node.AddSubtree(treeNode);
    191         node.AddSubtree(alphaConst);
    192         return node;
    193       }
    194     }
    195 
    196     private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode treeNode, double beta) {
    197       if (beta.IsAlmost(1.0)) {
    198         return treeNode;
    199       } else {
    200         var multipliciation = new Multiplication();
    201         var node = multipliciation.CreateTreeNode();
    202         var betaConst = MakeConstant(beta);
    203         node.AddSubtree(treeNode);
    204         node.AddSubtree(betaConst);
    205         return node;
    206       }
    207     }
    208 
    209     private static ISymbolicExpressionTreeNode MakeConstant(double c) {
    210       var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
    211       node.Value = c;
    212       return node;
    213     }
    214141  }
    215142}
Note: See TracChangeset for help on using the changeset viewer.