AlgoPlus v0.1.0
Loading...
Searching...
No Matches
metrics.h
1#ifndef MEAN_SQUARED_ERROR_H
2#define MEAN_SQUARED_ERROR_H
3
4#ifdef __cplusplus
5#include <algorithm>
6#include <cassert>
7#include <cmath>
8#include <iostream>
9#include <numbers>
10#include <numeric>
11#include <vector>
12#endif
13
14namespace _metrics_utils {
15inline double sigmoid(const double x) {
16 return 1.0 / (1.0 + exp(-x));
17}
18
19inline std::vector<double> softmax(const std::vector<double>& logits) {
20 double sum_logits = 0;
21 for (const double& x : logits) {
22 sum_logits += exp(x);
23 }
24
25 std::vector<double> probs;
26 for (const double& x : logits) {
27 probs.push_back(exp(x) / sum_logits);
28 }
29
30 return probs;
31}
32} // namespace _metrics_utils
33
39namespace metrics {
40
41namespace multi_metrics_ {
48inline std::tuple<int, int, int, int> all_metrics_(const std::vector<double>& y,
49 const std::vector<double>& y_pred) {
50 assert(y.size() == y_pred.size());
51 int tp = 0, tn = 0, fp = 0, fn = 0;
52 for (size_t i = 0; i < y.size(); i++) {
53 if (y_pred[i] == y[i] && y[i] == 1) {
54 tp += 1;
55 } else if (y_pred[i] == y[i] && y[i] == 0) {
56 tn += 1;
57 } else if (y_pred[i] != y[i] && y[i] == 1) {
58 fn += 1;
59 } else if (y_pred[i] != y[i] && y[i] == 0) {
60 fp += 1;
61 }
62 }
63
64 return {tp, tn, fp, fn};
65}
66} // namespace multi_metrics_
67
72inline double recall(const std::vector<double>& y, const std::vector<double>& y_pred) {
73 auto [tp, tn, fp, fn] = multi_metrics_::all_metrics_(y, y_pred);
74 return 1.0 * (tp) / (tp + fn);
75}
76
81inline double accuracy_score(const std::vector<double>& y, const std::vector<double>& y_pred) {
82 auto [tp, tn, fp, fn] = multi_metrics_::all_metrics_(y, y_pred);
83 return 1.0 * (tp + tn) / (tp + tn + fp + fn);
84}
85
90inline double precision(const std::vector<double>& y, const std::vector<double>& y_pred) {
91 auto [tp, tn, fp, fn] = multi_metrics_::all_metrics_(y, y_pred);
92 return 1.0 * tp / (tp + fp);
93}
94
99inline double f1_score(const std::vector<double>& y, const std::vector<double>& y_pred) {
100 auto [tp, tn, fp, fn] = multi_metrics_::all_metrics_(y, y_pred);
101 double prec = precision(y, y_pred), rec = recall(y, y_pred);
102 return 2.0 * (prec * rec) / (prec + rec);
103}
104
111inline double euclidean_distance(const std::vector<double>& x, const std::vector<double>& y) {
112 assert(x.size() == y.size());
113
114 double _dist = 0.0;
115 for (size_t i = 0; i < x.size(); i++) {
116 _dist += std::powf(y[i] - x[i], 2);
117 }
118
119 return std::sqrt(_dist);
120}
121
128inline double manhattan_distance(const std::vector<double>& x, const std::vector<double>& y) {
129 assert(x.size() == y.size());
130
131 double _dist = 0.0;
132 for (size_t i = 0; i < x.size(); i++) {
133 _dist += std::abs(y[i] - x[i]);
134 }
135
136 return _dist;
137}
138
146inline double minkowski_distance(const std::vector<double>& x, const std::vector<double>& y,
147 const double p) {
148 assert(x.size() == y.size());
149
150 double _dist = 0.0;
151 for (size_t i = 0; i < x.size(); i++) {
152 _dist += std::abs(y[i] - x[i]);
153 }
154
155 return std::powf(_dist, 1.0 / p);
156}
157
158namespace losses {
165inline double mean_squared_error(std::vector<double> const& y, std::vector<double> const& y_hat) {
166 assert(y.size() == y_hat.size());
167 size_t n = y.size();
168 double mse = 0.0;
169 for (size_t i = 0; i < n; i++) {
170 mse += powf(y[i] - y_hat[i], 2);
171 }
172 return mse / double(n);
173}
174
181inline double root_mean_squared_error(std::vector<double> const& y,
182 std::vector<double> const& y_hat) {
183 return std::sqrt(mean_squared_error(y, y_hat));
184}
185
192inline double mean_absolute_error(std::vector<double> const& y, std::vector<double> const& y_hat) {
193 assert(y.size() == y_hat.size());
194 size_t n = y.size();
195 double mae = 0.0;
196 for (size_t i = 0; i < n; i++) {
197 mae += std::abs(y[i] - y_hat[i]);
198 }
199 return mae / double(n);
200}
201
202// /**
203// * @brief log loss for multiclass classification
204// * @param y(vector<double>): the original labels
205// * @param y_hat(vector<double>): the predicted labels
206// * @return double
207// */
208// double xlogy(std::vector<double> const& y, std::vector<double> const& y_hat)
209// {
210// assert(y.size() == y_hat.size());
211// std::vector<double> softmax_ = _metrics_utils::softmax(y);
212// assert(softmax_.size() == y.size());
213
214// size_t n = y.size();
215// double ce = 0.0;
216// for (const double &x: softmax_) {
217// ce += log(x);
218// }
219// return -ce;
220// }
221
228inline double binary_crossentropy_loss(std::vector<double> const& y,
229 std::vector<double> const& y_hat) {
230 assert(y.size() == y_hat.size());
231 for (auto& x : y) {
232 assert(x == 0.0 || x == 1.0);
233 }
234
235 size_t n = y.size();
236 double bce = 0.0, eps = 1e-15;
237 for (size_t i = 0; i < n; i++) {
238 double prob = _metrics_utils::sigmoid(y_hat[i]);
239 double clipped_y_hat = std::clamp(prob, eps, 1 - eps);
240 bce += (y[i] * log(clipped_y_hat) + (1 - y[i]) * log(1 - clipped_y_hat));
241 }
242 return -bce / double(n);
243}
244} // namespace losses
245} // namespace metrics
246
247#endif
losses namespace that contains a couple of useful losses in machine learning
Definition metrics.h:39
double euclidean_distance(const std::vector< double > &x, const std::vector< double > &y)
euclidean distance function
Definition metrics.h:111
double manhattan_distance(const std::vector< double > &x, const std::vector< double > &y)
manhattan distance function
Definition metrics.h:128
double f1_score(const std::vector< double > &y, const std::vector< double > &y_pred)
f1 score function: [2 * precision * recall / precision + recall]
Definition metrics.h:99
double minkowski_distance(const std::vector< double > &x, const std::vector< double > &y, const double p)
minkowski distance
Definition metrics.h:146
double accuracy_score(const std::vector< double > &y, const std::vector< double > &y_pred)
accuracy score function[(tp + tn) / (tp + tn + fp + fn)]
Definition metrics.h:81
double recall(const std::vector< double > &y, const std::vector< double > &y_pred)
recall function[tp / tp + fn]
Definition metrics.h:72
double precision(const std::vector< double > &y, const std::vector< double > &y_pred)
precision function[tp / tp + fp]
Definition metrics.h:90