Loss Functions (anglepy.losses)¶
This module implements the energy score loss function using geodesic, chordal, or cosine distance for angular data.
- anglepy.losses.chordal_dist(t1, t2, dim=-1)¶
Calculates the chordal distance between two tensors of angles.
The chordal distance is the straight-line Euclidean distance between two angles when they are embedded as points on a unit circle. Unlike the arc length (angular distance), the chordal distance uses Cartesian coordinates, making it a continuous and differentiable metric that naturally avoids wrapping discontinuities at \(2\pi\).
For vectors of angles, this function computes the \(L_2\) norm of the element-wise Cartesian differences along the specified dimension:
\[\sqrt{\sum_{i} \left( (\cos(t_{1,i}) - \cos(t_{2,i}))^2 + (\sin(t_{1,i}) - \sin(t_{2,i}))^2 \right) + \epsilon}\]Note
A small epsilon (\(1 \times 10^{-8}\)) is added inside the square root to prevent infinite gradients (NaNs) during backpropagation when the distance is exactly zero.
- Parameters:
t1 (torch.Tensor) – The first tensor of angles in radians.
t2 (torch.Tensor) – The second tensor of angles in radians. Must be broadcastable to the shape of t1.
dim (int, optional) – The dimension over which to sum the squared Cartesian differences before applying the square root. Defaults to -1 (the last dimension).
- Returns:
A tensor containing the calculated chordal distances. The dimension specified by dim is reduced.
- Return type:
torch.Tensor
- anglepy.losses.cosine_dist(t1, t2, dim=-1)¶
Calculates the mean cosine-based circular distance between two tensors of angles.
This metric computes the Circular Mean Directional Error by evaluating \(1 - \cos(t_1 - t_2)\) element-wise. This formulation natively handles circular wrapping boundaries (e.g., the difference between \(2\pi\) and \(0\)). The resulting element-wise distances range from \(0\) (perfectly aligned) to \(2\) (completely opposite), which are then averaged across the specified dimension.
- Parameters:
t1 (torch.Tensor) – The first tensor of angles in radians.
t2 (torch.Tensor) – The second tensor of angles in radians. Must be broadcastable to the shape of t1.
dim (int, optional) – The dimension over which to compute the mean of the element-wise cosine distances. Defaults to -1 (the last dimension).
- Returns:
A tensor containing the computed mean cosine distances. The dimension specified by dim is reduced.
- Return type:
torch.Tensor
- anglepy.losses.energy_loss(x_true, x_est, gamma=1, verbose=True, dist_method='chordal')¶
Computes the energy score loss for probabilistic predictions of circular data.
The Energy Score is a strictly proper scoring rule that generalizes the Continuous Ranked Probability Score (CRPS) to multivariate settings. This implementation adapts the metric for angular data (in radians) by utilizing circular distance functions (“chordal” or “cosine”).
The empirical Energy Loss is computed as:
\[\mathbb{E}[d(\hat{x}, x)^\gamma] - \frac{1}{2} \mathbb{E}[d(\hat{x}_i, \hat{x}_j)^\gamma]\]where \(x\) is the ground truth, \(\hat{x}\) are the ensemble predictions, \(m\) is the number of ensemble members, and \(d(\cdot, \cdot)\) is the specified circular distance.
- Parameters:
x_true (torch.Tensor) – The ground truth angles in radians. Expected to be a tensor that can be reshaped to (Batch, Dim).
x_est (torch.Tensor or list of torch.Tensor) – The ensemble of predicted angles in radians. If a tensor, it is split across the batch dimension. If a list, it is stacked to form a shape of (Batch, Samples, Dim).
gamma (float, optional) – The power parameter applied to the distances. If gamma is not an integer, a small epsilon is added to the distances before exponentiation to prevent NaN gradients. Defaults to 1.
verbose (bool, optional) – If True, returns a concatenated tensor containing the total loss, the distance to ground truth (Term 1), and the pairwise ensemble distance (Term 2). If False, returns only the total scalar loss. Defaults to True.
dist_method (str, optional) – The distance metric to evaluate. Must be either “chordal” or “cosine”. Defaults to “chordal”.
- Returns:
If verbose is True, returns a 1D tensor of shape (3,) containing: [total_energy_loss, term_1, term_2].
If verbose is False, returns a scalar tensor containing the computed total energy loss.
- Return type:
torch.Tensor
- Raises:
ValueError – If dist_method is not one of the supported methods.
Note
This function relies on an external vectorize function and circular distance functions (chordal_dist, cosine_dist) which must be available in the local scope.
- anglepy.losses.energy_loss_geodesic(x_true, x_est, verbose=True, kernel_func=<function powered_exponential.<locals>.kernel>, gamma=1)¶
Computes the Energy Score Loss for probabilistic predictions using geodesic distance with a specified kernel function for strict propriety.
This function calculates a generalized, kernel-based Energy Score for angular data. It computes the shortest-path (geodesic) distances between the estimated ensemble and the ground truth, applies a specified kernel function (e.g., from anglepy.kernels), and evaluates the proper scoring rule.
The kernelized Energy Loss is formulated as:
\[\mathbb{E}[k(d(\hat{x}, x)^\gamma)] - \frac{1}{2} \mathbb{E}[k(d(\hat{x}_i, \hat{x}_j)^\gamma)]\]where \(x\) is the ground truth, \(\hat{x}\) are the ensemble predictions, \(m\) is the number of ensemble members, \(d(\cdot, \cdot)\) is the geodesic distance, and \(k(\cdot)\) is the specified kernel_func.
- Parameters:
x_true (torch.Tensor) – The ground truth angles in radians. Expected to be a tensor that can be reshaped to (Batch, Dim).
x_est (torch.Tensor or list of torch.Tensor) – The ensemble of predicted angles in radians. If a tensor, it is split across the batch dimension. If a list, it is stacked to form a shape of (Batch, Samples, Dim).
verbose (bool, optional) – If True, returns a concatenated tensor containing the total loss, the distance to ground truth (Term 1), and the pairwise ensemble distance (Term 2). If False, returns only the total scalar loss. Defaults to True.
kernel_func (callable, optional) – A kernel function initialized with its hyperparameters (e.g., powered_exponential from anglepy.kernels). Defaults to powered_exponential(c=1, alpha=1).
gamma (float, optional) – A power parameter applied to the geodesic distances before they are passed into the kernel function. Defaults to 1.
- Returns:
If verbose=True: A 1D tensor of shape (3,) containing [total_kernel_loss, term_1, term_2].
If verbose=False: A scalar tensor containing the computed total loss.
- Return type:
torch.Tensor
Note
This function expects inputs strictly in the range \([0, 2\pi)\).
It relies on external functions (vectorize, geodesic_dist, apply_kernel) and defaults to a kernel from anglepy.kernels, which must be available in the local scope.
- anglepy.losses.energy_loss_two_sample(x0, x, xp, x0p=None, gamma=1, verbose=True, weights=None, dist_method='chordal')¶
Computes a two-sample Energy Loss (or Energy Distance) for circular data.
This function evaluates the divergence between an estimated distribution and a target distribution using discrete samples. It operates in two modes:
Standard Energy Score (`x0p` is None): Uses one sample from the ground truth (\(x_0\)) and two independent samples from the estimated distribution (\(x, x'\)). Evaluates the strictly proper scoring rule:
\[\frac{1}{2} \left( \mathbb{E}[d(x, x_0)^\gamma] + \mathbb{E}[d(x', x_0)^\gamma] \right) - \frac{1}{2} \mathbb{E}[d(x, x')^\gamma]\]Maximum Mean Discrepancy / Energy Distance (`x0p` is provided): Uses two samples from the true distribution (\(x_0, x_0'\)) and two from the estimated distribution (\(x, x'\)). Evaluates the full symmetric energy distance:
\[\mathbb{E}[d(x, x_0)^\gamma] - \frac{1}{2} \mathbb{E}[d(x, x')^\gamma] - \frac{1}{2} \mathbb{E}[d(x_0, x_0')^\gamma]\]
Distances are computed using specified circular metrics to correctly handle angular wrapping boundaries. All inputs are expected to be in radians.
- Parameters:
x0 (torch.Tensor) – First sample from the ground truth distribution.
x (torch.Tensor) – First sample from the estimated (predicted) distribution.
xp (torch.Tensor) – Second independent sample from the estimated distribution.
x0p (torch.Tensor, optional) – Second independent sample from the ground truth distribution. If provided, calculates the full two-sample energy distance. Defaults to None.
gamma (float, optional) – Power parameter applied to the distances. If gamma is not an integer, a small epsilon is added to distances to prevent NaN gradients. Defaults to 1.
verbose (bool, optional) – If True, returns a concatenated tensor with the total loss, the cross-term distance (Term 1), and the internal estimated distance (Term 2). If False, returns only the total scalar loss. Defaults to True.
weights (torch.Tensor, optional) – Sample weights applied when computing the loss. Only used if x0p is None. Defaults to uniform weights (1 / N).
dist_method (str, optional) – The circular distance metric to use. Must be either “chordal” or “cosine”. Defaults to “chordal”.
- Returns:
If verbose=True: A 1D tensor of shape (3,) containing [total_loss, term_1, term_2].
If verbose=False: A scalar tensor containing the computed loss.
- Return type:
torch.Tensor
- Raises:
ValueError – If dist_method is not one of the supported strings.
Note
This function relies on an external vectorize function and circular distance functions (chordal_dist, cosine_dist) which must be available in the local scope.
- anglepy.losses.energy_loss_two_sample_geodesic(x0, x, xp, x0p=None, verbose=True, weights=None, kernel_func=<function powered_exponential.<locals>.kernel>, gamma=1)¶
Two-Sample Energy Loss using the specified kernel and geodesic distance. Assumes inputs are in radians \([0, 2\pi)\).
- anglepy.losses.geodesic_dist(t1, t2, dim=-1)¶
Calculates the geodesic (shortest arc) distance between two tensors of angles.
Unlike the chordal distance which measures the straight line through the circle, the geodesic distance measures the length of the shortest path along the circle’s circumference. It safely handles angular wrapping by computing the minimum of the clockwise and counter-clockwise arc lengths between the angles.
For vectors of angles, it computes the \(L_2\) norm of these element-wise shortest arcs along the specified dimension:
\[\sqrt{\sum_{i} \left( \min(\delta_i, 2\pi - \delta_i) \right)^2}\]where \(\delta_i = |t_{1,i} - t_{2,i}| \bmod 2\pi\).
- Parameters:
t1 (torch.Tensor) – The first tensor of angles in radians.
t2 (torch.Tensor) – The second tensor of angles in radians. Must be broadcastable to the shape of t1.
dim (int, optional) – The dimension over which to compute the \(L_2\) vector norm of the arc lengths. Defaults to -1 (the last dimension).
- Returns:
A tensor containing the computed geodesic distances. The dimension specified by dim is reduced.
- Return type:
torch.Tensor