Skip to content
Back to skills

Reinforcement Mid Training

ASecurity

Add an intermediate RL stage between pretraining and post-training using dynamic token budgeting, curriculum sampling, and dual training. Trigger: reduce reasoning steps while maintaining or improving performance in post-training.

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 9, 2026
developmentpythonperformance

Works with

  • cli

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill reinforcement-mid-training --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Reinforcement Mid Training?

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

Security grade badge for Reinforcement Mid Training
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-reinforcement-mid-training/badge)](https://www.skillsdirectory.com/skills/adu2021-reinforcement-mid-training)

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: reinforcement-mid-training
title: "Reinforcement Mid-Training: Intermediate Optimization Between Pretraining and Post-Training"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: https://arxiv.org/abs/2509.24375
keywords: [intermediate-training, reinforcement-learning, token-optimization, curriculum-learning, reasoning]
description: "Add an intermediate RL stage between pretraining and post-training using dynamic token budgeting, curriculum sampling, and dual training. Trigger: reduce reasoning steps while maintaining or improving performance in post-training."
---

# Reinforcement Mid-Training (RMT): Three-Stage LLM Development

## Core Concept

Standard LLM development has two stages: pretraining (next-token prediction) and post-training (instruction-tuning + RL). RMT inserts a **critical middle stage** that applies reinforcement learning to discourage unnecessary reasoning steps while focusing training on high-value tokens. This achieves up to 64.91% performance improvement while using only 21% of reasoning tokens.

The key insight: Not all tokens contribute equally to performance. Mid-training learns to allocate compute efficiently before the model develops bad reasoning habits during post-training.

## Architecture Overview

- **Dynamic Token Budgeting**: Learns when to stop generating reasoning and produce answers
- **Curriculum-Based Sampling**: Progressive training from simple to complex tokens
- **Dual Training Strategy**: Combines RL with next-token prediction for token importance weighting
- **Three-Stage Pipeline**: Pretraining → Mid-Training (RL) → Post-Training
- **Efficiency Gains**: 21% of tokens for equivalent or better performance

## Implementation Steps

### 1. Prepare Mid-Training Data and Setup

Mid-training requires a dataset with reasoning-intensive tasks (math, code) and a clean base model from pretraining.

```python
class MidTrainingConfig:
    # Model and data
    base_model_path = "llama-7b-pretrained"
    mid_training_dataset = "math_code_reasoning"  # MATH, GSM8K, MBPP
    num_examples = 50000

    # Training schedule
    num_epochs = 3
    warmup_steps = 1000
    total_steps = 100000

    # Token budgeting
    max_reasoning_tokens = 4096  # Hard limit on thinking
    reward_for_shorter_reasoning = 0.1  # Penalize verbose thinking

    # Curriculum
    difficulty_stages = [
        {"name": "easy", "examples": 10000, "curriculum_weight": 0.5},
        {"name": "medium", "examples": 25000, "curriculum_weight": 0.3},
        {"name": "hard", "examples": 15000, "curriculum_weight": 0.2},
    ]

    # RL settings
    lr = 1e-5
    rl_weight = 0.7  # RL loss weight vs. supervised loss
    supervised_weight = 0.3
```

### 2. Implement Dynamic Token Budgeting

Create a mechanism to reward efficient reasoning and penalize excessive token generation.

```python
class TokenBudgetingReward:
    def __init__(self, max_tokens=4096, target_ratio=0.5):
        self.max_tokens = max_tokens
        self.target_ratio = target_ratio  # Ideally use 50% of budget

    def compute_reward(self, thinking_tokens, final_answer_tokens, is_correct):
        """
        Reward correctness, but penalize verbose thinking.

        Args:
            thinking_tokens: Number of reasoning tokens generated
            final_answer_tokens: Number of tokens in final answer
            is_correct: Boolean whether answer is correct

        Returns:
            Scalar reward signal
        """
        # Base correctness reward
        correctness_reward = 1.0 if is_correct else -1.0

        # Efficiency bonus: reward using <50% of budget
        efficiency_ratio = thinking_tokens / self.max_tokens
        efficiency_bonus = 0.5 if efficiency_ratio < self.target_ratio else -0.2

        # Penalize excessive reasoning
        if thinking_tokens > self.max_tokens:
            excessive_penalty = -0.5
        else:
            excessive_penalty = 0

        # Combined reward
        total_reward = (
            correctness_reward +
            0.3 * efficiency_bonus +
            excessive_penalty
        )

        return total_reward

    def record_trajectory(self, problem, thinking, answer, is_correct):
        """Log a trajectory with token counts and correctness."""
        thinking_tokens = len(thinking.split())
        answer_tokens = len(answer.split())

        reward = self.compute_reward(
            thinking_tokens,
            answer_tokens,
            is_correct
        )

        return {
            "problem": problem,
            "thinking": thinking,
            "answer": answer,
            "thinking_tokens": thinking_tokens,
            "answer_tokens": answer_tokens,
            "is_correct": is_correct,
            "reward": reward
        }
```

### 3. Implement Curriculum-Based Sampling

Start with easy problems and progressively increase difficulty. This helps the model learn efficient reasoning on simpler tasks before tackling complex ones.

```python
class CurriculumSampler:
    def __init__(self, dataset, config):
        self.dataset = dataset
        self.config = config
        self.current_stage = 0
        self.stage_step = 0

    def sample_batch(self, batch_size):
        """
        Sample a batch weighted by curriculum.
        """
        # Determine current difficulty stage based on training progress
        stage_config = self.config.difficulty_stages[self.current_stage]

        # Sample from current stage with high probability
        # Sample from adjacent stages with lower probability
        difficulties = ["easy", "medium", "hard"]

        if self.current_stage == 0:
            difficulty_weights = [0.8, 0.2, 0.0]
        elif self.current_stage == 1:
            difficulty_weights = [0.2, 0.6, 0.2]
        else:
            difficulty_weights = [0.0, 0.3, 0.7]

        # Weighted sampling
        batch = []
        for _ in range(batch_size):
            difficulty = np.random.choice(
                difficulties,
                p=difficulty_weights
            )
            example = self.dataset.sample_by_difficulty(difficulty)
            batch.append(example)

        # Progress through stages
        self.stage_step += 1
        if self.stage_step > stage_config.get("duration_steps", 30000):
            self.current_stage = min(self.current_stage + 1, 2)
            self.stage_step = 0

        return batch

    def get_curriculum_weight(self):
        """Return curriculum weight for loss computation."""
        return self.config.difficulty_stages[self.current_stage]["curriculum_weight"]
```

### 4. Implement Dual Training (RL + Supervised)

Combine RL losses (based on correctness) with supervised losses (predicting important tokens).

```python
def compute_mid_training_loss(
    model,
    batch,
    token_budgeter,
    curriculum_weight,
    rl_weight=0.7,
    supervised_weight=0.3
):
    """
    Compute combined RL and supervised loss for mid-training.

    Args:
        model: LLM to train
        batch: List of training examples
        token_budgeter: Reward computer
        curriculum_weight: Importance weight from curriculum

    Returns:
        Scalar loss value
    """
    total_loss = 0
    batch_size = len(batch)

    for example in batch:
        # Generate thinking and answer
        output = model.generate(
            example["problem"],
            max_thinking_tokens=4096,
            return_intermediate=True
        )

        thinking = output["thinking"]
        answer = output["answer"]

        # Evaluate correctness
        is_correct = evaluate_answer(answer, example["ground_truth"])

        # Compute reward (RL component)
        reward = token_budgeter.compute_reward(
            len(thinking.split()),
            len(answer.split()),
            is_correct
        )

        log_prob = model.compute_log_prob(thinking + answer)

        # RL loss: policy gradient
        rl_loss = -reward * log_prob

        # Supervised loss: predict important tokens
        # Identify "important" tokens (problem-solving steps, key insights)
        important_tokens = identify_important_tokens(
            thinking,
            example["solution_tokens"]
        )

        supervised_loss = compute_token_importance_loss(
            model,
            thinking,
            important_tokens
        )

        # Combine losses with curriculum weight
        combined_loss = (
            rl_weight * rl_loss +
            supervised_weight * supervised_loss
        ) * curriculum_weight

        total_loss += combined_loss

    return total_loss / batch_size
```

### 5. Full Mid-Training Loop

Orchestrate the three-component training process.

```python
def train_mid_training(
    model,
    dataset,
    config,
    evaluation_dataset=None
):
    """
    Execute reinforcement mid-training.

    Args:
        model: Pretrained base model
        dataset: Training examples with reasoning and answers
        config: MidTrainingConfig instance
        evaluation_dataset: Optional validation set

    Returns:
        Model after mid-training, loss history
    """
    optimizer = torch.optim.Adam(model.parameters(), lr=config.lr)
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
        optimizer,
        T_max=config.total_steps
    )

    token_budgeter = TokenBudgetingReward(
        max_tokens=config.max_reasoning_tokens
    )
    curriculum_sampler = CurriculumSampler(dataset, config)

    loss_history = []
    step = 0

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

        for batch_idx in range(config.total_steps // 32):  # Batch size 32
            # Sample batch from curriculum
            batch = curriculum_sampler.sample_batch(batch_size=32)
            curriculum_weight = curriculum_sampler.get_curriculum_weight()

            # Compute loss
            loss = compute_mid_training_loss(
                model,
                batch,
                token_budgeter,
                curriculum_weight,
                rl_weight=config.rl_weight,
                supervised_weight=config.supervised_weight
            )

            # Backward pass
            optimizer.zero_grad()
            loss.backward()
            torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
            optimizer.step()
            scheduler.step()

            epoch_loss += loss.item()
            num_batches += 1
            step += 1

            # Logging
            if step % 100 == 0:
                avg_loss = epoch_loss / num_batches
                loss_history.append(avg_loss)
                print(f"Step {step}: loss={avg_loss:.4f}, "
                      f"curriculum_stage={curriculum_sampler.current_stage}")

            # Evaluation
            if evaluation_dataset and step % 5000 == 0:
                eval_metrics = evaluate_on_benchmark(
                    model,
                    evaluation_dataset,
                    metrics=["accuracy", "avg_reasoning_tokens"]
                )
                print(f"Eval at step {step}: {eval_metrics}")

    return model, loss_history
```

## Practical Guidance

**Hyperparameters:**
- **Max reasoning tokens**: 4096 (adapt to task complexity)
- **Target ratio for efficiency**: 0.5 (aim for 50% of budget)
- **RL loss weight**: 0.7 (emphasize correct reasoning)
- **Supervised weight**: 0.3 (maintain token prediction capability)
- **Curriculum duration**: 30K-50K steps per stage

**When to Use:**
- Developing reasoning models (math, code, logic)
- Want to reduce inference cost while maintaining quality
- Have access to reasoning datasets (MATH, GSM8K, MBPP)
- Pre-training already complete, before post-training

**When NOT to Use:**
- Single-turn generation tasks without reasoning
- Instruction-tuning directly from pretrained (skip mid-training)
- Limited compute for three-stage training pipeline
- Tasks where all tokens are equally important

## Reference

[Reinforcement Mid-Training: Intermediate Optimization Between Pretraining and Post-Training](https://arxiv.org/abs/2509.24375) — arXiv:2509.24375

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.