EasyFeature Engineering

Implement Min-Max Normalization

Feature Engineering · Data Processing

Easy

Problem

Scale numeric data to the interval [0,1]. For each slice selected by axis, compute

x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}}

Here, x_{\min} and x_{\max} are the minimum and maximum of the same slice. Use column-wise slices when axis=0 and row-wise slices when axis=1. If a slice has range at most eps, return zeros for that slice. Return the scaled values as a NumPy array.

Theory

Min-Max normalization rescales data to fall within a specified range, most commonly [0, 1]. For each feature, the transformation maps the smallest value to 0 and the largest value to 1, with all other values linearly distributed between them. This is a fundamental preprocessing technique for making features comparable.


The Core Formula

For a single value x in a feature with minimum x_{min} and maximum x_{max}:

x_{normalized} = \frac{x - x_{min}}{x_{max} - x_{min}}

This can be understood as two operations:

  1. Shift: Subtract minimum to make the range start at 0
  2. Scale: Divide by range to make the maximum equal to 1

Why Normalization Matters

Equal contribution: Without normalization, features with large values dominate distance calculations and gradient updates.

Convergence speed: Optimization algorithms converge faster when features are on similar scales.

Numerical stability: Very large or very small values can cause overflow or underflow in computations.

Algorithm requirements: Many algorithms assume or work better with normalized inputs.


Handling 1D vs 2D Arrays

1D array (single feature):

2D array (multiple features):

Key insight: The axis of normalization matters. For a 2D array with shape (n_samples, n_features):


Vectorized Implementation Concept

Instead of looping through columns:

  1. Compute all column minimums in one operation
  2. Compute all column maximums in one operation
  3. Broadcast and divide in one operation

Conceptual steps for a 2D array:


The Epsilon Parameter

When the range is zero (all values identical), division by zero occurs:

\frac{x - x_{min}}{0} = \text{undefined}

Solution: Add a small epsilon to the denominator:

x_{normalized} = \frac{x - x_{min}}{x_{max} - x_{min} + \epsilon}

Choosing epsilon:

Result when range is zero: With epsilon, all identical values normalize to approximately 0 (since numerator is 0).


Worked Example: 1D Array

Original data: [2, 4, 6, 8, 10]

Step 1 - Compute min and max:

Step 2 - Apply formula:

Result: [0.0, 0.25, 0.5, 0.75, 1.0]


Worked Example: 2D Array

Original data (3 samples, 2 features):

Step 1 - Compute column statistics:

Column 0: min=100, max=300, range=200 Column 1: min=0.1, max=0.5, range=0.4

Step 2 - Normalize each column:

Column 0:

Column 1:

Normalized result:


Worked Example: Zero Range Column

Original data (3 samples, 2 features):

Column 1 has all identical values (range = 0).

With epsilon = 1e-8:

Column 1 normalization:

All values in Column 1 become 0.


Properties of Min-Max Normalization

Preserves proportional relationships: If a was twice as far from the minimum as b, this relationship holds after normalization.

Does not center data: Unlike Z-score standardization, the mean of normalized data is not necessarily 0 or 0.5.

Bounded output: Values are guaranteed to be in [0, 1] for training data. Test data may exceed this range if it has values outside the training min/max.

Invertible: Can recover original values given the min and max: x = x_{normalized} \cdot (x_{max} - x_{min}) + x_{min}


Common Pitfalls

Forgetting axis: Normalizing along the wrong axis produces incorrect results.

Integer division: In some languages, dividing integers truncates. Ensure floating-point arithmetic.

Storing parameters: Must save min and max from training data to apply the same transformation to test data.

Assuming [0,1] output: Test data can produce values outside [0, 1] if it exceeds training data range.


Where Min-Max Normalization Shows Up

Examples

Example 1

Input
X = [[1, 2], [3, 6], [5, 10]], axis = 0, eps = 1e-12
Output
[[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]]
Explanation
Each column is scaled using its own minimum and maximum.

Example 2

Input
X = [[1, 2], [3, 6], [5, 10]], axis = 1, eps = 1e-12
Output
[[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]]

Hints

  1. Use np.min(..., keepdims=True) and np.max(..., keepdims=True) along axis.
  2. Use np.where(data_range > eps, data_range, 1.0) to build a safe denominator.

Requirements

Constraints

Starter Code

import numpy as np

def minmax_scale(X: list, axis: int = 0, eps: float = 1e-12) -> np.ndarray:
    """
    Returns a floating-point NumPy array matching the shape of X.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Per-column scalingExample 1public
Per-row scalingpublic