MediumLoss Functions

Implement Focal Loss

Loss Functions

Medium

Problem

Compute the mean binary focal loss from predicted probabilities:

L_i = -(1-p_i)^\gamma y_i\log(p_i) - p_i^\gamma(1-y_i)\log(1-p_i)

Here, p_i is the predicted probability for sample i, y_i is its binary label, and \gamma is gamma. Clip probabilities only for numerical stability, then return the mean of all L_i values as a Python float.

Theory

Multi-class classification often has imbalanced class distributions:

Standard cross-entropy computes the average loss across all samples. When classes are imbalanced:


Focal Loss for Multi-Class Classification

Focal loss extends cross-entropy by adding a modulating factor:

\text{FL}(p_t) = -\alpha_t (1 - p_t)^\gamma \log(p_t)

For multi-class with C classes and true class c^*:

\text{FL} = -\alpha_{c^*} (1 - \hat{y}_{c^*})^\gamma \log(\hat{y}_{c^*})

Where:


The Two Key Components

1. Class weights (alpha values):

2. Focusing term:

These work together:


Numerical Example

Consider 3-class classification:

Sample 1: Easy, majority class

Sample 2: Hard, minority class

The hard minority sample contributes 37,000x more to the loss than the easy majority sample.


Effect of Gamma on Different Confidence Levels

How the focusing factor scales with gamma:

At confidence 0.9 (confident correct):

At confidence 0.5 (uncertain):

At confidence 0.1 (confident wrong):


Setting Alpha Weights

Common strategies for setting alpha values:

Inverse class frequency:

\alpha_c = \frac{N}{C \cdot N_c} Where N is total samples, N_c is samples in class c, C is number of classes.

Effective number of samples:

\alpha_c = \frac{1 - \beta}{1 - \beta^{N_c}} Where \beta \in [0, 1) is a hyperparameter. This accounts for diminishing returns of more samples.

Equal weights:

Normalized:


Comparison: Cross-Entropy vs. Focal Loss

Training behavior differences:

Cross-entropy:

Focal loss:


The Gradient

The gradient of focal loss with respect to the logit for the true class:

\frac{\partial \text{FL}}{\partial z_{c^*}} = \alpha_{c^*} \left[ \gamma (1 - p_t)^{\gamma - 1} p_t \log(p_t) + (1 - p_t)^\gamma (p_t - 1) \right]

Properties:


Implementation Considerations

Numerical stability:

Initialization:

Batch size:


When to Use Focal Loss

Good use cases:

May not help:


Origin and Applications

Focal loss was introduced by Lin et al. in "Focal Loss for Dense Object Detection" (2017):

Examples

Example 1

Input
p = [0.9, 0.2, 0.7, 0.1], y = [1, 0, 1, 0], gamma = 2.0
Output
0.010783
Explanation
Confident correct predictions receive small weights, so their mean focal loss is low.

Example 2

Input
p = [0.5, 0.5, 0.5, 0.5], y = [1, 0, 1, 0], gamma = 2.0
Output
0.173287

Example 3

Input
p = [0.9, 0.2, 0.7, 0.1], y = [1, 0, 1, 0], gamma = 0.0
Output
0.197635

Hints

  1. Use np.clip(p, 1e-15, 1.0 - 1e-15) before taking logarithms.
  2. Use np.log1p(-p) for the negative-class logarithm.
  3. Average the negative sum of the positive and negative terms.

Requirements

Constraints

Starter Code

import numpy as np

def focal_loss(p: list, y: list, gamma: float = 2.0) -> float:
    """
    Returns the loss as a float.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Basicpublic
Uncertain predictionspublic
Gamma = 0public