Skip to content

Counterfactual cause labels from intervention deltas - #196

Open
ShauryaVM wants to merge 3 commits into
autowarefoundation:mainfrom
ShauryaVM:feat/cause-intervention-labels
Open

Counterfactual cause labels from intervention deltas#196
ShauryaVM wants to merge 3 commits into
autowarefoundation:mainfrom
ShauryaVM:feat/cause-intervention-labels

Conversation

@ShauryaVM

@ShauryaVM ShauryaVM commented Aug 12, 2026

Copy link
Copy Markdown

Summary

Reviewable now: the intervention cause labeller, the schema provenance, and counterfactual_weak at source weight 0.3.

Synthetic unit protocol (not the #122 anchor)

evaluation/cause_label_unit_protocol.py smoke-tests the selector. Conflict and deltas are computed from 2-D scene geometry (ego polyline + factor points); they are not typed onto the same line. An independent geometry teacher uses a wider forward envelope — not MockTeacher's taxonomy hash. Results are labelled synthetic_unit_protocol. Oracle F1 on this protocol is 0.96 (the default relative_to_max drops a weaker true conflict); that number is a unit-test of the selector, not KIT object-GT recovery.

Test plan

  • pytest Model/tests/test_intervention_cause.py
  • python -m evaluation.cause_label_unit_protocol

Related to #122 (labeller + weak provenance only).

Offline helper for autowarefoundation#122: turn per-candidate trajectory L2 deltas into
cause lists with counterfactual_gt provenance for weak supervision / eval.

Co-authored-by: Cursor <cursoragent@cursor.com>
@riita10069

Copy link
Copy Markdown
Collaborator

Thank you for the contribution.
I would like you to submit it along with the experimental results. And could you explain in numbers?
To be honest, I'm not convinced about what value this issue provides.

@riita10069

Copy link
Copy Markdown
Collaborator

Under the contribution standard proposed in #198, I consider this PR AI slop in its current form. #122 calls for external-truth validation of the circularity risk first, but this PR instead generates counterfactual_gt from arbitrary model-sensitivity thresholds without that validation. This is not ready for review; please provide the required real-world validation before resubmitting.

Default provenance is counterfactual_weak. Precision/recall vs constructed ego-path conflict shows a privileged labeller recovers causes (F1=1) while a blind model-sensitivity labeller does not (F1=0.44) — the circularity autowarefoundation#122 asked to measure before anyone trains on these labels.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ShauryaVM

Copy link
Copy Markdown
Author

#122 asked to score this labeller against external truth before calling the labels ground truth. I do not have KIT LiDAR shards locally, so I ran the same precision/recall protocol on 12 constructed scenes whose external anchor is geometric conflict with the ego path (the KIT LiDAR/HD-map check, without the SDK). JSON: Model/evaluation/results/cause_label_validation.json.

Two labellers, same scenes, default selector (min_delta=1e-3, relative_to_max=0.5):

Labeller Precision Recall F1
oracle (delta tracks geometry) 1.00 1.00 1.00
blind (model ignores the conflict, attends to a distractor) 0.43 0.46 0.44

That is the circularity number: if you generate cause from the same network's sensitivity, you inherit its blind spots and still emit a label. Jaccard vs MockTeacher (an independent correlational labeller) is 0.08 for both arms — these are not the same thing as teacher_gt.

Because of that, this PR no longer writes provenance=counterfactual_gt. Labels default to counterfactual_weak (source weight 0.3, same band as weak_gt). counterfactual_gt is opt-in after a real KIT LiDAR pass beats a bar you are willing to train on.

How I tested: pytest Model/tests/test_intervention_cause.py (5 passed) and python -m evaluation.cause_label_validation.

I am not claiming KIT object-GT recovery. The value of the issue, in numbers: the selector is only as good as the intervention signal, and a blind model is not a labeller.

@gcordova10

Copy link
Copy Markdown
Contributor

Reran it: 5 tests pass, the JSON reproduces. The module is fine and
counterfactual_weak at 0.3 is the right call.

cause_label_validation.py cannot fail. In SCENES, in_conflict,
oracle_delta and blind_delta are hand-written on the same line. Across the 36
factors oracle_delta is 0.28–0.51 when in_conflict is true and 0.00–0.06 when it is
false, no overlap — so with min_delta=1e-3 F1 = 1.00 follows from how the table was
typed. #122's anchor has to come from somewhere the author of the deltas did not write.

MockTeacher is not an independent labeller. mock_teacher.py:57 is
labels[(seed + gi) % len(labels)] with seed hashed from the scene id; it returns
slippery_road for ped_in_crosswalk. Jaccard 0.08 measures the 27-label taxonomy,
not circularity.

The circularity number is still missing, so as it stands the PR claims a validation it
does not have and I do not think it is ready in one piece. Getting that number needs
real KIT scenes with LiDAR or HD-map conflict as the anchor — the part #122 calls
research, not a small follow-up. I would split it: intervention_cause.py, the schema
change and the weight are reviewable now; cause_label_validation.py and its JSON need
the real data first.

Deltas and conflict are computed from scene geometry, MockTeacher is gone,
and the JSON no longer claims autowarefoundation#122 KIT validation.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ShauryaVM

Copy link
Copy Markdown
Author

@gcordova10 Agreed on the split.

Still in this PR, and what I am claiming: intervention_cause.py, the schema provenance, and counterfactual_weak at 0.3. Labels from the model's own sensitivity are weak labels, not GT. counterfactual_gt stays opt-in.

Not claimed: issue #122 external-truth validation, KIT LiDAR / object-GT recovery, or circularity F1 from a handwritten table. I do not have KIT shards, so I am not inventing them. The PR description no longer quotes F1=1.00.

What happened to the old validation file: it could not fail — in_conflict / oracle_delta / blind_delta were typed on the same line, and MockTeacher was labels[(seed + gi) % len(labels)] (Jaccard 0.08 was taxonomy size; it returned slippery_road for ped_in_crosswalk). That is gone.

In its place is a synthetic unit protocol (evaluation/cause_label_unit_protocol.py), labelled as such in the JSON (claim=synthetic_unit_protocol, not_claimed includes kit_lidar_object_gt and issue_122_external_truth_validation):

  • Factor records are (name, x, y, radius) only. Conflict = surface distance to the ego polyline < 1.75 m. Oracle delta = exp(-d / 2) of that distance. Blind delta = the same vs a distractor attention point. Move a pedestrian onto the path and the numbers change; the author of the positions did not type the F1.
  • Independent labeller is a 4 m forward occupancy envelope, not MockTeacher. For ped_in_crosswalk it returns pedestrian_crossing, not slippery_road. Mean Jaccard vs the oracle selector is 0.60 (corridor vs two-lane envelope), not 0.08.
  • The protocol can fail: slippery_plus_lead has two true conflicts; relative_to_max=0.5 drops slow_lead_vehicle. Oracle micro F1 = 0.96 (recall 0.92), not 1.00. Blind F1 = 0.40.

That F1 is a unit-test of the selector against geometry it derived, not #122's KIT anchor. Getting that number still needs real KIT scenes with LiDAR or HD-map conflict.

pytest Model/tests/test_intervention_cause.py: 11 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.

3 participants