Navigation

Introduction to AI

Machine Learning

Deep Learning

Generative AI

Tools & Frameworks

General

Curriculum Learning in Machine Learning

Curriculum learning is a training strategy inspired by human education: rather than presenting training examples in random order, the model is exposed to easier examples first and progressively harder ones as training advances. The intuition — that a well-ordered learning experience leads to better generalization and faster convergence — has been validated empirically across many machine learning tasks since Bengio et al. formalized it in 2009.

In standard stochastic gradient descent, mini-batches are sampled uniformly at random. Curriculum learning replaces this with a difficulty-aware sampling strategy that evolves over training — starting with “easy” examples where the gradient signal is clean and building toward harder examples that require more refined representations.

Motivations and Intuitions

Why does training order matter?

Avoiding local minima early in training: Easy examples produce consistent, low-variance gradients that drive the model toward a good basin in the loss landscape. Hard examples early in training — where the model is random — produce noisy, contradictory gradient updates that can push parameters into poor local minima.

Gradual complexity: When learning compositional skills (parsing sentences, recognizing objects in cluttered scenes, playing games), building simpler components first creates a foundation that hard examples can build upon.

Human analogy: A student learning mathematics works through arithmetic before calculus. A language learner encounters common words before rare ones. A chess player learns tactical patterns before complex strategy.

Cold start in RL: In reinforcement learning, an agent exploring a difficult environment with sparse rewards receives almost no learning signal initially — curricula that start with easier versions of the task or denser reward shaping enable the agent to bootstrap.

Defining Difficulty

A curriculum requires a difficulty measure that assigns each training example a scalar difficulty score. Common approaches:

Loss-Based Difficulty

The model’s own loss on a sample is a natural difficulty proxy — easy examples have low loss, hard ones have high loss:

def compute_sample_difficulties(model, dataset, device):
    """
    Rank dataset samples by model loss.
    Lower loss = easier for the current model state.
    """
    model.eval()
    difficulties = []
    
    with torch.no_grad():
        for idx, (x, y) in enumerate(dataset):
            x, y = x.to(device), y.to(device)
            output = model(x.unsqueeze(0))
            loss = F.cross_entropy(output, y.unsqueeze(0))
            difficulties.append((idx, loss.item()))
    
    # Sort by difficulty (ascending = easy first)
    difficulties.sort(key=lambda d: d[1])
    return [idx for idx, _ in difficulties]

Predefined Difficulty (Teacher-Based Curriculum)

For many domains, difficulty can be defined externally without model feedback:

  • NLP: Sentence length, syntactic depth, rare word proportion.
  • Computer vision: Object size, occlusion, number of objects, background clutter.
  • Reinforcement learning: Level complexity, number of enemies, maze size.
  • Machine translation: Sentence length, vocabulary rarity.
def text_difficulty(sentence: str, word_freq_dict: dict) -> float:
    """
    Approximate difficulty of a training sentence.
    Combines length and vocabulary rarity.
    """
    words = sentence.lower().split()
    length_score = len(words) / 50.0  # Normalized sentence length
    
    # Proportion of rare words (frequency below threshold)
    rare_words = [w for w in words if word_freq_dict.get(w, 0) < 100]
    rarity_score = len(rare_words) / max(len(words), 1)
    
    return 0.5 * length_score + 0.5 * rarity_score

Learned Difficulty Scores

A scoring network trained alongside the main model can learn to estimate difficulty in a task-adapted way — predicting which examples are most informative at the current training stage.

Self-Paced Learning

Self-paced learning (SPL) (Kumar et al., 2010) formalizes curriculum learning as an optimization problem — the model jointly learns parameters and which examples to train on:

$$\min_{\mathbf{w}, \mathbf{v}} \sum_i v_i L(y_i, f(\mathbf{x}_i; \mathbf{w})) - \lambda \sum_i v_i$$

where $v_i \in [0,1]$ is a learnable weight for each example, and $\lambda > 0$ is a pacing parameter. At the optimum:

$$v_i^* = \begin{cases} 1 & \text{if } L_i \leq \lambda \ 0 & \text{otherwise} \end{cases}$$

The model selects examples with loss below a threshold $\lambda$ — initially only easy examples (small $\lambda$), then progressively harder ones as $\lambda$ increases. This is the self-paced aspect: the model’s current loss on a sample determines whether that sample is included.

class SelfPacedSampler:
    """
    Gradually includes harder examples as lambda increases.
    """
    def __init__(self, dataset_size: int, initial_lambda: float = 0.5, 
                 growth_rate: float = 1.05):
        self.dataset_size = dataset_size
        self.lambda_threshold = initial_lambda
        self.growth_rate = growth_rate
    
    def step(self):
        """Increase threshold after each epoch to include more samples."""
        self.lambda_threshold *= self.growth_rate
    
    def get_selected_indices(self, losses: list[float]) -> list[int]:
        """Return indices of examples with loss below current threshold."""
        selected = [i for i, loss in enumerate(losses) if loss <= self.lambda_threshold]
        # Ensure at least a minimum fraction of the dataset is included
        if len(selected) < 0.1 * self.dataset_size:
            threshold = sorted(losses)[int(0.1 * self.dataset_size)]
            selected = [i for i, loss in enumerate(losses) if loss <= threshold]
        return selected

# Training loop with self-paced sampling
sampler = SelfPacedSampler(len(train_dataset))

for epoch in range(num_epochs):
    # Compute current losses on all training examples
    current_losses = compute_sample_difficulties(model, train_dataset, device)
    
    # Select easy-to-moderate examples based on current lambda
    selected_indices = sampler.get_selected_indices(current_losses)
    
    # Train on the selected subset
    subset = torch.utils.data.Subset(train_dataset, selected_indices)
    loader = DataLoader(subset, batch_size=32, shuffle=True)
    train_epoch(model, loader, optimizer)
    
    # Expand the curriculum
    sampler.step()

Competence-Based Curriculum

Competence-based curriculum (Platanios et al., 2019) conditions the sampling distribution on a competence function $c(t) \in [0,1]$ that grows from 0 to 1 during training:

  • At $c = 0$ (start of training): only the easiest examples are sampled.
  • At $c = 1$ (end of training): all examples are sampled uniformly.

A common competence schedule:

$$c(t) = \min\left(1, \sqrt{\frac{t}{T} \cdot (1 - c_0^2) + c_0^2}\right)$$

where $c_0$ is the initial competence fraction (e.g., 0.01 = start with top 1% easiest) and $T$ is the total number of training steps.

import numpy as np

def competence_schedule(step: int, total_steps: int, initial_fraction: float = 0.01) -> float:
    """
    Returns competence value in [0, 1].
    Controls what fraction of the difficulty range is accessible.
    """
    c0 = initial_fraction
    c = min(1.0, np.sqrt((step / total_steps) * (1 - c0**2) + c0**2))
    return c

def sample_with_competence(difficulties: list[float], competence: float, 
                           batch_size: int) -> list[int]:
    """
    Sample batch_size examples from the 'competence' fraction of the difficulty range.
    """
    n = len(difficulties)
    sorted_indices = np.argsort(difficulties)  # Easy to hard
    
    # Only sample from examples within current competence range
    max_idx = max(1, int(competence * n))
    accessible = sorted_indices[:max_idx]
    
    return np.random.choice(accessible, size=batch_size, replace=False).tolist()

Anti-Curriculum and Mixed Strategies

Interestingly, anti-curriculum (hard examples first) sometimes outperforms standard curriculum in specific settings:

  • When the model has strong priors from pretraining, easy examples provide almost no learning signal — hard examples drive learning.
  • For fine-tuning pretrained models (BERT, GPT), standard curriculum may slow convergence because the model already handles easy examples well.

Mixed curriculum strategies combine curriculum and anti-curriculum:

  • Balanced sampling: Sample half from easy examples, half from hard examples at each step.
  • Oscillating curriculum: Alternate between easy-focused and hard-focused epochs.
  • Focal loss as implicit curriculum: In object detection and classification, focal loss $(1 - p_t)^\gamma \cdot CE$ automatically downweights easy (high-confidence) examples and upweights hard (low-confidence) ones — achieving the benefits of curriculum learning without explicit example ordering.

Applications

Neural Machine Translation

Training NMT systems with short, simple sentences first significantly improves convergence speed — the model learns basic word alignment patterns from simple sentences before tackling complex syntactic transformations. Competence-based curricula on sentence length and vocabulary complexity reduce training time by 30-40% to reach the same BLEU score.

Visual Question Answering

VQA models benefit from curricula that start with single-object, direct questions before progressing to multi-hop reasoning questions requiring scene understanding.

Reinforcement Learning

In RL, curriculum learning is particularly impactful for sparse-reward environments:

  • Automatic Domain Randomization (ADR): Starts training in easy (low-variation) environments and automatically increases environment complexity as the agent demonstrates competence.
  • Goal-Conditioned RL: Gradually move goal locations farther from the agent’s start position.
  • Procedural content generation: Video game difficulty curves are effectively RL curricula — starting with easy levels before harder ones.

Large Language Model Pretraining

Curriculum strategies for LLM pretraining:

  • Data quality curriculum: Start with high-quality curated text (books, Wikipedia), introduce noisier web data later.
  • Sequence length curriculum: Start with shorter sequences to fill the context window efficiently, extend to full context length as training matures.
  • Domain curriculum: Start with well-structured text (code, academic papers) before unstructured web crawl data.

Relationship to Other Techniques

TechniqueKey Difference from Curriculum Learning
Active LearningSelects which examples to label (acquisition), not training order
Data AugmentationTransforms existing examples, doesn’t change selection order
Importance SamplingReweights examples for variance reduction, not difficulty-based ordering
Hard Negative MiningSpecifically targets hard negatives in contrastive learning
Focal LossImplicit curriculum via loss weighting, no explicit ordering

Curriculum learning is most valuable when training from scratch on a heterogeneous dataset, when the task has natural difficulty structure (length, complexity, frequency), and when the training budget is limited — because good curricula reach target performance faster, enabling more experiments with the same compute.