You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.9 KiB

  1. #ifndef __CORESTATS_H__
  2. #define __CORESTATS_H__
  3. class Stats {
  4. public:
  5. virtual ~Stats() {}
  6. /// Resets the statistics.
  7. virtual void reset(float startMean=0, float startVar=0) = 0;
  8. /// Adds a value to the statistics (returns the mean).
  9. virtual float update(float value) = 0;
  10. /// The statistics.
  11. virtual float mean() const = 0;
  12. virtual float var() const = 0;
  13. virtual float stddev() const;
  14. /// Returns the normalized value according to the computed statistics (mean and variance).
  15. float normalize(float value) const;
  16. };
  17. class SimpleStats : public Stats {
  18. public:
  19. float _mean;
  20. float _mean2; // mean of squared values
  21. unsigned long _nSamples;
  22. /// ctor
  23. SimpleStats(float startMean=0, float startVar=0);
  24. virtual ~SimpleStats() {}
  25. /// Resets the statistics.
  26. virtual void reset(float startMean=0, float startVar=0);
  27. /// Adds a value to the statistics (returns the mean).
  28. virtual float update(float value);
  29. /// The statistics.
  30. virtual float mean() const { return _mean; }
  31. // The var() and stddev() are the population (ie. not the sample) variance and standard dev, so technically
  32. // they should be readjusted by multiplying it by _nSamples / (_nSamples-1). But with a lot of samples the
  33. // difference vanishes and we priviledged less floating points computations over precision.
  34. virtual float var() const;
  35. };
  36. /// An exponential moving average class.
  37. class MovingAverage {
  38. public:
  39. // The alpha (mixing) variable (in [0,1]).
  40. float _alpha;
  41. // The current value of the exponential moving average.
  42. float _value;
  43. /**
  44. * Constructs the moving average, starting with #startValue# as its value. The #alphaOrN# argument
  45. * has two options:
  46. * - if <= 1 then it's used directly as the alpha value
  47. * - if > 1 then it's used as the "number of items that are considered from the past" (*)
  48. * (*) Of course this is an approximation. It actually sets the alpha value to 2 / (n - 1)
  49. */
  50. MovingAverage(float alphaOrN=1);
  51. MovingAverage(float alphaOrN, float startValue);
  52. virtual ~MovingAverage() {}
  53. /// Change the smoothing factor to #alphaOrN#.
  54. void setAlphaOrN(float alphaOrN);
  55. /// Resets the moving average.
  56. void reset();
  57. /// Resets the moving average to #startValue#.
  58. void reset(float startValue);
  59. /// Updates the moving average with new value #v# (also returns the current value).
  60. float update(float v);
  61. /// Returns the value of the moving average. This is undefined if isValid() == false.
  62. float get() const { return _value; }
  63. /// Returns true iff the moving average has already been started.
  64. bool isStarted() const;
  65. /// Returns the alpha value.
  66. float alpha() const { return _alpha; }
  67. protected:
  68. void _setStarted(bool start);
  69. };
  70. class MovingStats : public Stats {
  71. public:
  72. MovingAverage avg;
  73. float _var;
  74. /**
  75. * Constructs the moving statistics, starting with #startMean# and #startVar# as initial mean and
  76. * variance. The #alphaOrN# argument has two options:
  77. * - if <= 1 then it's used directly as the alpha value
  78. * - if > 1 then it's used as the "number of items that are considered from the past" (*)
  79. * (*) Of course this is an approximation. It actually sets the alpha value to 2 / (n - 1)
  80. */
  81. MovingStats(float alphaOrN=1);
  82. MovingStats(float alphaOrN, float startMean, float startVar);
  83. virtual ~MovingStats() {}
  84. /// Resets the statistics.
  85. virtual void reset();
  86. /// Resets the statistics.
  87. virtual void reset(float startMean, float startVar);
  88. /// Adds a value to the statistics (returns the mean).
  89. virtual float update(float value);
  90. /// The statistics.
  91. virtual float mean() const { return avg.get(); }
  92. virtual float var() const { return _var; }
  93. virtual bool isStarted() const;
  94. };
  95. /// Adaptive normalizer: normalizes values on-the-run using exponential moving
  96. /// averages over mean and stddev.
  97. class AdaptiveNormalizer : public MovingStats {
  98. public:
  99. AdaptiveNormalizer(float smoothFactor=0.001f);
  100. AdaptiveNormalizer(float mean, float stddev, float smoothFactor=0.001f);
  101. virtual ~AdaptiveNormalizer() {}
  102. void setMean(float mean) { _mean = mean; }
  103. void setStddev(float stddev) { _stddev = stddev; };
  104. virtual float put(float value);
  105. virtual float get() { return _value; }
  106. float _value;
  107. float _mean;
  108. float _stddev;
  109. };
  110. /// Standard normalizer: normalizes values on-the-run using real mean and stddev.
  111. class Normalizer : public SimpleStats {
  112. public:
  113. Normalizer();
  114. Normalizer(float mean, float stddev);
  115. virtual ~Normalizer() {}
  116. void setMean(float mean) { _mean = mean; }
  117. void setStddev(float stddev) { _stddev = stddev; };
  118. virtual float put(float value);
  119. virtual float get() { return _value; }
  120. float _value;
  121. float _mean;
  122. float _stddev;
  123. };
  124. /// Regularizes signal into [0,1] by rescaling it using the min and max values.
  125. class MinMaxScaler {
  126. public:
  127. MinMaxScaler();
  128. virtual ~MinMaxScaler() {}
  129. virtual float put(float value);
  130. virtual float get() { return _value; }
  131. float _value;
  132. float _minValue;
  133. float _maxValue;
  134. };
  135. #endif // __CORESTATS_H__