Implement exact tie-breaking for compute_challenge_score using hypergeometric distribution #4
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR updates the implementation of the challenge score metric to compute the exact expected TPR under random tie-breaking at the selection cutoff using the hypergeometric distribution.
Motivation
Previously, the metric relied on Monte Carlo permutations (
num_permutations = 10^4) to approximate the expected confusion matrix when ties occurred in the model outputs. This was both computationally expensive and stochastic.The new implementation uses the hypergeometric expectation to compute the result exactly, with no sampling. With the exact formulation, the metric is now reproducible, consistent, and fast. This implementation eliminates the
num_permutationsloop, reducing runtime fromO(num_permutations * n log n)toO(n log n).Explanation
The updated metric computes the exact expected TPR under uniform random tie-breaking at the cutoff capacity.
1. Handle edge cases and transform to numpy arrays
Capacity = 0 -> TPR = 0(nothing selected)Capacity >= n -> TPR = 1(everything selected)No positives -> TPR = NaN(undefined)2. Handle a split tie at the boundary
[start, end)where all scores equalv_incl(withintie_tol). This is the boundary tie group.g = end - start(group size)k = sum(y_sorted[start:end] == 1)(positives in the group)m = capacity - start(how many items must be selected from this group to reach capacity)pos_before = sum(y_sorted[:start] == 1)(positives strictly above the tie group)3. Exact expectation for the tie group
E[TP_from_tie] = m * (k / g)4. Combine contributions
E[TP] = pos_before + E[TP_from_tie] = pos_before + m * (k / g)TPR = E[TP] / P