MediumActivation Functions

Implement GELU Activation (Gaussian Error Linear Unit)

Activation Functions

Medium

Problem

Compute the exact Gaussian Error Linear Unit for every input value:

\operatorname{GELU}(x) = \frac{x}{2}\left(1 + \operatorname{erf}\left(\frac{x}{\sqrt{2}}\right)\right)

Here, x is an input value and \operatorname{erf} is the Gaussian error function. Apply the formula elementwise and return a NumPy array with the same shape as the input.

Theory

A neural network without activation functions is just a stack of linear transformations. No matter how many layers you add, the whole thing collapses into a single linear function: y = Wx + b. It cannot learn curves, boundaries, or any non-trivial pattern.

Activation functions introduce nonlinearity after each layer. They decide which neurons "fire" and how strongly. The choice of activation function has a major impact on how well the network trains and how it behaves.


ReLU: The Current Standard

The most widely used activation function is ReLU (Rectified Linear Unit):

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

But ReLU has a sharp corner at x = 0. The output jumps from 0 to linear with no smooth transition. The gradient is either 0 (for negative inputs) or 1 (for positive inputs), with a discontinuity at zero.

This causes two issues:


GELU: A Smooth Alternative

GELU (Gaussian Error Linear Unit) replaces ReLU's hard cutoff with a smooth, probabilistic transition. The formula is:

\text{GELU}(x) = x \cdot \Phi(x)

where \Phi(x) is the cumulative distribution function (CDF) of the standard normal distribution. \Phi(x) answers the question: "If I draw a random number from a standard normal distribution N(0,1), what is the probability that it is less than x?"

Some values of \Phi(x) to build intuition:

So GELU multiplies each input x by the probability that a Gaussian random variable is less than x:

The transition from "suppress" to "pass through" is gradual, not abrupt like ReLU.


The Error Function Connection

The standard normal CDF can be written in terms of the error function (erf):

\Phi(x) = \frac{1}{2}\left(1 + \text{erf}\left(\frac{x}{\sqrt{2}}\right)\right)

Substituting into the GELU formula:

\text{GELU}(x) = \frac{1}{2} x \left(1 + \text{erf}\left(\frac{x}{\sqrt{2}}\right)\right)

The error function \text{erf}(z) is a standard mathematical function that goes smoothly from -1 to +1:

It is available in most math libraries and can be computed efficiently.


Comparing GELU to ReLU

Some concrete values to see the difference:

At x = -1:

At x = 0:

At x = 1:

At x = 3:

Key differences:


Why Smoothness Matters

The smoothness of GELU has practical consequences for training:


Where GELU Is Used

GELU has become the standard activation for Transformer models:

The original GELU paper (Hendrycks and Gimpel, 2016) showed that GELU consistently outperforms ReLU on several benchmarks, especially in natural language processing tasks.

Examples

Example 1

Input
x = [-1.0, 0.0, 1.0]
Output
[-0.158655, 0.0, 0.841345]
Explanation
The exact GELU formula scales negative values toward zero while retaining most of a positive value.

Example 2

Input
x = [[-2.0, -1.0], [0.0, 1.0]]
Output
[[-0.0455, -0.158655], [0.0, 0.841345]]

Hints

  1. Use np.asarray(x, dtype=float) before applying the formula.
  2. Use np.vectorize(math.erf) to apply the scalar error function elementwise.

Requirements

Constraints

Starter Code

import math
import numpy as np

def gelu(x: list) -> np.ndarray:
    """
    Returns a NumPy array with the same shape as x.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Basic 1D arrayExample 1public
2D matrixExample 2public