All challenges
Medium 0 solved 0% acceptance

Layer Normalization

Normalize each row to zero mean and unit variance, then scale and shift it, as every Transformer block does.

What you'll learn

  • Normalize each row to zero mean and unit variance
  • Scale and shift with gamma and beta
  • Understand why epsilon is needed

Problem

Layer normalization keeps the activations of each token on a stable scale. For each row x of the matrix:

  1. mean = Σ x / d and var = Σ (x - mean)² / d (population variance over the row's d values)
  2. x̂ = (x - mean) / √(var + epsilon)
  3. output = gamma × x̂ + beta (element-wise: column j uses gamma[j] and beta[j])

Implement layer_norm(x, gamma, beta, epsilon).

Input

x: A matrix with one row per token and d columns.

gamma, beta: The learned scale and shift, d values each.

epsilon: A small number that avoids division by zero.

Output

Return the normalized matrix, same shape as x.

Constraints

1 ≤ rows ≤ 100, 1 ≤ d ≤ 128

-100 ≤ each value ≤ 100, 0 < epsilon ≤ 0.001

Examples

Example 1
Input:
x = [
    [1.0, 2.0, 3.0]
]
beta = [0.0, 0.0, 0.0]
gamma = [1.0, 1.0, 1.0]
epsilon = 1.0e-05

Expected output:
expected = [
    [-1.224736, 0.0, 1.224736]
]
Input:
std::vector<std::vector<double>> x = {
    {1.0, 2.0, 3.0}
};
std::vector<double> beta = {0.0, 0.0, 0.0};
std::vector<double> gamma = {1.0, 1.0, 1.0};
double epsilon = 1.0e-05;

Expected output:
std::vector<std::vector<double>> expected = {
    {-1.224736, 0.0, 1.224736}
};
Input:
double[][] x = new double[][] {
    new double[] {1.0, 2.0, 3.0}
};
double[] beta = new double[] {0.0, 0.0, 0.0};
double[] gamma = new double[] {1.0, 1.0, 1.0};
double epsilon = 1.0e-05;

Expected output:
double[][] expected = new double[][] {
    new double[] {-1.224736, 0.0, 1.224736}
};

Explanation

mean = 2 and var = (1 + 0 + 1) / 3 ≈ 0.666667, so √(var + epsilon) ≈ 0.816503. The row becomes about [-1.224736, 0, 1.224736]: centered at 0 with variance 1.

Example 2
Input:
x = [
    [5.0, 5.0]
]
beta = [1.0, -1.0]
gamma = [2.0, 3.0]
epsilon = 1.0e-05

Expected output:
expected = [
    [1.0, -1.0]
]
Input:
std::vector<std::vector<double>> x = {
    {5.0, 5.0}
};
std::vector<double> beta = {1.0, -1.0};
std::vector<double> gamma = {2.0, 3.0};
double epsilon = 1.0e-05;

Expected output:
std::vector<std::vector<double>> expected = {
    {1.0, -1.0}
};
Input:
double[][] x = new double[][] {
    new double[] {5.0, 5.0}
};
double[] beta = new double[] {1.0, -1.0};
double[] gamma = new double[] {2.0, 3.0};
double epsilon = 1.0e-05;

Expected output:
double[][] expected = new double[][] {
    new double[] {1.0, -1.0}
};

Explanation

Both values equal the mean, so x̂ = [0, 0] and the output is just beta: [1, -1]. Epsilon prevents dividing by zero.

References

This challenge is adapted for CodeUtility. Follow the statement and constraints above.

Learn from others

Community solutions

No published solutions yet. Solve this challenge to share the first one.