Skip to content

Generalize gradient flow probe to any experiment config - #128

Merged
alexkroman merged 4 commits into
mainfrom
claude/admiring-dijkstra-ufn5bb
Oct 8, 2026
Merged

alexkroman merged 4 commits into
mainfrom
claude/admiring-dijkstra-ufn5bb

Conversation

@alexkroman

Copy link
Copy Markdown
Owner

Summary

Refactors the gradient flow debugging script to work with any experiment configuration instead of being hardcoded to embedded.yaml. The script now accepts an --experiment flag and uses the same config composition and model building logic as the training pipeline.

Key Changes

scripts/debug/check_gradient_flow.py

  • Generalized config loading: Replaced hardcoded embedded.yaml reading with load_experiment_config() that composes config.yaml + experiment overrides using Hydra, matching the trainer's approach
  • Unified model building: Now uses build_asr_config() from scripts/train.py instead of manually constructing ASRConfig, ensuring the probe uses identical freeze settings and configuration as training
  • Real training collator: Replaced hand-built synthetic batch with DataCollator from scripts/train_collator.py, eliminating divergence between probe and actual training data flow
  • Extended knob tracking: Added encoder_learning_rate and encoder_weight_decay to the training knobs dictionary
  • Simplified gradient norm computation: Uses torch.nn.utils.get_total_norm() instead of manual L2 norm calculation
  • Chat template consistency: Calls disable_chat_template_thinking() before collation to match training setup
  • Command-line interface: Added --experiment parameter (defaults to stage_1) via Typer

tests/test_check_gradient_flow.py (new)

  • Added comprehensive test suite covering:
    • Gradient norm computation correctness
    • Config composition supplies trainer knobs
    • Synthetic batch uses real training collator
    • Full decoder fine-tune passes gradient flow checks

Supporting Changes

  • scripts/train.py: Added get_token() import for Hub token preflight checks
  • tiny_audio/asr_modeling.py: Refactored generate() to fold generation flags into a deepcopied generation_config instead of passing alongside it, addressing transformers v5 deprecation warnings
  • scripts/eval/audio.py: Extracted to_mono() helper for consistent multichannel audio handling; updated prepare_wav_bytes() to use real training collator pattern
  • scripts/deploy/remote_scripts.py: Added shlex quoting for all caller-supplied values (tokens, W&B IDs, Hydra overrides) to prevent shell expansion
  • scripts/analysis/metrics.py: Replaced per-utterance jiwer.process_words() with word_errors() Levenshtein distance for efficiency
  • scripts/eval/formatting.py: Fixed alignment to skip punctuation-only tokens, preventing spurious word pairings
  • Test updates: Added tests for column ordering preservation, dataset expansion, bash value escaping, and torchcodec stereo handling

Notable Implementation Details

  • The probe now runs the exact same DataCollator configuration as training, including left-padding of text and proper <audio> token emission
  • Config composition forces attn_implementation=eager to avoid flash-attn dependency while maintaining gradient flow independence from attention implementation
  • Gradient flow diagnostics remain unchanged; only the setup and batch construction were unified with training

https://claude.ai/code/session_014D4gdQCgNfW9ZWGdgMuEVg

claude added 4 commits October 8, 2026 21:57
- formatting: align on key lists with Levenshtein.opcodes so punctuation-only
  tokens no longer shift every later pair (corrupted case/punct metrics)
- audio: word-bounded spelling fixes ("overall rights" no longer becomes
  "overalrights"); torchcodec audio no longer round-trips through PCM_16;
  shared to_mono downmix (fixes channels-first stereo written as n channels)
- swift_sdk: reuse prepare_wav_bytes instead of a parallel WAV writer
- metrics: per-utterance WER via word_errors; scipy.stats.bootstrap for
  paired_bootstrap_delta (same CI for the same seed)
- speaker_metrics: rapidfuzz.process.cdist for the cpWER cost matrix
- common: drop unreachable subsequence fallback in entity_in_text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D4gdQCgNfW9ZWGdgMuEVg
- generate/generate_streaming: fold kwargs into a config copy via
  GenerationConfig.update (also stops v5's deprecation warnings)
- save_pretrained: set base_model_name_or_path on the PEFT config before
  saving instead of rewriting adapter_config.json afterwards
- asr_config: AutoConfig.for_model
- asr_layers: nn.Module.get_submodule for the layer-stack lookup
- projectors: torch.nn.RMSNorm instead of transformers' LlamaRMSNorm

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D4gdQCgNfW9ZWGdgMuEVg
…/deploy

- production.yaml: hub_strategy end; PushToHubCallback already pushes every
  save, so Trainer was uploading the same weights a second time
- train: Dataset.repeat for upsampling/epoch expansion; select_columns;
  token preflight via huggingface_hub.get_token (accepts `hf auth login`
  and training.hub_token, which is now actually passed to the pushes)
- remote_scripts: shlex.quote/shlex.join for tokens, keys and Hydra
  overrides so `$`, quotes, spaces or brackets survive bash on the pod
- plan: count projector params on the meta device
- check_gradient_flow: read a real experiment (--experiment, default
  stage_1; embedded.yaml no longer exists), build the batch with the
  training DataCollator, get_total_norm, transformers.set_seed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D4gdQCgNfW9ZWGdgMuEVg
nn.RMSNorm multiplies by the weight before the final bf16 cast; LlamaRMSNorm
casts first. In bf16 about a quarter of outputs differed by one ULP, so
existing checkpoints would no longer decode bit-identically. Not worth it
for dropping one import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D4gdQCgNfW9ZWGdgMuEVg
@alexkroman
alexkroman merged commit 545b228 into main Oct 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants