Skip to content

One-pass qmap-partial specificity metric, replacing fast and qnorm spec - #6

Merged
davek44 merged 6 commits into
mainfrom
qmap-spec
Oct 16, 2026
Merged

davek44 merged 6 commits into
mainfrom
qmap-spec

Conversation

@davek44

@davek44 davek44 commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Replaces fast spec (per epoch) and qnorm spec (hound_eval_spec, post hoc) with one streaming specificity metric. It is reported per epoch in training (spec, spec/<group> in metrics.tsv) and per track in hound_eval (spec column of acc.txt).

Changes

  • hound_data: writes target_hist to each examples/*.zarr: exact whole-genome histograms of the stored fp16 targets, per track, with strand pairs summed (num_targets × 31744). Replaces write_target_means.
  • metrics.SpecPearsonCorrCoef:
    • Tables: builds qnorm's tie-averaged quantile map for each track from target_hist (qmap_tables).
    • Per batch: sums strand pairs, maps preds and targets through the target's table, regresses the group mean out of each track, and accumulates moments.
    • Output: per-track Pearson r of the residuals.
  • hound_eval: computes spec in the normal eval pass.
  • hound_train_folds --eval: scores the test fold at the end of each training job.
  • Removed:
    • hound_eval_spec, spec_norm.py, seqnn.eval(combine_pairs=...);
    • hound_eval_folds options --spec, --band, --seq_chunk, --ram and --scratch_dir.

Validation

  • Agreement with qnorm spec: Spearman ρ across tracks within each group, on test sets of a 4-fold hg38 + mm10 model.
    • ChIP groups 0.97–0.99, and ≥ 0.9 in 13 of 17 groups.
    • Sparse single-cell groups are lower: 0.77–0.89.
    • For reference, fast spec gave −0.33 on hg38 H3K4me3.
  • Early stopping: over 160 checkpoints, epoch-to-epoch changes in valid spec track those in test spec at r 0.94 (summed over datasets).
  • Tests:
    • tables match a sort-based qnorm reference;
    • the streaming metric matches a direct numpy computation;
    • depth-only gain scores ≈ 0, and a planted track-specific signal is recovered;
    • histogram counts are exact, including strand pairs;
    • NaN predictions, near-identical tracks and constant group means are handled.

Known limitation

Predictions are mapped through the target's table, not through their own distribution as qnorm does. In sparse groups, where most bins are zero, this reads up to 0.10 lower than qnorm and ranks tracks less consistently with it.

Breaking changes

  • Datasets need target_hist. Without it, spec is disabled with a warning. Backfill with python -c "from baskerville import dataset; dataset.write_target_hist('data_dir')". The mean attr is no longer written or read.
  • spec changes meaning: in metrics.tsv and acc.txt it now reports the new metric.
  • GCP eval resume: the run-id hash no longer includes spec options, so earlier GCP eval runs won't resume.

🤖 Generated with Claude Code

davek44 and others added 6 commits October 8, 2026 10:47
hound_data writes exact whole-genome per-track histograms of the stored
fp16 targets (strand sums) as target_hist; SpecPearsonCorrCoef builds
qnorm's tie-averaged quantile maps from them, maps preds and targets
through each track's table, regresses out the group mean per track, and
streams per-track moments. hound_eval reports it in its single pass.
Removes hound_eval_spec, spec_norm, combine_pairs, and hound_eval_folds
--spec/--band/--seq_chunk/--ram/--scratch_dir.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map NaN predictions as 0 instead of indexing outside the tables; build
the group reference once by sweeping all tracks' tie-block bounds;
accumulate group-mean moments per group and only cross terms per track;
share tables between train and valid metrics; count histograms per
track in int32; reject strand-pair splits when subsetting target_hist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ning job

With one-pass spec, the test eval is cheap enough to run on the training GPU
right after training. Each job chains hound_eval per dataset on its held-out
fold, writing <fold>/eval*/fold<t> as hound_eval_folds does; the GCP run links
test -> fold<t> after the final pull. A fold with COMPLETE but no test acc.txt
is relaunched (the trainer resumes finished and exits; the eval reruns).
--rc passes through. link_test_metrics moves to helpers/fold_utils.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@davek44
davek44 merged commit ad371f5 into main Oct 16, 2026
2 of 3 checks passed
@davek44
davek44 deleted the qmap-spec branch October 16, 2026 04:05
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.

1 participant