Skip to content
Back to skills

Low Prob Exploration

ASecurity

Preserve reasoning diversity in RL by protecting low-probability tokens that represent novel thinking paths. Trigger: maintain exploration capability during RL training while avoiding entropy collapse on reasoning tasks.

  • 6 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 9, 2026
datapythongitperformance

Works with

  • cli

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill low-prob-exploration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Low Prob Exploration?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Low Prob Exploration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-low-prob-exploration/badge)](https://www.skillsdirectory.com/skills/adu2021-low-prob-exploration)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: low-prob-exploration
title: "Low-Probability Tokens Sustain Exploration in Reasoning RL"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: https://arxiv.org/abs/2510.03222
keywords: [reinforcement-learning, exploration, entropy-regularization, reasoning, token-filtering]
description: "Preserve reasoning diversity in RL by protecting low-probability tokens that represent novel thinking paths. Trigger: maintain exploration capability during RL training while avoiding entropy collapse on reasoning tasks."
---

# Low-Probability Tokens Sustain Exploration

## Core Concept

During RLVR (RL with Verifiable Rewards) training on reasoning tasks, models suffer from entropy collapse—the policy converges too tightly to common answer patterns, eliminating valuable exploratory reasoning. Low-probability tokens (rare in pretraining) represent genuine thinking diversity but are systematically eliminated during RL. This skill introduces Low-probability Regularization (Lp-Reg): create a proxy distribution filtering noise while protecting "reasoning sparks"—low-probability tokens that enable novel solution paths.

The key insight: Not all entropy is useful exploration; distinguish signal-carrying low-probability tokens from noise, and protect only the signal.

## Architecture Overview

- **Reasoning Sparks Identification**: Detect low-probability tokens that carry reasoning value
- **Proxy Distribution Creation**: Filter out noise while preserving signal
- **Soft Regularization**: KL divergence-based entropy maintenance targeted to valuable tokens
- **Stable On-Policy RL**: Enable continuous scaling without entropy collapse
- **Token-Level Analysis**: Fine-grained understanding of what enables diverse reasoning

## Implementation Steps

### 1. Identify Reasoning Sparks

Analyze which low-probability tokens contribute to diverse reasoning paths.

```python
class ReasoningSparkDetector:
    """
    Identify low-probability tokens that enable novel reasoning.
    """
    def __init__(self, model, reference_model):
        self.model = model
        self.ref_model = reference_model  # Pretrained baseline

    def identify_reasoning_sparks(self, reasoning_traces, solutions, correctness):
        """
        Determine which low-probability tokens lead to correct solutions.

        Args:
            reasoning_traces: List of reasoning token sequences
            solutions: Corresponding final answers
            correctness: Boolean list of correctness

        Returns:
            Set of token IDs that represent reasoning sparks
        """
        spark_candidates = {}

        for trace, solution, is_correct in zip(reasoning_traces, solutions, correctness):
            tokens = tokenize(trace)

            for token_id in tokens:
                token_prob_pretrain = self.ref_model.get_token_prob(token_id)

                # Low-probability tokens: prob < 0.1
                if token_prob_pretrain < 0.1:
                    if token_id not in spark_candidates:
                        spark_candidates[token_id] = {
                            "correct_count": 0,
                            "total_count": 0,
                            "solutions": []
                        }

                    spark_candidates[token_id]["total_count"] += 1
                    spark_candidates[token_id]["solutions"].append(solution)

                    if is_correct:
                        spark_candidates[token_id]["correct_count"] += 1

        # Filter: keep tokens with high correctness rate
        reasoning_sparks = set()
        for token_id, stats in spark_candidates.items():
            correctness_rate = stats["correct_count"] / (stats["total_count"] + 1e-8)

            # Keep tokens that appear in correct solutions >50% of the time
            if correctness_rate > 0.5 and stats["total_count"] > 3:
                reasoning_sparks.add(token_id)

        return reasoning_sparks
```

### 2. Create Proxy Distribution

Build a filtered probability distribution that removes noise while preserving reasoning sparks.

```python
def create_proxy_distribution(logits, reasoning_sparks, noise_threshold=0.01):
    """
    Create proxy distribution: filter noise, amplify reasoning sparks.

    Args:
        logits: Raw model logits (vocab_size,)
        reasoning_sparks: Set of token IDs to protect
        noise_threshold: Probability below which tokens are filtered

    Returns:
        Filtered probability distribution
    """
    # Convert logits to probabilities
    probs = torch.softmax(logits, dim=-1)

    # Create mask for tokens to keep
    keep_mask = torch.zeros_like(probs)

    for token_id in reasoning_sparks:
        keep_mask[token_id] = 1.0

    # Remove low-probability noise (except protected sparks)
    for token_id in range(len(probs)):
        if token_id not in reasoning_sparks and probs[token_id] < noise_threshold:
            probs[token_id] = 0.0

    # Re-normalize to valid probability distribution
    proxy_dist = probs / (torch.sum(probs) + 1e-8)

    # Amplify reasoning sparks slightly
    for token_id in reasoning_sparks:
        proxy_dist[token_id] *= 1.2  # 20% boost

    # Final normalization
    proxy_dist = proxy_dist / (torch.sum(proxy_dist) + 1e-8)

    return proxy_dist
```

### 3. Implement Low-Probability Regularization (Lp-Reg)

Apply soft KL regularization using the proxy distribution.

```python
class LowProbabilityRegularization:
    """
    Maintain entropy using low-probability token protection.
    """
    def __init__(self, reference_model):
        self.ref_model = reference_model

    def compute_lp_reg_loss(
        self,
        model_dist,
        proxy_dist,
        reasoning_sparks,
        temperature=1.0,
        reg_weight=0.1
    ):
        """
        Compute regularization loss protecting reasoning sparks.

        Args:
            model_dist: Current model's probability distribution
            proxy_dist: Filtered proxy distribution
            reasoning_sparks: Protected token set
            temperature: Distribution sharpness
            reg_weight: Regularization strength

        Returns:
            Scalar regularization loss
        """
        # Apply temperature to soften distributions
        model_dist_soft = model_dist ** (1 / temperature)
        model_dist_soft = model_dist_soft / torch.sum(model_dist_soft)

        proxy_dist_soft = proxy_dist ** (1 / temperature)
        proxy_dist_soft = proxy_dist_soft / torch.sum(proxy_dist_soft)

        # KL divergence: encourage model to match proxy distribution
        # But only for tokens related to reasoning sparks
        kl_loss = 0

        for token_id in reasoning_sparks:
            kl = model_dist_soft[token_id] * (
                torch.log(model_dist_soft[token_id] + 1e-8) -
                torch.log(proxy_dist_soft[token_id] + 1e-8)
            )
            kl_loss += kl

        # Mild regularization: don't fully constrain, allow some flexibility
        regularization = reg_weight * kl_loss

        return regularization
```

### 4. Full RL Loop with Lp-Reg

Integrate regularization into standard RL training.

```python
def train_with_lp_regularization(
    model,
    reference_model,
    dataset,
    config
):
    """
    RL training with low-probability token protection.
    """
    # Phase 1: Identify reasoning sparks
    print("Phase 1: Identifying reasoning sparks")

    # Collect initial rollouts
    rollouts = []
    for problem in dataset[:1000]:  # Sample for spark detection
        trace = model.generate(problem, max_tokens=500)
        solution = extract_solution(trace)
        is_correct = evaluate_correctness(solution, problem)
        rollouts.append({
            "trace": trace,
            "solution": solution,
            "is_correct": is_correct
        })

    detector = ReasoningSparkDetector(model, reference_model)
    reasoning_sparks = detector.identify_reasoning_sparks(
        [r["trace"] for r in rollouts],
        [r["solution"] for r in rollouts],
        [r["is_correct"] for r in rollouts]
    )
    print(f"Identified {len(reasoning_sparks)} reasoning sparks")

    # Phase 2: RL training with Lp-Reg
    print("\nPhase 2: RL training with low-probability regularization")
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-5)
    lp_regularizer = LowProbabilityRegularization(reference_model)

    for epoch in range(config.num_epochs):
        epoch_loss = 0

        for batch_idx, problem in enumerate(dataset):
            # Generate reasoning with current policy
            trace = model.generate(problem, max_tokens=500)
            solution = extract_solution(trace)

            # Evaluate reward
            is_correct = evaluate_correctness(solution, problem)
            reward = 1.0 if is_correct else -1.0

            # Get model logits and probabilities
            logits = model.get_logits_for_sequence(trace)
            model_dist = torch.softmax(logits, dim=-1)

            # Create proxy distribution for this sequence
            proxy_dist = create_proxy_distribution(
                logits,
                reasoning_sparks,
                noise_threshold=0.01
            )

            # Policy gradient loss
            log_prob = model.compute_log_prob(trace)
            pg_loss = -reward * log_prob

            # Lp-Reg loss: protect reasoning sparks
            reg_loss = lp_regularizer.compute_lp_reg_loss(
                model_dist,
                proxy_dist,
                reasoning_sparks,
                temperature=1.0,
                reg_weight=0.1
            )

            # Total loss: RL + regularization
            total_loss = pg_loss + reg_loss

            # Update
            optimizer.zero_grad()
            total_loss.backward()
            torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
            optimizer.step()

            epoch_loss += total_loss.item()

            if (batch_idx + 1) % 100 == 0:
                avg_loss = epoch_loss / (batch_idx + 1)
                print(f"Epoch {epoch}, Batch {batch_idx}: loss={avg_loss:.4f}")

    return model
```

### 5. Evaluation: Stability and Performance

Assess that model maintains exploration while improving correctness.

```python
def evaluate_lp_reg_training(model, benchmark_dataset, reference_model):
    """
    Evaluate exploration stability and performance.
    """
    results = {
        "accuracy": 0,
        "entropy": 0,
        "diversity": 0
    }

    correct = 0
    entropies = []
    solutions_set = set()

    for problem in benchmark_dataset:
        # Generate multiple samples to assess diversity
        traces = []
        for _ in range(5):
            trace = model.generate(problem, max_tokens=500, temperature=0.8)
            traces.append(trace)
            solution = extract_solution(trace)
            solutions_set.add(solution)

            # Check correctness
            if evaluate_correctness(solution, problem):
                correct += 1

        # Compute entropy of solutions for this problem
        solution_entropy = compute_entropy([extract_solution(t) for t in traces])
        entropies.append(solution_entropy)

    results["accuracy"] = correct / (len(benchmark_dataset) * 5) * 100
    results["entropy"] = np.mean(entropies)
    results["diversity"] = len(solutions_set)

    print(f"Accuracy: {results['accuracy']:.1f}%")
    print(f"Entropy: {results['entropy']:.3f}")
    print(f"Solution diversity: {results['diversity']}")

    return results
```

## Practical Guidance

**Hyperparameters:**
- **Noise threshold**: 0.01 (filter very rare tokens)
- **Spark correctness threshold**: 0.5 (keep tokens in correct solutions >50%)
- **Regularization weight**: 0.1 (soft constraint)
- **Temperature for soft distributions**: 1.0-2.0 (sharpness control)
- **Spark detection sample size**: 1000+ problems

**When to Use:**
- RL training on reasoning tasks (math, code, logic)
- Experiencing entropy collapse during training
- Want to preserve diverse solution paths
- Tasks have multiple valid approaches

**When NOT to Use:**
- Single-solution tasks where diversity not valued
- Simple supervised learning (not RL)
- Streaming inference where entropy control not critical
- Tasks where rare tokens are pure noise

## Reference

[Low-Probability Tokens Sustain Exploration in Reasoning RL](https://arxiv.org/abs/2510.03222) — arXiv:2510.03222

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.