yat/normalizer/Zscore.h

Code
Comments
Other
Rev Date Author Line
1521 21 Sep 08 peter 1 #ifndef _theplu_yat_normalizer_z_score_
1521 21 Sep 08 peter 2 #define _theplu_yat_normalizer_z_score_
1445 27 Aug 08 peter 3
1575 14 Oct 08 jari 4 // $Id$
1575 14 Oct 08 jari 5
1445 27 Aug 08 peter 6 /*
2119 12 Dec 09 peter 7   Copyright (C) 2008 Jari Häkkinen, Peter Johansson
4089 07 Sep 21 peter 8   Copyright (C) 2009, 2010, 2016, 2021 Peter Johansson
1445 27 Aug 08 peter 9
1445 27 Aug 08 peter 10   This file is part of the yat library, http://dev.thep.lu.se/yat
1445 27 Aug 08 peter 11
1445 27 Aug 08 peter 12   The yat library is free software; you can redistribute it and/or
1445 27 Aug 08 peter 13   modify it under the terms of the GNU General Public License as
1486 09 Sep 08 jari 14   published by the Free Software Foundation; either version 3 of the
1445 27 Aug 08 peter 15   License, or (at your option) any later version.
1445 27 Aug 08 peter 16
1445 27 Aug 08 peter 17   The yat library is distributed in the hope that it will be useful,
1445 27 Aug 08 peter 18   but WITHOUT ANY WARRANTY; without even the implied warranty of
1445 27 Aug 08 peter 19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1445 27 Aug 08 peter 20   General Public License for more details.
1445 27 Aug 08 peter 21
1445 27 Aug 08 peter 22   You should have received a copy of the GNU General Public License
1487 10 Sep 08 jari 23   along with yat. If not, see <http://www.gnu.org/licenses/>.
1445 27 Aug 08 peter 24 */
1445 27 Aug 08 peter 25
2157 18 Jan 10 peter 26 #include "utility.h"
2157 18 Jan 10 peter 27
1521 21 Sep 08 peter 28 #include "yat/statistics/Averager.h"
1524 23 Sep 08 peter 29 #include "yat/statistics/AveragerWeighted.h"
1445 27 Aug 08 peter 30
3541 23 Dec 16 peter 31 #include "yat/utility/concept_check.h"
1524 23 Sep 08 peter 32 #include "yat/utility/iterator_traits.h"
1524 23 Sep 08 peter 33
2157 18 Jan 10 peter 34 #include <boost/concept_check.hpp>
2157 18 Jan 10 peter 35
1445 27 Aug 08 peter 36 namespace theplu {
1445 27 Aug 08 peter 37 namespace yat {
1497 12 Sep 08 peter 38 namespace normalizer {
1445 27 Aug 08 peter 39
1445 27 Aug 08 peter 40   /**
1521 21 Sep 08 peter 41      \brief Zero mean and unity variance
1445 27 Aug 08 peter 42
1717 13 Jan 09 peter 43      Shift and scale the values in a range as: \f$ y_i =
4048 03 Mar 21 peter 44      \frac{x_i-m}{k*s} \f$ where \a m is the mean, \a s is the
4048 03 Mar 21 peter 45      standard deviation, and \a k is set in constructor (default:
4048 03 Mar 21 peter 46      1.0). After normalization, the range will have zero mean and
4048 03 Mar 21 peter 47      variance = \f$ 1/k^2 \f$.
1445 27 Aug 08 peter 48
3541 23 Dec 16 peter 49        Type Requirements:
3541 23 Dec 16 peter 50        - \c InputIterator is \ref concept_data_iterator
3541 23 Dec 16 peter 51        - \c InputIterator is \forward_traversal_iterator
3541 23 Dec 16 peter 52        - \c OutputIterator is \writable_iterator
3541 23 Dec 16 peter 53        - \c OutputIterator is \forward_traversal_iterator
3541 23 Dec 16 peter 54
1445 27 Aug 08 peter 55      \since New in yat 0.5
1445 27 Aug 08 peter 56    */
1521 21 Sep 08 peter 57   class Zscore
1445 27 Aug 08 peter 58   {
1445 27 Aug 08 peter 59   public:
1445 27 Aug 08 peter 60     /**
4048 03 Mar 21 peter 61        \param k In the scaling step elements are divided by \c k times
4048 03 Mar 21 peter 62        the standard deviation
4048 03 Mar 21 peter 63
4048 03 Mar 21 peter 64        \since New in yat 0.19
4048 03 Mar 21 peter 65      */
4049 03 Mar 21 peter 66     explicit Zscore(double k=1.0);
4048 03 Mar 21 peter 67
4048 03 Mar 21 peter 68     /**
4048 03 Mar 21 peter 69        \return the k-factor set in constructor
4048 03 Mar 21 peter 70
4048 03 Mar 21 peter 71        \since new in yat 0.19
4048 03 Mar 21 peter 72      */
4048 03 Mar 21 peter 73     double k(void) const;
4048 03 Mar 21 peter 74
4048 03 Mar 21 peter 75     /**
1521 21 Sep 08 peter 76        The element in range [result, result + (last-first)) is
1717 13 Jan 09 peter 77        calculated as result[i] = (first[i] - m) / s where m and std
1521 21 Sep 08 peter 78        are the mean and standard deviation, respectively, of the range
1521 21 Sep 08 peter 79        [first, last).
1445 27 Aug 08 peter 80
1445 27 Aug 08 peter 81        It is possible to centralize a range "in place"; it is
1445 27 Aug 08 peter 82        permissible for the iterators \a first and \a result to be the
1445 27 Aug 08 peter 83        same. \see std::transform
1445 27 Aug 08 peter 84      */
3541 23 Dec 16 peter 85     template<class InputIterator, class OutputIterator>
3541 23 Dec 16 peter 86     void operator()(InputIterator first, InputIterator last,
3541 23 Dec 16 peter 87                     OutputIterator result) const
1445 27 Aug 08 peter 88     {
3541 23 Dec 16 peter 89       BOOST_CONCEPT_ASSERT((utility::DataIteratorConcept<InputIterator>));
3541 23 Dec 16 peter 90       BOOST_CONCEPT_ASSERT((utility::DataIteratorConcept<OutputIterator>));
3541 23 Dec 16 peter 91
3541 23 Dec 16 peter 92       // needed for weighted_if_any2
3541 23 Dec 16 peter 93       typename utility::weighted_if_any2<InputIterator, OutputIterator>::type tag;
1739 21 Jan 09 peter 94       normalize(first, last, result, tag);
1524 23 Sep 08 peter 95     }
1524 23 Sep 08 peter 96
1524 23 Sep 08 peter 97   private:
4048 03 Mar 21 peter 98     double k_;
4048 03 Mar 21 peter 99
4048 03 Mar 21 peter 100
2157 18 Jan 10 peter 101     template<class ForwardIterator, class OutputIterator>
2157 18 Jan 10 peter 102     void normalize(ForwardIterator first, ForwardIterator last,
2157 18 Jan 10 peter 103                    OutputIterator result,
1739 21 Jan 09 peter 104                    utility::unweighted_iterator_tag tag) const
1524 23 Sep 08 peter 105     {
3541 23 Dec 16 peter 106       // we need to traverse the input range once in calculating m
3541 23 Dec 16 peter 107       // (and std) and a second time when assigning new values, so
3541 23 Dec 16 peter 108       // single pass iterator will not suffice.
3541 23 Dec 16 peter 109       BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<ForwardIterator>));
3541 23 Dec 16 peter 110
3541 23 Dec 16 peter 111       BOOST_CONCEPT_ASSERT((boost_concepts::WritableIterator<OutputIterator>));
3541 23 Dec 16 peter 112
1521 21 Sep 08 peter 113       statistics::Averager a;
1521 21 Sep 08 peter 114       add(a, first, last);
1521 21 Sep 08 peter 115       double m = a.mean();
4048 03 Mar 21 peter 116       double factor = 1.0 / (a.std() * k_);
1521 21 Sep 08 peter 117       while (first!=last) {
4048 03 Mar 21 peter 118         *result = (*first - m) * factor;
1521 21 Sep 08 peter 119         ++first;
1521 21 Sep 08 peter 120         ++result;
1521 21 Sep 08 peter 121       }
1445 27 Aug 08 peter 122     }
1445 27 Aug 08 peter 123
3541 23 Dec 16 peter 124     template<class ForwardIterator, class OutputIterator>
3541 23 Dec 16 peter 125     void normalize(ForwardIterator first, ForwardIterator last,
3541 23 Dec 16 peter 126                    OutputIterator result,
1739 21 Jan 09 peter 127                    utility::weighted_iterator_tag tag) const
1524 23 Sep 08 peter 128     {
3541 23 Dec 16 peter 129       // we need to traverse the input range once in calculating m
3541 23 Dec 16 peter 130       // (and std) and a second time when assigning new values, so
3541 23 Dec 16 peter 131       // single pass iterator will not suffice.
3541 23 Dec 16 peter 132       BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<ForwardIterator>));
3541 23 Dec 16 peter 133
3541 23 Dec 16 peter 134       BOOST_CONCEPT_ASSERT((boost_concepts::WritableIterator<OutputIterator>));
3541 23 Dec 16 peter 135       // we traverse output range twice
3541 23 Dec 16 peter 136       BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<OutputIterator>));
2157 18 Jan 10 peter 137       detail::copy_weight_if_weighted(first, last, result);
1524 23 Sep 08 peter 138       statistics::AveragerWeighted a;
1524 23 Sep 08 peter 139       add(a, first, last);
1524 23 Sep 08 peter 140       double m = a.mean();
4048 03 Mar 21 peter 141       double factor = 1.0 / (a.std() * k_);
3541 23 Dec 16 peter 142       utility::iterator_traits<ForwardIterator> in_trait;
3541 23 Dec 16 peter 143       utility::iterator_traits<OutputIterator> out_trait;
1524 23 Sep 08 peter 144       while (first!=last) {
4048 03 Mar 21 peter 145         out_trait.data(result) = (in_trait.data(first) - m) * factor;
1524 23 Sep 08 peter 146         ++first;
1524 23 Sep 08 peter 147         ++result;
1524 23 Sep 08 peter 148       }
1524 23 Sep 08 peter 149     }
1445 27 Aug 08 peter 150   };
1445 27 Aug 08 peter 151
1497 12 Sep 08 peter 152 }}} // end of namespace normalizer, yat and thep
1445 27 Aug 08 peter 153 #endif