-
Notifications
You must be signed in to change notification settings - Fork 1
/
LossFunction.hpp
90 lines (67 loc) · 2.09 KB
/
LossFunction.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef LOSSFUNCTION_HPP
#define LOSSFUNCTION_HPP
#include <cmath>
#include <vector>
#include <Eigen/Dense>
class LossFunction {
protected:
const double _epsilon;
public:
LossFunction() :_epsilon(1.0e-8) {}
virtual double calculateLoss(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const = 0;
virtual Eigen::VectorXd calculateGradient(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const = 0;
virtual ~LossFunction() {}
};
// Mean Squared Error (MSE) loss
class MSE : public LossFunction {
public:
double calculateLoss(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const override
{
assert(predictions.size() == targets.size());
size_t classNum = predictions.size();
double predictLoss = 0.0;
for (size_t c = 0; c < classNum; ++c) {
double error = predictions[c] - targets[c];
predictLoss += std::pow(error, 2.0);
}
return predictLoss / (2.0 * predictions.size());
}
Eigen::VectorXd calculateGradient(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const override
{
assert(predictions.size() == targets.size());
Eigen::VectorXd gradientMSE = predictions - targets;
gradientMSE = (gradientMSE / predictions.size());
return gradientMSE;
}
};
// Cross-Entropy loss
class CrossEntropy : public LossFunction {
public:
double calculateLoss(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const override
{
assert(predictions.size() == targets.size());
size_t classNum = predictions.size();
double loss = 0.0;
for (size_t c = 0; c < classNum; ++c) {
loss -= targets(c) * std::log(std::max(predictions(c), _epsilon));
}
return loss / classNum;
}
Eigen::VectorXd calculateGradient(const Eigen::VectorXd& predictions,
const Eigen::VectorXd& targets) const override
{
assert(predictions.size() == targets.size());
size_t classNum = predictions.size();
Eigen::VectorXd gradientCE(classNum);
for (size_t c = 0; c < classNum; ++c) {
gradientCE(c) = -targets(c) / (predictions(c) + _epsilon);
}
return gradientCE;
}
};
#endif // LOSSFUNCTION_HPP