source: branches/2906_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ZNormalizationTransformation.cs @ 15884

Last change on this file since 15884 was 15884, checked in by pfleck, 15 months ago

#2906 Refactoring

  • Moved transformation-specific parts out of existing interfaces.
  • Moved all Transformation logic to DataAnalysisTransformation.
  • Simplified (Inverse)Transformation of Dataset/ProblemData/Model/Solution.
File size: 6.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Problems.DataAnalysis {
32  [Item("Z-Score Normalization", "Z-Score normalization transformation to standardize the values to a Target Mean and Target Standard Deviation.")]
33  [StorableClass]
34  public class ZNormalizationTransformation : Transformation<double> {
35    #region Parameters
36    private IFixedValueParameter<DoubleValue> TargetMeanParameter {
37      get { return (IFixedValueParameter<DoubleValue>)Parameters["Target Mean"]; }
38    }
39    private IFixedValueParameter<DoubleValue> TargetStandardDeviationParameter {
40      get { return (IFixedValueParameter<DoubleValue>)Parameters["Target Standard Deviation"]; }
41    }
42    private IFixedValueParameter<DoubleValue> OriginalMeanParameter {
43      get { return (IFixedValueParameter<DoubleValue>)Parameters["Original Mean"]; }
44    }
45    private IFixedValueParameter<DoubleValue> OriginalStandardDeviationParameter {
46      get { return (IFixedValueParameter<DoubleValue>)Parameters["Original Standard Deviation"]; }
47    }
48    #endregion
49
50    #region Properties
51    public double TargetMean {
52      get { return TargetMeanParameter.Value.Value; }
53      set { TargetMeanParameter.Value.Value = value; }
54    }
55    public double TargetStandardDeviation {
56      get { return TargetStandardDeviationParameter.Value.Value; }
57      set { TargetStandardDeviationParameter.Value.Value = value; }
58    }
59    public double OriginalMean {
60      get { return OriginalMeanParameter.Value.Value; }
61      private set { OriginalMeanParameter.Value.Value = value; }
62    }
63    public double OriginalStandardDeviation {
64      get { return OriginalStandardDeviationParameter.Value.Value; }
65      private set { OriginalStandardDeviationParameter.Value.Value = value; }
66    }
67    #endregion
68
69    #region Constructor, Cloning & Persistence
70    public ZNormalizationTransformation()
71      : base() {
72      Parameters.Add(new FixedValueParameter<DoubleValue>("Target Mean", new DoubleValue(0)));
73      Parameters.Add(new FixedValueParameter<DoubleValue>("Target Standard Deviation", new DoubleValue(1)));
74      Parameters.Add(new FixedValueParameter<DoubleValue>("Original Mean", new DoubleValue(double.NaN)) { Hidden = true });
75      Parameters.Add(new FixedValueParameter<DoubleValue>("Original Standard Deviation", new DoubleValue(double.NaN)) { Hidden = true });
76    }
77
78    protected ZNormalizationTransformation(ZNormalizationTransformation original, Cloner cloner)
79      : base(original, cloner) {
80    }
81    public override IDeepCloneable Clone(Cloner cloner) {
82      return new ZNormalizationTransformation(this, cloner);
83    }
84
85    [StorableConstructor]
86    protected ZNormalizationTransformation(bool deserializing)
87      : base(deserializing) {
88    }
89    #endregion
90
91    public override bool Check(IEnumerable<double> data, out string errorMessage) {
92      if (data.StandardDeviationPop().IsAlmost(0.0)) {
93        errorMessage = "Z-Score Normalization cannot be applied for data with a standard deviation of zero.";
94        return false;
95      }
96      return base.Check(data, out errorMessage);
97    }
98
99    public override void Configure(IEnumerable<double> data) {
100      Configure(data, out double originalMean, out double originalStandardDeviation);
101      OriginalMean = originalMean;
102      OriginalStandardDeviation = originalStandardDeviation;
103      base.Configure(data);
104    }
105
106    public override IEnumerable<double> Apply(IEnumerable<double> data) {
107      if (double.IsNaN(OriginalMean) || double.IsNaN(OriginalStandardDeviation))
108        throw new InvalidOperationException("Transformation is not configured");
109
110      return Apply(data, TargetMean, TargetStandardDeviation, OriginalMean, OriginalStandardDeviation);
111    }
112
113    public override IEnumerable<double> InverseApply(IEnumerable<double> data) {
114      if (double.IsNaN(OriginalMean) || double.IsNaN(OriginalStandardDeviation))
115        throw new InvalidOperationException("Transformation is not configured");
116
117      return InverseApply(data, TargetMean, TargetStandardDeviation, OriginalMean, OriginalStandardDeviation);
118    }
119
120
121    public static void Configure(IEnumerable<double> data, out double originalMean, out double originalStandardDeviation) {
122      originalMean = data.Average();
123      originalStandardDeviation = data.StandardDeviationPop();
124    }
125
126    public static IEnumerable<double> Apply(IEnumerable<double> data, double targetMean, double targetStandardDeviation, double originalMean = double.NaN, double originalStandardDeviation = double.NaN) {
127      if (double.IsNaN(originalMean)) originalMean = data.Average();
128      if (double.IsNaN(originalStandardDeviation)) originalStandardDeviation = data.StandardDeviationPop();
129
130      return data
131        .Select(x => (x - originalMean) / originalStandardDeviation) // standardize (0, 1)
132        .Select(x => x * targetStandardDeviation + targetMean);
133    }
134
135    public static IEnumerable<double> InverseApply(IEnumerable<double> data, double targetMean, double targetStandardDeviation, double originalMean, double originalStandardDeviation) {
136      return Apply(data, originalMean, originalStandardDeviation, targetMean, targetStandardDeviation);
137    }
138  }
139}
Note: See TracBrowser for help on using the repository browser.