ZeroOneLoss.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  * \brief Error measure for classication tasks, typically used for evaluation of results
4  *
5  * \author T. Glasmachers
6  * \date 2010-2011
7  *
8  *
9  * <BR><HR>
10  * This file is part of Shark. This library is free software;
11  * you can redistribute it and/or modify it under the terms of the
12  * GNU General Public License as published by the Free Software
13  * Foundation; either version 3, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this library; if not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24 
25 #ifndef SHARK_OBJECTIVEFUNCTIONS_LOSS_ZEROONELOSS_H
26 #define SHARK_OBJECTIVEFUNCTIONS_LOSS_ZEROONELOSS_H
27 
28 
30 
31 namespace shark {
32 
33 ///
34 /// \brief 0-1-loss for classification.
35 ///
36 /// The ZeroOneLoss requires the existence of the comparison
37 /// operator == for its LabelType template parameter. The
38 /// loss function returns zero of the predictions exactly
39 /// matches the label, and one otherwise.
40 ///
41 template<class LabelType = unsigned int, class OutputType = LabelType>
42 class ZeroOneLoss : public AbstractLoss<LabelType, LabelType>
43 {
44 public:
48 
49  /// constructor
51  { }
52 
53 
54  /// \brief From INameable: return the class name.
55  std::string name() const
56  { return "ZeroOneLoss"; }
57 
58  using base_type::eval;
59 
60  ///\brief Return zero if labels == predictions and one otherwise.
61  double eval(BatchLabelType const& labels, BatchOutputType const& predictions) const{
62  std::size_t numInputs = size(labels);
63  SIZE_CHECK(numInputs == size(predictions));
64 
65  double error = 0;
66  for(std::size_t i = 0; i != numInputs; ++i){
67  error += (predictions(i) != labels(i))?1.0:0.0;
68  }
69  return error;
70  }
71 };
72 
73 
74 /// \brief 0-1-loss for classification.
75 template <>
76 class ZeroOneLoss<unsigned int, RealVector> : public AbstractLoss<unsigned int, RealVector>
77 {
78 public:
82 
83  /// constructor
84  ///
85  /// \param threshold: in the case dim(predictions) == 1, predictions strictly larger than this parameter are regarded as belonging to the positive class
86  ZeroOneLoss(double threshold = 0.0)
87  {
88  m_threshold = threshold;
89  }
90 
91  /// \brief From INameable: return the class name.
92  std::string name() const
93  { return "ZeroOneLoss"; }
94 
95 
96  // annoyingness of C++ templates
97  using base_type::eval;
98 
99  /// Return zero if labels == arg max { predictions_i } and one otherwise,
100  /// where the index i runs over the components of the predictions vector.
101  /// A special version of dim(predictions) == 1 computes the predicted
102  /// labels by thresholding at zero. Shark's label convention is used,
103  /// saying that a positive value encodes class 0, a negative value
104  /// encodes class 1.
105  double eval(BatchLabelType const& labels, BatchOutputType const& predictions) const{
106  std::size_t numInputs = size(labels);
107  SIZE_CHECK(numInputs == (std::size_t)size(predictions));
108 
109  double error = 0;
110  for(std::size_t i = 0; i != numInputs; ++i){
111  error+=evalSingle(labels(i),get(predictions,i));
112  }
113  return error;
114  }
115 private:
116  template<class VectorType>
117  double evalSingle(unsigned int label, VectorType const& predictions) const{
118  std::size_t size = predictions.size();
119  if (size == 1){
120  // binary case, single real-valued predictions
121  unsigned int t = (predictions(0) > m_threshold);
122  if (t == label) return 0.0;
123  else return 1.0;
124  }
125  else{
126  // multi-class case, one prediction component per class
127  RANGE_CHECK(label < size);
128  double p = predictions(label);
129  for (std::size_t i = 0; i<size; i++)
130  {
131  if (i == label) continue;
132  if (predictions(i) >= p) return 1.0;
133  }
134  return 0.0;
135  }
136  }
137 
138  double m_threshold; ///< in the case dim(predictions) == 1, predictions strictly larger tha this parameter are regarded as belonging to the positive class
139 };
140 
141 
142 }
143 #endif