Skip to content
Back to skills

F Grpo Focal Policy Optimization

ASecurity

Prevent policy collapse onto common solutions during reinforcement learning by applying difficulty-aware focal weighting to gradient contributions, maintaining diversity across solution modes while preserving performance.

  • 6 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added September 9, 2026
ai-agentspythonperformance

Works with

  • cli

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill f-grpo-focal-policy-optimization --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of F Grpo Focal Policy Optimization?

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

Security grade badge for F Grpo Focal Policy Optimization
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-f-grpo-focal-policy-optimization/badge)](https://www.skillsdirectory.com/skills/adu2021-f-grpo-focal-policy-optimization)

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: f-grpo-focal-policy-optimization
title: "F-GRPO: Don't Let Your Policy Learn the Obvious and Forget the Rare"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2602.06717"
keywords: [Policy Optimization, Diversity, Rare Solution Mining, RL Verifiable Rewards, Focal Weighting]
description: "Prevent policy collapse onto common solutions during reinforcement learning by applying difficulty-aware focal weighting to gradient contributions, maintaining diversity across solution modes while preserving performance."
---

# F-GRPO: Don't Let Your Policy Learn the Obvious and Forget the Rare

## Problem Context

Reinforcement learning with verifiable rewards (RLVR) for language models exhibits distribution sharpening at intermediate group sizes. Policies improve pass@1 (best single solution) but degrade pass@256 (solution diversity), indicating concentration onto a narrow set of solutions. This erases rare but valuable solutions, reducing the value of the learned model for exploring multiple reasoning paths.

## Core Concept

F-GRPO applies [focal weighting, difficulty-aware scaling, group-relative advantage] to address this phenomenon. The insight is that distribution collapse peaks at intermediate group sizes due to how probability mass redistributes. A single scalar multiplier per prompt down-weights high-success cases where concentration pressure peaks, preserving rare solutions without additional compute.

## Architecture Overview

- **Theoretical foundation**: Closed-form tail-miss probability showing non-monotonic dependence on group size
- **Focal weight function**: g(x) = (1 − μ̂_pos(x))^γ scaling advantage contributions
- **Group-relative optimization**: Asymmetric pressure preserving diversity at specific group sizes
- **Hyperparameter**: Single γ (focal strength, typically 0.5-1.0) with intuitive effects
- **Integration**: Drop-in modification to GRPO, DAPO, CISPO without new networks

## Implementation

### Step 1: Estimate success probability per prompt

Compute empirical pass rate (probability of getting any correct solution) for each prompt during training.

```python
# Estimate success probability
def estimate_success_probability(
    prompt_ids, group_results, smoothing_alpha=0.5
):
    """
    Estimate μ_pos(x): probability of success for each prompt.
    Smooth with alpha for stability on small groups.
    """
    success_probs = {}

    for prompt_id in set(prompt_ids):
        # Get all results for this prompt
        prompt_results = [
            r for r, p in zip(group_results, prompt_ids)
            if p == prompt_id
        ]

        # Count correct solutions (non-zero reward)
        num_correct = sum(1 for r in prompt_results if r > 0)
        total = len(prompt_results)

        # Estimate with smoothing
        raw_prob = num_correct / max(total, 1)
        smoothed_prob = (num_correct + smoothing_alpha) / (total + 2 * smoothing_alpha)

        success_probs[prompt_id] = smoothed_prob

    return success_probs
```

### Step 2: Compute focal weights for each prompt

Calculate difficulty-aware weights based on estimated success probability. Down-weight high-success prompts where concentration risk is highest.

```python
# Focal weighting
def compute_focal_weights(success_probs, gamma=1.0):
    """
    Compute focal weights: g(x) = (1 - μ_pos(x))^gamma
    Higher gamma → stronger down-weighting of easy prompts
    """
    focal_weights = {}

    for prompt_id, prob in success_probs.items():
        # Focal weight: prioritizes hard prompts
        weight = (1.0 - prob) ** gamma
        focal_weights[prompt_id] = weight

    return focal_weights
```

### Step 3: Apply focal weighting to advantage calculation

Modify the advantage computation in GRPO to include focal weights. This directly affects gradient magnitudes.

```python
# Modified advantage with focal weighting
def compute_focal_advantages(
    log_probs, rewards, prompt_ids, focal_weights,
    group_size=8
):
    """
    Compute GRPO advantages with focal weighting.
    F-GRPO advantage: Â^F-GRPO = g(x) * Â^GRPO
    """
    # First compute standard GRPO advantages
    batch_size = len(log_probs)
    num_groups = batch_size // group_size

    standard_advantages = []

    for group_idx in range(num_groups):
        group_start = group_idx * group_size
        group_end = (group_idx + 1) * group_size

        group_rewards = rewards[group_start:group_end]
        group_probs = log_probs[group_start:group_end]

        # Compute per-token advantage within group
        mean_reward = group_rewards.mean()

        for i in range(group_size):
            advantage = group_rewards[i] - mean_reward
            standard_advantages.append(advantage)

    # Apply focal weights
    focal_advantages = []
    for adv, prompt_id in zip(standard_advantages, prompt_ids):
        weight = focal_weights.get(prompt_id, 1.0)
        focal_adv = weight * adv
        focal_advantages.append(focal_adv)

    return torch.tensor(focal_advantages)
```

### Step 4: Integrate into GRPO training step

Replace standard advantage computation with focal advantages in the main training loop.

```python
# GRPO training with focal weighting
def grpo_step_with_focal(
    model, batch_prompts, group_size=8, gamma=1.0,
    optimizer=None, clip_ratio=0.2
):
    """
    Single GRPO training step with focal weighting.
    """
    # Generate responses
    responses = []
    log_probs_list = []

    for prompt in batch_prompts:
        response, log_prob = model.generate_with_logprobs(
            prompt, max_tokens=200
        )
        responses.append(response)
        log_probs_list.append(log_prob)

    # Compute rewards (assuming verifier available)
    rewards = []
    for response in responses:
        reward = verifier(response)
        rewards.append(reward)

    rewards = torch.tensor(rewards)

    # Estimate success probability per prompt
    prompt_ids = list(range(len(batch_prompts)))  # Simplification
    success_probs = estimate_success_probability(
        prompt_ids, rewards.tolist()
    )

    # Compute focal weights
    focal_weights = compute_focal_weights(success_probs, gamma=gamma)

    # Compute advantages with focal weighting
    log_probs = torch.stack(log_probs_list)
    focal_advantages = compute_focal_advantages(
        log_probs, rewards, prompt_ids, focal_weights,
        group_size=group_size
    )

    # Standard GRPO clipping objective
    log_prob_ratio = log_probs - log_probs.detach()
    clipped_ratio = torch.clamp(
        torch.exp(log_prob_ratio), 1 - clip_ratio, 1 + clip_ratio
    )

    loss = -torch.min(
        log_prob_ratio * focal_advantages,
        clipped_ratio * focal_advantages
    ).mean()

    if optimizer is not None:
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    return loss.item()
```

### Step 5: Monitor diversity metrics during training

Track pass@k metrics to verify that focal weighting preserves solution diversity.

```python
# Diversity monitoring
def compute_pass_at_k_metrics(
    model, test_prompts, verifier, k_values=[1, 8, 256],
    num_samples_per_prompt=256
):
    """
    Compute pass@k: probability of having at least one correct solution
    in k samples per prompt.
    """
    results = {f'pass@{k}': [] for k in k_values}

    for prompt in test_prompts:
        samples = []

        for _ in range(num_samples_per_prompt):
            response = model.generate(prompt, max_tokens=200)
            is_correct = verifier(response)
            samples.append(is_correct)

        for k in k_values:
            # Pass@k: has at least one correct in first k
            has_correct = any(samples[:k])
            results[f'pass@{k}'].append(float(has_correct))

    # Average over prompts
    final_results = {
        k: sum(v) / len(v) for k, v in results.items()
    }

    return final_results
```

## Practical Guidance

**When to use**: Reasoning tasks (math, code, logic) where solution diversity matters for downstream use (ensemble, reranking, exploration). Less critical for single-solution tasks (generation, summarization).

**Hyperparameters**:
- **γ (focal strength)**: 0.5 (mild) to 2.0 (strong)
  - γ=0.5: gentle diversity preservation
  - γ=1.0: balanced (recommended baseline)
  - γ>1.5: aggressive diversity, may hurt pass@1
- **Group size**: Typically 4-8; focal weighting effects stronger at 8-16
- **Smoothing alpha**: 0.5-1.0 for probability estimation stability

**Tuning guidance**:
1. Measure baseline pass@1 and pass@256 without focal weighting
2. Apply γ=1.0 and evaluate; if pass@1 drops >1%, reduce γ
3. If pass@256 still dropping, increase γ slightly
4. Use pass@256 / pass@1 ratio to track diversity relative to quality

**Common pitfalls**:
- Focal weights computed with insufficient samples; use averaging over recent batches
- Over-aggressive γ (>1.5) hurts quality; start conservative
- Forgetting to smooth success probabilities; sparse data leads to unstable weights
- Not evaluating on test set; training pass@256 may not match test

**Scaling**: Negligible computational overhead; single scalar multiplication per prompt. Effective across model sizes (1B-70B parameters) and group sizes (4-256).

## Reference

Paper: https://arxiv.org/abs/2602.06717
Code: Available at author's repository
Related work: GRPO, policy divergence, solution diversity in RL
Metrics: pass@k evaluation, diversity-quality tradeoffs

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.