Source code for secml.ml.classifiers.loss.c_loss_epsilon_insensitive

"""
.. module:: CLossEpsilonInsensitive
   :synopsis: Epsilon-Insensitive Loss Functions

.. moduleauthor:: Marco Melis <marco.melis@unica.it>
.. moduleauthor:: Ambra Demontis <ambra.demontis@unica.it>

"""
from secml.ml.classifiers.loss import CLossRegression
from secml.array import CArray


[docs]class CLossEpsilonInsensitive(CLossRegression): """Epsilon-Insensitive Loss Function. Any difference between the current prediction and the ground truth is ignored if is less than the `epsilon` threshold. Epsilon-Insensitive loss is used by support vector regression. The Epsilon-Insensitive loss is defined as: .. math:: L_{\\epsilon-\\text{ins}} (y, s) = \\max \\left\\{ |y - s| - \\epsilon, 0 \\right\\} Attributes ---------- class_type : 'e-insensitive' suitable_for : 'regression' """ __class_type = 'e-insensitive' def __init__(self, epsilon=0.1): self._epsilon = float(epsilon) @property def epsilon(self): """Threshold parameter epsilon.""" return self._epsilon @epsilon.setter def epsilon(self, value): """Set the threshold parameter epsilon.""" self._epsilon = float(value)
[docs] def loss(self, y_true, score): """Computes the value of the epsilon-insensitive loss function. Parameters ---------- y_true : CArray Ground truth (correct), targets. Vector-like array. score : CArray Outputs (predicted), targets. Vector-like array of shape (n_samples,). Returns ------- CArray Loss function. Vector-like array. """ if score.is_vector_like is False: raise ValueError("only a vector-like `score` array is supported.") # Ensure we work with vector-like arrays y_true = y_true.ravel() score = score.ravel() # max(0, abs(y - s) - epsilon) e = abs(y_true - score) - self.epsilon e[e < 0] = 0.0 return e
[docs] def dloss(self, y_true, score): """Computes the derivative of the epsilon-insensitive loss function with respect to `score`. Parameters ---------- y_true : CArray Ground truth (correct), targets. Vector-like array. score : CArray Outputs (predicted), targets. Vector-like array of shape (n_samples,). Returns ------- CArray Derivative of the loss function. Vector-like array. """ if score.is_vector_like is False: raise ValueError("only a vector-like `score` array is supported.") # Ensure we work with vector-like arrays y_true = y_true.ravel() score = score.ravel() # -1 if (y - s) > epsilon, 1 if (y - s) < -epsilon, 0 otherwise d = CArray.zeros(shape=y_true.size, dtype=float) d[y_true - score > self.epsilon] = -1 d[score - y_true > self.epsilon] = 1 return d
[docs]class CLossEpsilonInsensitiveSquared(CLossEpsilonInsensitive): """Squared Epsilon-Insensitive Loss Function. Any difference between the current prediction and the ground truth is ignored if is less than the `epsilon` threshold. The Squared Epsilon-Insensitive loss is defined as: .. math:: L^2_{\\epsilon-\\text{ins}} (y, s) = {\\left( \\max\\left\\{ |y - s| - \\epsilon, 0 \\right\\} \\right)}^2 Attributes ---------- class_type : 'e-insensitive-squared' suitable_for : 'regression' """ __class_type = 'e-insensitive-squared'
[docs] def loss(self, y_true, score): """Computes the value of the squared epsilon-insensitive loss function. Parameters ---------- y_true : CArray Ground truth (correct), targets. Vector-like array. score : CArray Outputs (predicted), targets. Vector-like array of shape (n_samples,). Returns ------- CArray Loss function. Vector-like array. """ if score.is_vector_like is False: raise ValueError("only a vector-like `score` array is supported.") # Ensure we work with vector-like arrays y_true = y_true.ravel() score = score.ravel() # (max(0, abs(y - s) - epsilon))^2 e = abs(y_true - score) - self.epsilon e2 = e ** 2 e2[e < 0] = 0 return e2
[docs] def dloss(self, y_true, score): """Computes the derivative of the squared epsilon-insensitive loss function with respect to `score`. Parameters ---------- y_true : CArray Ground truth (correct), targets. Vector-like array. score : CArray Outputs (predicted), targets. Vector-like array of shape (n_samples,). Returns ------- CArray Derivative of the loss function. Vector-like array. """ if score.is_vector_like is False: raise ValueError("only a vector-like `score` array is supported.") # Ensure we work with vector-like arrays y_true = y_true.ravel() score = score.ravel() d = CArray.zeros(shape=y_true.size, dtype=float) z = y_true - score d[z > self.epsilon] = -2 * (z[z > self.epsilon] - self.epsilon) d[z < self.epsilon] = 2 * (-z[z < self.epsilon] - self.epsilon) return d