Spaces:
Paused
Paused
Run 8: disable unlikeliness (β_rank=0.0) + keep β=0.04 + env-verified traces — root-cause fix for Run 7 R1 over-prediction
Browse files- tests/test_rewards.py +32 -29
- tools/fetch_run8.py +67 -0
- training/config.yaml +42 -46
- training/rewards.py +27 -1
tests/test_rewards.py
CHANGED
|
@@ -259,41 +259,44 @@ def test_wrappers_survive_trl_keyword_calling_convention():
|
|
| 259 |
# ─────────────────────────────────────────────────────────────────────────────
|
| 260 |
|
| 261 |
|
| 262 |
-
def
|
| 263 |
-
"""
|
| 264 |
-
|
| 265 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
pack = build_reward_pack(total_episodes=300)
|
| 267 |
-
pack.episode_counter[0] = 200 #
|
| 268 |
|
| 269 |
def raw_returning_spread(completions, **_):
|
| 270 |
-
# 4 rollouts with distinct positive rewards — classic GRPO group
|
| 271 |
return [1.0, 0.8, 0.6, 0.4]
|
| 272 |
|
| 273 |
wrapped = weighted_environmental_reward(raw_returning_spread, pack)
|
| 274 |
scores = wrapped(completions=["a", "b", "c", "d"])
|
| 275 |
|
| 276 |
-
#
|
| 277 |
-
#
|
| 278 |
-
#
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
#
|
| 282 |
-
|
| 283 |
-
# Bottom: 1.5 * 0.4 * 1.0 = 0.6
|
| 284 |
-
assert abs(scores[0] - 1.5 * 1.0 * 0.8125) < 1e-6, f"top score wrong: {scores[0]}"
|
| 285 |
-
assert abs(scores[3] - 1.5 * 0.4 * 1.0) < 1e-6, f"bottom score wrong: {scores[3]}"
|
| 286 |
-
unshaped_ratio = 1.0 / 0.4
|
| 287 |
-
shaped_ratio = scores[0] / scores[3]
|
| 288 |
-
assert shaped_ratio < unshaped_ratio, (
|
| 289 |
-
f"unlikeliness shaping failed: shaped ratio {shaped_ratio} >= unshaped {unshaped_ratio}"
|
| 290 |
-
)
|
| 291 |
|
| 292 |
|
| 293 |
-
def
|
| 294 |
-
"""
|
| 295 |
-
|
| 296 |
-
up-weight losses."""
|
| 297 |
pack = build_reward_pack(total_episodes=300)
|
| 298 |
pack.episode_counter[0] = 200
|
| 299 |
|
|
@@ -303,11 +306,11 @@ def test_unlikeliness_reward_skips_negative_samples():
|
|
| 303 |
wrapped = weighted_environmental_reward(raw, pack)
|
| 304 |
scores = wrapped(completions=["a", "b", "c", "d"])
|
| 305 |
|
| 306 |
-
#
|
| 307 |
-
assert scores[0]
|
| 308 |
-
# Negatives
|
| 309 |
for s in scores[1:]:
|
| 310 |
-
assert abs(s -
|
| 311 |
|
| 312 |
|
| 313 |
def test_r_level_bonus_applied_for_correct_high_r_predictions():
|
|
|
|
| 259 |
# ─────────────────────────────────────────────────────────────────────────────
|
| 260 |
|
| 261 |
|
| 262 |
+
def test_unlikeliness_reward_disabled_in_run_8():
|
| 263 |
+
"""Run 8: BETA_RANK is now 0.0 (disabled) because unlikeliness shaping
|
| 264 |
+
INVERTED the gradient signal for our classification-style task. Our
|
| 265 |
+
continuous partial-credit reward (level_accuracy × calibration) meant
|
| 266 |
+
top-reward-ranked samples = correct predictions, so the He et al.
|
| 267 |
+
penalty on top-ranked samples paid more for WRONG predictions.
|
| 268 |
+
|
| 269 |
+
With BETA_RANK=0.0, shaped rewards equal raw rewards (times the
|
| 270 |
+
schedule weight), so the gradient is clean.
|
| 271 |
+
"""
|
| 272 |
+
from training.rewards import BETA_RANK
|
| 273 |
+
assert BETA_RANK == 0.0, (
|
| 274 |
+
f"Expected BETA_RANK=0.0 in Run 8; got {BETA_RANK}. "
|
| 275 |
+
"If you re-enabled unlikeliness shaping, also re-validate that it "
|
| 276 |
+
"doesn't invert the gradient for classification-style rewards."
|
| 277 |
+
)
|
| 278 |
+
|
| 279 |
pack = build_reward_pack(total_episodes=300)
|
| 280 |
+
pack.episode_counter[0] = 200 # env weight = 1.5
|
| 281 |
|
| 282 |
def raw_returning_spread(completions, **_):
|
|
|
|
| 283 |
return [1.0, 0.8, 0.6, 0.4]
|
| 284 |
|
| 285 |
wrapped = weighted_environmental_reward(raw_returning_spread, pack)
|
| 286 |
scores = wrapped(completions=["a", "b", "c", "d"])
|
| 287 |
|
| 288 |
+
# With BETA_RANK=0.0 and no R-level bonus firing (no training_log exposed
|
| 289 |
+
# by the raw_fn), the wrapper is just: schedule_weight × raw_reward.
|
| 290 |
+
# Env weight = 1.5.
|
| 291 |
+
assert abs(scores[0] - 1.5 * 1.0) < 1e-6, f"top score wrong: {scores[0]}"
|
| 292 |
+
assert abs(scores[3] - 1.5 * 0.4) < 1e-6, f"bottom score wrong: {scores[3]}"
|
| 293 |
+
# Ratio of top:bottom preserved (no longer inverted by shaping)
|
| 294 |
+
assert abs(scores[0] / scores[3] - 1.0 / 0.4) < 1e-6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
|
| 296 |
|
| 297 |
+
def test_unlikeliness_reward_passes_negatives_unchanged():
|
| 298 |
+
"""With BETA_RANK=0.0, negative rewards flow through unchanged too
|
| 299 |
+
(previously shaping only affected positives; now nothing is shaped)."""
|
|
|
|
| 300 |
pack = build_reward_pack(total_episodes=300)
|
| 301 |
pack.episode_counter[0] = 200
|
| 302 |
|
|
|
|
| 306 |
wrapped = weighted_environmental_reward(raw, pack)
|
| 307 |
scores = wrapped(completions=["a", "b", "c", "d"])
|
| 308 |
|
| 309 |
+
# No penalty on top (BETA_RANK=0.0)
|
| 310 |
+
assert abs(scores[0] - 1.5 * 0.8) < 1e-6, f"top shouldn't be penalized now: {scores[0]}"
|
| 311 |
+
# Negatives still flow through
|
| 312 |
for s in scores[1:]:
|
| 313 |
+
assert abs(s - 1.5 * -0.1) < 1e-6, f"negative reward shaped unexpectedly: {s}"
|
| 314 |
|
| 315 |
|
| 316 |
def test_r_level_bonus_applied_for_correct_high_r_predictions():
|
tools/fetch_run8.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""One-shot script to pull Run 8 artifacts from HF Hub.
|
| 2 |
+
|
| 3 |
+
Run 8 root-cause fix:
|
| 4 |
+
BETA_RANK = 0.25 → 0.0 (disabled unlikeliness shaping).
|
| 5 |
+
|
| 6 |
+
Why: He et al. 2506.02355 designed unlikeliness reward for BINARY-reward
|
| 7 |
+
theorem proving. Our classification-style RLVR with partial-credit rewards
|
| 8 |
+
(level_accuracy × calibration ∈ [0,1]) INVERTED the gradient — GRPO paid
|
| 9 |
+
more for wrong R1 predictions than correct R2 predictions on db_snapshot
|
| 10 |
+
(Run 7 training log shows 0.773 vs 0.751).
|
| 11 |
+
|
| 12 |
+
Cross-reference: "Rewards as Labels: Revisiting RLVR from a Classification
|
| 13 |
+
Perspective" (arxiv 2602.05630) confirms GRPO's Gradient Misassignment in
|
| 14 |
+
Positives for classification tasks.
|
| 15 |
+
|
| 16 |
+
Everything else from Run 7 is preserved:
|
| 17 |
+
* β=0.04 KL (stabilized late drift)
|
| 18 |
+
* μ=2 PPO epochs
|
| 19 |
+
* 78 env-verified warmup traces
|
| 20 |
+
* 4 forced variants
|
| 21 |
+
* R-level balance bonus
|
| 22 |
+
|
| 23 |
+
Theory predictions:
|
| 24 |
+
* Eval accuracy: 46% (Run 7) → 85-92% (high confidence)
|
| 25 |
+
* R5 recall: preserved at ≥95%
|
| 26 |
+
* No R1 over-prediction in confusion matrix
|
| 27 |
+
* task_force_push_release recovered to R2
|
| 28 |
+
|
| 29 |
+
GUARDRAIL: if eval R5 recall < 95%, revert to Run 6.1 adapter.
|
| 30 |
+
"""
|
| 31 |
+
from __future__ import annotations
|
| 32 |
+
|
| 33 |
+
import os
|
| 34 |
+
import shutil
|
| 35 |
+
import subprocess
|
| 36 |
+
from huggingface_hub import snapshot_download
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
TARGET_DIR = "training_runs/run_8_disable_unlikeliness"
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def main() -> None:
|
| 43 |
+
if os.path.exists(TARGET_DIR):
|
| 44 |
+
shutil.rmtree(TARGET_DIR)
|
| 45 |
+
token = subprocess.check_output(["hf", "auth", "token"], text=True).strip()
|
| 46 |
+
path = snapshot_download(
|
| 47 |
+
repo_id="chane335/permanence-artifacts",
|
| 48 |
+
repo_type="dataset",
|
| 49 |
+
local_dir=TARGET_DIR,
|
| 50 |
+
token=token,
|
| 51 |
+
)
|
| 52 |
+
total = 0
|
| 53 |
+
for root, _dirs, files in os.walk(path):
|
| 54 |
+
for f in files:
|
| 55 |
+
rel = os.path.relpath(os.path.join(root, f), path)
|
| 56 |
+
if ".cache" in rel:
|
| 57 |
+
continue
|
| 58 |
+
size = os.path.getsize(os.path.join(root, f))
|
| 59 |
+
total += size
|
| 60 |
+
print(f" {size:>12,} bytes {rel}")
|
| 61 |
+
print(f"TOTAL: {total/1e6:.1f} MB")
|
| 62 |
+
print(f"\nCheck eval first: python -c \"import json; "
|
| 63 |
+
f"print(json.load(open('{TARGET_DIR}/eval/results.json')))\"")
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
if __name__ == "__main__":
|
| 67 |
+
main()
|
training/config.yaml
CHANGED
|
@@ -1,52 +1,51 @@
|
|
| 1 |
-
# PERMANENCE Training Config — Run
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
#
|
| 3 |
# Architecture: 4-stage pipeline (training/pipeline.py)
|
| 4 |
#
|
| 5 |
-
# Stage 1 — SFT on 78 tech+forced warmup traces × 10 epochs
|
| 6 |
-
#
|
| 7 |
-
# → gate
|
| 8 |
-
# Run 7 trace distribution: R1=22, R2=23, R3=3, R4=7, R5=23.
|
| 9 |
-
# Added 6 calibration traces: git_push_force → R2 (when nothing
|
| 10 |
-
# overwritten), git_push → R2, git_commit → R2, git_filter_branch
|
| 11 |
-
# → R4 (reflog preserves), fs_rm_rf → R4 (backup), db_truncate
|
| 12 |
-
# → R4 (snapshot). Fixes Run 6 failure: model conflated all git
|
| 13 |
-
# context with R4/R5 (task_force_push_release eval 6/6 predicted
|
| 14 |
-
# R4 when actual was R2) and all destructive DB ops with R5
|
| 15 |
-
# (37/41 actual R4 predicted as R5).
|
| 16 |
#
|
| 17 |
# Stage 2 — Format-coverage gate on 20 held-out prompts
|
| 18 |
-
# → artifacts/gate/status.json
|
| 19 |
# → gate: ≥80% of completions contain both tags
|
| 20 |
#
|
| 21 |
-
# Stage 3 — GRPO with
|
| 22 |
-
#
|
| 23 |
-
#
|
| 24 |
-
#
|
| 25 |
-
#
|
| 26 |
-
# * Unlikeliness
|
| 27 |
-
# *
|
| 28 |
-
# correct rare predictions. R4 → +0.1, R5 → +0.2.
|
| 29 |
-
# * Curriculum introduces forced-outcome variants:
|
| 30 |
-
# eps 0– 50: standard tasks only (baseline)
|
| 31 |
-
# eps 51–150: 50% forced (break local optimum)
|
| 32 |
-
# eps 151–end: 70% forced (full spectrum required)
|
| 33 |
-
# * μ=2 inner PPO-style updates per generation batch
|
| 34 |
-
#
|
| 35 |
-
# Length auto-abort if mean completion > 1000 chars for 3 windows
|
| 36 |
-
# → artifacts/grpo/adapter/ + training_log.json
|
| 37 |
#
|
| 38 |
# Stage 4 — Held-out eval comparing scripted / SFT-only / GRPO-trained
|
| 39 |
-
# → artifacts/eval/results.json + comparison.csv
|
| 40 |
#
|
| 41 |
-
# Run
|
| 42 |
-
# * Eval accuracy:
|
| 43 |
-
# *
|
| 44 |
-
# *
|
| 45 |
-
# *
|
| 46 |
-
# *
|
|
|
|
|
|
|
| 47 |
#
|
| 48 |
-
# GUARDRAIL: if eval
|
| 49 |
-
# Run 6.1 adapter and ship that instead.
|
| 50 |
#
|
| 51 |
# Constraints:
|
| 52 |
# - T4 GPU (16 GB). Llama-3.2-3B in 4-bit Unsloth + LoRA fits under 12 GB.
|
|
@@ -57,12 +56,10 @@ model_name: unsloth/Llama-3.2-3B-Instruct-bnb-4bit
|
|
| 57 |
total_episodes: 300
|
| 58 |
group_size: 4
|
| 59 |
learning_rate: 4.0e-5
|
| 60 |
-
|
| 61 |
-
#
|
| 62 |
-
#
|
| 63 |
-
#
|
| 64 |
-
# "git_commit R2 → R4" collapse that Run 6 exhibited (100% correct through
|
| 65 |
-
# step 135, then degrading to 0-30% correct by step 300).
|
| 66 |
kl_coefficient: 0.04
|
| 67 |
gradient_clip: 1.0
|
| 68 |
lora_r: 16
|
|
@@ -76,8 +73,7 @@ format_reward_cutoff: 300
|
|
| 76 |
eval_episodes: 36
|
| 77 |
eval_seed_offset: 50000
|
| 78 |
|
| 79 |
-
#
|
| 80 |
-
# 2506.02355 recommendation. TRL default is 1. Range 1..4 safe; 2 sweet spot.
|
| 81 |
ppo_epochs: 2
|
| 82 |
|
| 83 |
# Domain filter: devtools | meridian | (empty for mixed)
|
|
|
|
| 1 |
+
# PERMANENCE Training Config — Run 8 (disable unlikeliness shaping)
|
| 2 |
+
#
|
| 3 |
+
# Run 8 Root-cause fix: BETA_RANK = 0.0 (disable unlikeliness reward).
|
| 4 |
+
#
|
| 5 |
+
# Diagnosis from Run 7 training log:
|
| 6 |
+
# Our reward function gives partial credit for wrong-but-close predictions
|
| 7 |
+
# (level_accuracy × calibration ∈ [0,1]). The He et al. unlikeliness reward
|
| 8 |
+
# was designed for BINARY-reward theorem proving. When applied to our
|
| 9 |
+
# continuous-reward classification task, it PENALIZES correct high-reward
|
| 10 |
+
# predictions relative to wrong-but-still-positive ones. Empirical proof:
|
| 11 |
+
# Run 7: db_snapshot (actual R2) predicted R1 → avg reward 0.773
|
| 12 |
+
# db_snapshot (actual R2) predicted R2 → avg reward 0.751
|
| 13 |
+
# GRPO learned to predict R1 because the unlikeliness shaping paid more
|
| 14 |
+
# for the WRONG answer. Eval accuracy collapsed 75% → 46%.
|
| 15 |
+
#
|
| 16 |
+
# Cross-reference: "Rewards as Labels: Revisiting RLVR from a Classification
|
| 17 |
+
# Perspective" (arxiv 2602.05630) — GRPO already has "Gradient Misassignment
|
| 18 |
+
# in Positives" for classification tasks; unlikeliness shaping amplifies it.
|
| 19 |
#
|
| 20 |
# Architecture: 4-stage pipeline (training/pipeline.py)
|
| 21 |
#
|
| 22 |
+
# Stage 1 — SFT on 78 env-verified tech+forced warmup traces × 10 epochs
|
| 23 |
+
# R1=22, R2=23, R3=3, R4=7, R5=23
|
| 24 |
+
# → gate coverage 100% (Run 7 proved this works)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
#
|
| 26 |
# Stage 2 — Format-coverage gate on 20 held-out prompts
|
|
|
|
| 27 |
# → gate: ≥80% of completions contain both tags
|
| 28 |
#
|
| 29 |
+
# Stage 3 — GRPO with preserved Run 6/7 innovations:
|
| 30 |
+
# * β = 0.04 KL (kept from Run 7 — stabilized late drift)
|
| 31 |
+
# * μ = 2 inner PPO epochs (kept)
|
| 32 |
+
# * Forced variants curriculum (kept — broke R2-only)
|
| 33 |
+
# * R-level balance bonus (+0.1 per R-level for correct R4/R5)
|
| 34 |
+
# * Unlikeliness β_rank = 0.0 (DISABLED — Run 8 root-cause fix)
|
| 35 |
+
# * Length auto-abort if mean > 1000 chars for 3 windows
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
#
|
| 37 |
# Stage 4 — Held-out eval comparing scripted / SFT-only / GRPO-trained
|
|
|
|
| 38 |
#
|
| 39 |
+
# Run 8 theory predictions:
|
| 40 |
+
# * Eval accuracy: 46% (Run 7) → 85-92% (high confidence, mechanism clear)
|
| 41 |
+
# * R5 recall: preserved at ≥95% (forced variants still drive R5 signal)
|
| 42 |
+
# * Mean reward: 0.64 (Run 7) → 0.65-0.75 (small improvement, same training)
|
| 43 |
+
# * No R1 over-prediction (smoking-gun reward inversion is gone)
|
| 44 |
+
# * No R4/R5 conflation regression (β=0.04 still holds)
|
| 45 |
+
# * task_force_push_release: correct R2 on all 6 scenarios
|
| 46 |
+
# * task_schema_migration: correct R2 on all 6 scenarios
|
| 47 |
#
|
| 48 |
+
# GUARDRAIL: if eval R5 recall < 95%, revert to Run 6.1 adapter.
|
|
|
|
| 49 |
#
|
| 50 |
# Constraints:
|
| 51 |
# - T4 GPU (16 GB). Llama-3.2-3B in 4-bit Unsloth + LoRA fits under 12 GB.
|
|
|
|
| 56 |
total_episodes: 300
|
| 57 |
group_size: 4
|
| 58 |
learning_rate: 4.0e-5
|
| 59 |
+
|
| 60 |
+
# Run 7: β doubled 0.02 → 0.04 (TRL default) — stabilized late-training drift.
|
| 61 |
+
# Run 8: kept at 0.04 — this change is proven to help, independent of the
|
| 62 |
+
# unlikeliness bug.
|
|
|
|
|
|
|
| 63 |
kl_coefficient: 0.04
|
| 64 |
gradient_clip: 1.0
|
| 65 |
lora_r: 16
|
|
|
|
| 73 |
eval_episodes: 36
|
| 74 |
eval_seed_offset: 50000
|
| 75 |
|
| 76 |
+
# μ=2 inner PPO-style updates per generation batch. Kept from Run 7.
|
|
|
|
| 77 |
ppo_epochs: 2
|
| 78 |
|
| 79 |
# Domain filter: devtools | meridian | (empty for mixed)
|
training/rewards.py
CHANGED
|
@@ -58,7 +58,33 @@ CONFIDENCE_RE = re.compile(r"confidence=[\"']([0-9.]+)[\"']", re.IGNORECASE)
|
|
| 58 |
THINKING_RE = re.compile(r"<thinking>.*?</thinking>", re.IGNORECASE | re.DOTALL)
|
| 59 |
|
| 60 |
# Run 6 hyperparameters — from He et al. 2506.02355
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
R_LEVEL_BONUS_PER_LEVEL = 0.1 # Additive bonus per R-level of correct rare prediction
|
| 63 |
|
| 64 |
|
|
|
|
| 58 |
THINKING_RE = re.compile(r"<thinking>.*?</thinking>", re.IGNORECASE | re.DOTALL)
|
| 59 |
|
| 60 |
# Run 6 hyperparameters — from He et al. 2506.02355
|
| 61 |
+
#
|
| 62 |
+
# Run 8 update: BETA_RANK set to 0.0 (disabled).
|
| 63 |
+
#
|
| 64 |
+
# Research basis: The unlikeliness-reward technique in He et al. was designed
|
| 65 |
+
# for FORMAL THEOREM PROVING with BINARY rewards (proof works / doesn't).
|
| 66 |
+
# Our task is a classification-style RLVR with CONTINUOUS partial-credit
|
| 67 |
+
# rewards (level_accuracy × calibration in [0, 1]). Applying unlikeliness
|
| 68 |
+
# to our continuous-reward setting has the opposite of the intended effect:
|
| 69 |
+
# it penalizes correct, confident predictions (high reward) relative to
|
| 70 |
+
# wrong-but-close predictions (lower but still positive reward).
|
| 71 |
+
#
|
| 72 |
+
# Evidence from Run 7 training log:
|
| 73 |
+
# db_snapshot (actual R2) with predicted R1 → avg reward 0.773
|
| 74 |
+
# db_snapshot (actual R2) with predicted R2 → avg reward 0.751
|
| 75 |
+
# The unlikeliness shaping inverted the gradient: R1 paid MORE than R2.
|
| 76 |
+
# GRPO learned to predict R1 and eval accuracy dropped to 46%.
|
| 77 |
+
#
|
| 78 |
+
# Cross-reference: "Rewards as Labels: Revisiting RLVR from a Classification
|
| 79 |
+
# Perspective" (arxiv 2602.05630) identifies GRPO's "Gradient Misassignment
|
| 80 |
+
# in Positives" for classification tasks. Unlikeliness shaping amplifies
|
| 81 |
+
# this pathology rather than fixing it in our setting.
|
| 82 |
+
#
|
| 83 |
+
# Setting BETA_RANK=0.0 disables the shaping entirely. The forced variants
|
| 84 |
+
# + R-level balance bonus still address the Run 5 R2-only collapse. Our
|
| 85 |
+
# classification-style reward already has a clear gradient signal without
|
| 86 |
+
# needing unlikeliness to surface rare samples.
|
| 87 |
+
BETA_RANK = 0.0 # Run 8: disabled (was 0.25 in Runs 6 and 7)
|
| 88 |
R_LEVEL_BONUS_PER_LEVEL = 0.1 # Additive bonus per R-level of correct rare prediction
|
| 89 |
|
| 90 |
|