DiSMEC++
confusion_matrix.h
Go to the documentation of this file.
1 // Copyright (c) 2021, Aalto University, developed by Erik Schultheis
2 // All rights reserved.
3 //
4 // SPDX-License-Identifier: MIT
5 
6 #ifndef DISMEC_SRC_UTILS_CONFUSION_MATRIX_H
7 #define DISMEC_SRC_UTILS_CONFUSION_MATRIX_H
8 
9 #include <cmath>
10 
12  template<class T>
18  };
19 
20  template<class T>
22  lhs.TruePositives += rhs.TruePositives;
23  lhs.FalsePositives += rhs.FalsePositives;
24  lhs.TrueNegatives += rhs.TrueNegatives;
25  lhs.FalseNegatives += rhs.FalseNegatives;
26  return lhs;
27  }
28 
29  // https://en.wikipedia.org/wiki/Confusion_matrix
30 
31  template<class T>
32  constexpr T predicted_positives(const ConfusionMatrixBase<T>& matrix) {
33  return matrix.TruePositives + matrix.FalsePositives;
34  }
35 
36  template<class T>
37  constexpr T predicted_negatives(const ConfusionMatrixBase<T>& matrix) {
38  return matrix.TrueNegatives + matrix.FalseNegatives;
39  }
40 
41  template<class T>
42  constexpr T positives(const ConfusionMatrixBase<T>& matrix) {
43  return matrix.TruePositives + matrix.FalseNegatives;
44  }
45 
46  template<class T>
47  constexpr T negatives(const ConfusionMatrixBase<T>& matrix) {
48  return matrix.TrueNegatives + matrix.FalsePositives;
49  }
50 
51  template<class T>
52  constexpr T total_samples(const ConfusionMatrixBase<T>& matrix) {
53  return matrix.TrueNegatives + matrix.TruePositives + matrix.FalseNegatives + matrix.FalsePositives;
54  }
55 
58  template<class Scalar>
59  constexpr double save_div(Scalar num, Scalar den) {
60  if(num == 0) return 0.0;
61  return static_cast<double>(num) / static_cast<double>(den);
62  }
63 
64  // total-normalized values
65  template<class T>
66  constexpr double true_positive_fraction(const ConfusionMatrixBase<T>& matrix) {
67  return save_div(matrix.TruePositives, total_samples(matrix));
68  }
69 
70  template<class T>
71  constexpr double false_positive_fraction(const ConfusionMatrixBase<T>& matrix) {
72  return save_div(matrix.FalsePositives, total_samples(matrix));
73  }
74 
75  template<class T>
76  constexpr double true_negative_fraction(const ConfusionMatrixBase<T>& matrix) {
77  return save_div(matrix.TrueNegatives, total_samples(matrix));
78  }
79 
80  template<class T>
81  constexpr double false_negative_fraction(const ConfusionMatrixBase<T>& matrix) {
82  return save_div(matrix.FalseNegatives, total_samples(matrix));
83  }
84 
85  template<class T>
86  constexpr double accuracy(const ConfusionMatrixBase<T>& matrix) {
87  return save_div(matrix.TruePositives + matrix.TrueNegatives, total_samples(matrix));
88  }
89 
90  template<class T>
91  constexpr double prevalence(const ConfusionMatrixBase<T>& matrix) {
92  return save_div(positives(matrix), total_samples(matrix));
93  }
94 
95  // prediction-normalized values
96 
97  template<class T>
98  constexpr double positive_predictive_value(const ConfusionMatrixBase<T>& matrix) {
99  return save_div(matrix.TruePositives, predicted_positives(matrix));
100  }
101 
102  template<class T>
103  constexpr double false_discovery_rate(const ConfusionMatrixBase<T>& matrix) {
104  return 1.0 - positive_predictive_value(matrix);
105  }
106 
107  template<class T>
108  constexpr double negative_predictive_value(const ConfusionMatrixBase<T>& matrix) {
109  return save_div(matrix.TrueNegatives, predicted_negatives(matrix));
110  }
111 
112  template<class T>
113  constexpr double false_omission_rate(const ConfusionMatrixBase<T>& matrix) {
114  return 1.0 - negative_predictive_value(matrix);
115  }
116 
117  // detection rates
118  template<class T>
119  constexpr double true_positive_rate(const ConfusionMatrixBase<T>& matrix) {
120  return save_div(matrix.TruePositives, positives(matrix));
121  }
122 
123  template<class T>
124  constexpr double false_negative_rate(const ConfusionMatrixBase<T>& matrix) {
125  return save_div(matrix.FalseNegatives, positives(matrix));
126  }
127 
128  template<class T>
129  constexpr double false_positive_rate(const ConfusionMatrixBase<T>& matrix) {
130  return save_div(matrix.FalsePositives, negatives(matrix));
131  }
132 
133  template<class T>
134  constexpr double true_negative_rate(const ConfusionMatrixBase<T>& matrix) {
135  return save_div(matrix.TrueNegatives, negatives(matrix));
136  }
137 
138  // Common names
139 
140  template<class T>
141  constexpr double precision(const ConfusionMatrixBase<T>& matrix) {
142  return positive_predictive_value(matrix);
143  }
144 
145  template<class T>
146  constexpr double recall(const ConfusionMatrixBase<T>& matrix) {
147  return true_positive_rate(matrix);
148  }
149 
150  template<class T>
151  constexpr double sensitivity(const ConfusionMatrixBase<T>& matrix) {
152  return true_positive_rate(matrix);
153  }
154 
155  template<class T>
156  constexpr double specificity(const ConfusionMatrixBase<T>& matrix) {
157  return true_negative_rate(matrix);
158  }
159 
160  // complex metrics
161 
162  template<class T>
163  constexpr double informedness(const ConfusionMatrixBase<T>& matrix) {
164  return true_positive_rate(matrix) + true_negative_rate(matrix) - 1.0;
165  }
166 
167  template<class T>
168  constexpr double markedness(const ConfusionMatrixBase<T>& matrix) {
169  return positive_predictive_value(matrix) + negative_predictive_value(matrix) - 1.0;
170  }
171 
172  template<class T>
173  constexpr double fowlkes_mallows(const ConfusionMatrixBase<T>& matrix) {
174  return std::sqrt(positive_predictive_value(matrix) * true_positive_rate(matrix));
175  }
176 
177  template<class T>
178  constexpr double positive_likelihood_ratio(const ConfusionMatrixBase<T>& matrix) {
179  return save_div(true_positive_rate(matrix), false_positive_rate(matrix));
180  }
181 
182  template<class T>
183  constexpr double negative_likelihood_ratio(const ConfusionMatrixBase<T>& matrix) {
184  return save_div(false_negative_rate(matrix), true_negative_rate(matrix));
185  }
186 
187  template<class T>
188  constexpr double diagnostic_odds_ratio(const ConfusionMatrixBase<T>& matrix) {
190  }
191 
192  template<class T>
193  constexpr double matthews(const ConfusionMatrixBase<T>& matrix) {
194  return std::sqrt(true_positive_rate(matrix) * true_negative_rate(matrix) * positive_predictive_value(matrix) *
195  negative_predictive_value(matrix)) - std::sqrt(false_negative_rate(matrix) *
196  false_positive_rate(matrix) * false_omission_rate(matrix) * false_discovery_rate(matrix));
197  }
198 
199  template<class T>
200  constexpr double balanced_accuracy(const ConfusionMatrixBase<T>& matrix) {
201  return (true_positive_rate(matrix) + true_negative_rate(matrix)) / 2.0;
202  }
203 
204  template<class T>
205  constexpr double f_beta(const ConfusionMatrixBase<T>& matrix, double beta) {
206  double bs = beta * beta;
207  double num = (1.0 + bs) * static_cast<double>(matrix.TruePositives);
208  double den = num + bs * static_cast<double>(matrix.FalseNegatives) + static_cast<double>(matrix.FalsePositives);
209  if(den == 0.0) return 0.0;
210  return num / den;
211  }
212 }
213 
214 namespace dismec {
215  using confusion_matrix_detail::ConfusionMatrixBase;
216 }
217 
218 #endif //DISMEC_SRC_UTILS_CONFUSION_MATRIX_H
constexpr double positive_likelihood_ratio(const ConfusionMatrixBase< T > &matrix)
constexpr double matthews(const ConfusionMatrixBase< T > &matrix)
constexpr ConfusionMatrixBase< T > & operator+=(ConfusionMatrixBase< T > &lhs, const ConfusionMatrixBase< T > &rhs)
constexpr double diagnostic_odds_ratio(const ConfusionMatrixBase< T > &matrix)
constexpr double negative_predictive_value(const ConfusionMatrixBase< T > &matrix)
constexpr T negatives(const ConfusionMatrixBase< T > &matrix)
constexpr double fowlkes_mallows(const ConfusionMatrixBase< T > &matrix)
constexpr double precision(const ConfusionMatrixBase< T > &matrix)
constexpr T predicted_positives(const ConfusionMatrixBase< T > &matrix)
constexpr T predicted_negatives(const ConfusionMatrixBase< T > &matrix)
constexpr double markedness(const ConfusionMatrixBase< T > &matrix)
constexpr double balanced_accuracy(const ConfusionMatrixBase< T > &matrix)
constexpr double false_positive_fraction(const ConfusionMatrixBase< T > &matrix)
constexpr double false_positive_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double true_negative_fraction(const ConfusionMatrixBase< T > &matrix)
constexpr double informedness(const ConfusionMatrixBase< T > &matrix)
constexpr double false_negative_fraction(const ConfusionMatrixBase< T > &matrix)
constexpr double f_beta(const ConfusionMatrixBase< T > &matrix, double beta)
constexpr double true_positive_fraction(const ConfusionMatrixBase< T > &matrix)
constexpr double true_negative_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double false_negative_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double specificity(const ConfusionMatrixBase< T > &matrix)
constexpr double false_omission_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double true_positive_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double sensitivity(const ConfusionMatrixBase< T > &matrix)
constexpr double false_discovery_rate(const ConfusionMatrixBase< T > &matrix)
constexpr double positive_predictive_value(const ConfusionMatrixBase< T > &matrix)
constexpr T positives(const ConfusionMatrixBase< T > &matrix)
constexpr double recall(const ConfusionMatrixBase< T > &matrix)
constexpr double accuracy(const ConfusionMatrixBase< T > &matrix)
constexpr double save_div(Scalar num, Scalar den)
constexpr double prevalence(const ConfusionMatrixBase< T > &matrix)
constexpr double negative_likelihood_ratio(const ConfusionMatrixBase< T > &matrix)
constexpr T total_samples(const ConfusionMatrixBase< T > &matrix)
Main namespace in which all types, classes, and functions are defined.
Definition: app.h:15