Filter non-positive RTs before KDE bandwidth estimation - #349
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthrough
ChangesKDE filtering
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to The change filters non-positive and non-finite reaction times before KDE bandwidth estimation, preventing one invalid sample from discarding an entire choice group's density while preserving clean data behavior. No actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
A genuinely negative or zero RT - real and expected for models whose non-decision-time kernel has unbounded support (e.g. a Normal(t, st) kernel), and distinct from the omission sentinel - produces log(non-positive) = NaN in the log-RT array. A single NaN poisons np.std() over the entire choice group inside bandwidth_silverman, which then fails the 'bandwidth > 0' check and silently discards the whole group as 'no_base_data'. Measured directly: 1 negative RT out of 198,865 samples collapsed its entire choice group, flattening that group's density to a theta-independent floor in the training labels. Extend the validity mask to require rt > 0 and finite log(rt), applied to the final (possibly displace_t-shifted) RTs. - The mask stays after the log rather than at it: with displace_t, measured 10 of 200 strictly-positive input RTs become non-positive only after the shift, so an earlier-only mask misses them. The RuntimeWarning from the earlier log is left unsuppressed - it reports real data. - All three mask terms are load-bearing, measured over 2M draws at the displace_t boundary: 3 cases where rt - t > 0 but the log path underflows to -inf (caught only by isfinite) and 1 in the reverse direction (caught only by rt > 0); rt = +inf is caught only by isfinite. != filter_rts is kept because filter_rts is a documented parameter and rt > 0 subsumes it only for negative sentinels. - No input existed for which the old code produced a finite bandwidth that this changes: contamination always forced no_base_data. Verified byte-identical (float hex) bandwidths and log_rts for clean data across ddm, ddm_st, full_ddm and ddm_sdv, at n=200 and n=5000. - Filtering can now leave a choice group with a single sample, where bandwidth_silverman returns its std_n_1 fallback of ~10.59 instead of collapsing. That is an improvement on a flat fallback but not a meaningful bandwidth, so it is documented on the class and pinned by a test. Raising the len(log_rts) == 0 floor to < 2 would also change pre-existing n=1 behavior and is left as a separate change. - Retention contract, the pre-filter basis of choice_proportions, and the n=1 limitation are now in the LogKDE class docstring, which is what the API docs render; the stale caller-precondition sentence in the kde_class tutorial is corrected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e89f64e to
696053f
Compare
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
A genuinely negative or zero RT - real and expected for models whose non-decision-time kernel has unbounded support (e.g. a Normal(t, st) kernel), and distinct from the omission sentinel - produces log(non-positive) = NaN in the log-RT array. A single NaN poisons np.std() over the entire choice group inside bandwidth_silverman, which then fails the 'bandwidth > 0' check and silently discards the whole group as 'no_base_data'. Measured directly: 1 negative RT out of 198,865 samples collapsed its entire choice group, flattening that group's density to a theta-independent floor in the training labels.
Extend the validity mask to require rt > 0 and finite log(rt), applied to the final (possibly displace_t-shifted) RTs. Clean data is unaffected