-
Notifications
You must be signed in to change notification settings - Fork 2
/
losses.py
77 lines (60 loc) · 2.45 KB
/
losses.py
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
import numpy as np
from abc import ABC
class LossFunction(ABC):
"""
Class to calculate the defined loss function for a given target vector and a prediction.
"""
def __init__(self):
...
def __call__(self, output: np.array, target: np.array):
...
def first_derivative(self, output: np.array, target: np.array, **kwargs):
...
class Unity(LossFunction):
def __init__(self):
super(Unity).__init__()
def __call__(self, output: np.array, target: np.array):
return target - output
def first_derivative(self, output: np.array, target: np.array, **kwargs):
return np.eye(output.shape[0])
class QuadraticLoss(LossFunction):
"""
Calculated the quadratic loss or Mean squared error (mse) for regression problems. The target and output are
expected to have the form 1 x observations
"""
def __init__(self):
super(QuadraticLoss).__init__()
def __call__(self, output: np.array, target: np.array):
return np.mean(np.linalg.norm(output - target))
def first_derivative(self, output: np.array, target: np.array, **kwargs):
return output - target
class CrossEntropy(LossFunction):
"""
The cross entropy \sum_{classes}y log(y_hat) is calculated for a binary/multiclass classification problem. The
target vector is assumed to have the form 1 x observations. The target values may not be one-hot encoded, but
be numerated starting from zero. The output is a matrix of the form classes x observations.
"""
def __init__(self):
super(CrossEntropy).__init__()
def __call__(self, output, target):
N = target.shape[1]
p = np.copy(output)
# binary cross entropy case
if output.shape[0] == 1:
loss = target * np.log(np.clip(output, 0, 1) + 1e-8)
loss += (1 - target) * np.log(1 - np.clip(output, 0, 1) + 1e-8)
loss = np.mean(-loss)
# multiclass cross entropy case
else:
log_likelihood = -np.log(p[target, range(N)])
loss = np.sum(log_likelihood) / N
return loss
def first_derivative(self, output: np.array, target: np.array, **kwargs):
a = -(np.divide(target, output+1e-8)) + (np.divide(1-target, 1-output+1e-8))
return a
def first_derivative_softmax(self, output, target):
N = target.shape[1]
grad = np.copy(output)
grad[target, range(N)] -= 1
grad = grad/N
return grad