EasyActivation Functions

Implement Leaky ReLU (with α)

Activation Functions

Easy

Problem

Implement the Leaky ReLU activation function:

f(x) = \begin{cases} x & x \geq 0 \\ \alpha x & x < 0 \end{cases}

Here, \alpha is the slope applied to negative inputs. Return a NumPy array for a scalar, list, or NumPy-array input.

Theory

ReLU outputs exactly zero for any negative input:

\text{ReLU}(x) = \max(0, x)

This means if a neuron's pre-activation is negative for every training example, its gradient is always zero. The neuron never updates. It is permanently dead and contributes nothing to the network.

This happens more often than you might expect:


Leaky ReLU: A Simple Fix

Leaky ReLU modifies the negative side to have a small slope instead of being flat at zero:

\text{LeakyReLU}(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x < 0 \end{cases}

Some examples with \alpha = 0.01:

The "leak" is small but crucial. Instead of completely blocking negative signals, it lets a tiny amount through.


The Role of Alpha

The parameter \alpha controls the slope for negative inputs:

The key insight: as long as \alpha \neq 0, no neuron can ever die. Even when the pre-activation is negative, there is always a nonzero gradient (\alpha), so the weights can still update.


The Gradient

The derivative of Leaky ReLU is:

\frac{d}{dx} \text{LeakyReLU}(x) = \begin{cases} 1 & \text{if } x \geq 0 \\ \alpha & \text{if } x < 0 \end{cases}

Compare this to ReLU, where the derivative for negative inputs is exactly 0. With Leaky ReLU, the derivative for negative inputs is \alpha, which is small but nonzero. During backpropagation:

This means gradients can always reach every neuron, regardless of the sign of the input.


Parametric ReLU (PReLU)

A natural extension: instead of fixing \alpha as a constant, make it a learnable parameter. This is called PReLU (Parametric ReLU):

\text{PReLU}(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x < 0 \end{cases}

The formula is identical, but \alpha is now learned during training via backpropagation, just like weights and biases. The network can discover the optimal slope for each layer (or even each neuron).


Where Leaky ReLU Shows Up

Examples

Example 1

Input
x = [-2, -1, 0, 1, 2], alpha = 0.1
Output
[-0.2, -0.1, 0.0, 1.0, 2.0]
Explanation
Nonnegative values remain unchanged, while negative values are multiplied by 0.1.

Example 2

Input
x = [-5, 5], alpha = 0.01
Output
[-0.05, 5.0]

Hints

  1. np.asarray(x, dtype=float) preserves the input shape as an array.
  2. np.where(x >= 0, x, alpha * x) applies both branches elementwise.

Requirements

Constraints

Starter Code

import numpy as np

def leaky_relu(x: list | float, alpha: float = 0.01) -> np.ndarray:
    """
    Returns elementwise Leaky ReLU values as a NumPy array matching the input shape.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Basicpublic
Default alphapublic