MediumNLP

Pad Sequences

NLP · Data Processing

Medium

Problem

In NLP, batches often need sequences of equal length. Given a list of token ID sequences (lists of ints), pad them with a special pad_value to match the length of the longest sequence.

Theory

Sequence padding transforms variable-length sequences into fixed-length ones by adding special padding tokens. In NLP, sentences have different word counts; in time series, recordings have different durations. Neural networks require fixed-size tensor inputs, so padding is essential for creating batches.


Why Padding is Necessary

Batch processing requirement: Neural networks process data in batches for efficiency. A batch must be a rectangular tensor where all sequences have the same length.

GPU efficiency: GPUs perform best with fixed-size operations. Variable-length inputs require sequential processing, losing parallelism benefits.

API constraints: Framework functions expect arrays/tensors with consistent shapes.


The Padding Process

Given sequences of different lengths:

  1. Determine the target length (max length in batch or specified value)
  2. For sequences shorter than target: add padding tokens
  3. For sequences longer than target: truncate

Padding position:


Mathematical Representation

For a batch of B sequences with lengths l_1, l_2, ..., l_B and target length L:

L = \max(l_1, l_2, ..., l_B) \quad \text{if max\_len is None}

For each sequence s_i with length l_i:

\text{padded\_length} = L

\text{padding\_needed} = \max(0, L - l_i)

\text{truncation\_needed} = \max(0, l_i - L)


Worked Example: Post-Padding

Input sequences (token IDs):

Target length: max(3, 5, 1) = 5

Padding value: 0

Post-padded result:

Output shape: (3, 5) - a proper rectangular matrix


Worked Example: Pre-Padding

Same input sequences, pre-padding:

When to use pre-padding: For sequence models where the last token is most important (e.g., classification based on final hidden state).


Truncation

When sequences exceed the maximum length:

Post-truncation: Keep the first max_len tokens

Pre-truncation: Keep the last max_len tokens

Choice depends on task:


Choosing the Padding Value

Common choices:

Requirements:


Handling Empty Input

When the input list of sequences is empty:

Expected output: Array with shape (0, 0)

This preserves type consistency and allows downstream operations to proceed without special cases.


Interaction with Attention Masks

Padding tokens should not affect model predictions. Attention masks indicate which positions are real vs padded:

\text{mask}_i = \begin{cases} 1 & \text{if position } i \text{ is real} \\ 0 & \text{if position } i \text{ is padding} \end{cases}

Example: Sequence [5, 12, 8, 0, 0]

Transformers use this mask to set attention weights to negative infinity for padded positions, effectively ignoring them.


Determining Maximum Length

Dynamic (per batch):

Fixed:

Considerations:


Worked Example with Truncation

Input sequences:

max_len = 4, padding_value = 0, post-truncation:

Output shape: (3, 4)


Output Data Type

The output should be a NumPy array with integer dtype (typically int32 or int64):


Bucketed Padding

For large datasets, grouping sequences by similar length before padding reduces wasted space:

Bucket strategy:

Trade-off: More complex batching logic vs memory efficiency


Where Sequence Padding Shows Up

Examples

Example 1

Input
seqs = [[1, 2], [3, 4, 5], [6]], pad_value = 0, max_len = None
Output
[[1, 2, 0], [3, 4, 5], [6, 0, 0]]
Explanation
The longest sequence has length 3, so shorter sequences are padded on the right.

Example 2

Input
seqs = [[1, 2, 3], [4]], pad_value = -1, max_len = None
Output
[[1, 2, 3], [4, -1, -1]]

Hints

  1. When max_len is None, derive it from the longest sequence and use zero for an empty collection.
  2. Initialize the output with np.full, then copy each truncated sequence into its row.

Requirements

Constraints

Starter Code

import numpy as np

def pad_sequences(seqs: list, pad_value: int = 0, max_len: int | None = None) -> np.ndarray:
    """
    Returns: np.ndarray of shape (N, L) where:
      N = len(seqs)
      L = max_len if provided else max(len(seq) for seq in seqs) or 0
    """
    # Your code here
    pass

Test Cases

CaseMatches
Basic paddingpublic
Custom pad valuepublic