Skip to content

Learned fusion (LTR) over per-candidate features — make-or-break #129

Description

@nikolay-e

Context

Make-or-break for the "graph has independent value" thesis. Deployed EGO mixture (hand-set weights) scores below its own lexical component (0.352 < 0.402); union proves the ceiling ≥0.473. Instead of hand-tuning 10 category multipliers, learn a linear ranker over per-candidate features. Runtime stays a dot product: deterministic, zero-model-cost identity preserved, weights are interpretable (and are the per-category calibration Section 4.3 promised).

Features (initial set, ~15–20)

bm25_score, ego_score, ppr_score, cochange_count, import_hop_distance, same_dir, test_link, path_token_overlap, identifier_overlap, fragment_kind one-hot, I(f) importance prior, file_size_tokens, in_degree, sibling, proximity_decay

Tasks

  • Feature extraction pass emitting per-candidate vectors into telemetry (behind env flag)
  • Train logistic regression + LambdaMART on co-change corpus (04) train split + ContextBench train; select on val
  • Bake winning weights into Rust as ScoringMode::Learned; weights table committed + printed by --explain
  • Full sweep at B=8000, seeds 42/43/44, paired stats vs RRF (01) and vs union artifact
  • Ablate feature groups (graph-only, lexical-only, history-only) for the paper

Gate (pre-registered)

  • held-out nontrivial_file_recall ≥ 0.50 AND file_precision ≥ 0.30
  • If failed: RRF stays deployed default and paper v3 states plainly that the graph is a complement, not a dominant signal. Commit the negative result with REVERT-tag discipline.

Depends on: 04-cochange-corpus, 06-multihop-imports

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions