Fix/ part of #115 compute planner loss - #124
Conversation
40d1acd to
45beaba
Compare
|
Thanks for this. Wiring I went through the branch. Two things. 1.
self._validate_trajectory_target(trajectory_target, B, bev_features.device) # :334but that helper is defined on trajectory = self.forward(bev_features, visual_history, egomotion_history)
imitation_loss = torch.nn.functional.smooth_l1_loss(trajectory, trajectory_target)On your branch, with two samples whose targets differ: planner = BezierPlanner().eval()
B, T = 2, 128
bev, vis, ego = torch.zeros(B,256,8,8), torch.zeros(B,896), torch.zeros(B,256)
tgt = torch.stack([torch.full((T,), 1.0), torch.full((T,), 5.0)]) # [B, T]
planner.compute_planner_loss(bev, vis, ego, tgt)["loss"] # 2.494182
planner.compute_planner_loss(bev, vis, ego, tgt[0])["loss"] # 0.494356 <- no error
To be clear about the blast radius, though: this cannot fire today. I would lift the guard to # base.py
def _validate_trajectory_target(self, trajectory_target, batch_size, device): ...
# bezier_planner.py — first line of compute_planner_loss
self._validate_trajectory_target(trajectory_target, bev_features.shape[0], bev_features.device)and add a Bezier counterpart to 2. Nothing calls #115's proposed fix has four steps. This PR does the first two — implement the objective on both
That is still open. On this branch and on loss_fn = TrajectoryImitationLoss(loss_type="smooth_l1")
...
pred = model(..., mode="train", trajectory_target=target)
loss = loss_fn(pred, target) # workflows.py:441 here, :805 on main
Since the description says If you do add the wiring here, it is worth rebasing first: the branch is based on 3. Should The reason I care about this entry point is #123: closed-loop RL needs somewhere to put a The one piece that doesn't quite fit is the signature: def compute_planner_loss(self, bev_features, visual_history, egomotion_history,
trajectory_target=None, **kwargs):I am not asking for it in this PR — the goal right now is a minimum architecture that can train, @riita10069, two of these are really yours to call rather than mine, and I would rather ask than
Neither blocks merging from my side. The one I would fix before it lands is the first: it is a |
|
@gcordova10 Thanks for the detailed review! I will look into it , |
|
Thanks for the thorough read — point 1 is real, confirmed it with your On point 2 — agreed this PR shouldn't claim "Fixes #115" as-is. I'd On point 3 (optional trajectory_target) — no objection to trajectory_target=None |
45beaba to
ced94e6
Compare
|
Thank you for following through on #115 so quickly — and for shaping the API exactly as discussed in #123. The Rather than treating this as a PR to review in isolation, we would like to propose something bigger: let's take this all the way to KITScenes Benchmark numbers, together. Here is the context. The production model does not use So here is what we would like to ask, as one arc of work:
On our side, we are happy to carry the infrastructure half of this: running the training and benchmark evaluations on our GPU cluster (we know GPU access has been a constraint for you), and reviewing the calibration questions from #76 against the actual map renderer ( This PR plus #76 together form a coherent research arc: correct objective → trained FlowMatching checkpoint → multi-sample scoring → benchmark comparison. We would be glad to walk that arc with you. Thank you again for driving this. |
|
Thanks for your time, You're right—I did mess up the regression on point 1. I'm fixing that now so the current mainline behavior is preserved, including restoring ReasoningCoupling, the zero-init visual_history_proj, and initial_noise support. As for the benchmark work, I'm already working on that. I first tried the k-sample trajectory visualization on a simple front-view camera sample from a random NVIDIA physical dataset just to validate the sampling pipeline. It correctly produces the random k trajectories in top-down (x, y) space. As you suggested, the next step is to move this over to the KITScenes dataset, which was already my plan after validating the pipeline. I'll also try to keep the comparison as apples-to-apples as possible by evaluating Bezier and FlowMatching using the same KITScenes dataset split, the same checkpoint evaluation pipeline, and the same sampling/scoring budget. That should make any performance differences attributable to the planners themselves rather than differences in the evaluation setup. As long as my laptop holds up( ;__;). Thanks for offering to handle the training ans benchmark evaluations on your GPU cluster—that'll definitely make this much more practical. Looking forward to seeing how FlowMatching stacks up once everything is wired together. 🙌 |
|
@FLagbusted — answering your earlier question, though you already landed on the same answer: yes, One leftover from point 2: the title now says "part of #115", but the body still has On point 2 of the arc, one thing worth settling before the wiring — I ran it rather than guessed,
Your apples-to-apples plan is the right instinct. If it is useful, the piece I could bring is on the |
|
Confirmed the regression — you were right on all three: ReasoningCoupling, the #13 zero-init, and initial_noise all got silently dropped by the earlier sync merges (git's 3-way merge took the "unchanged" side since the loss was already baked into the merge-base). Redid the merge + restored all three in a follow-up commit; diffed against main to confirm nothing else moved. 66/67 tests pass (1 GPU-only skip), ruff clean. Also fixed the Fixes #115 → Part of #115 body text @gcordova10 caught. Pushing now — will go on the KITScenes checkpoint again, Really appreciate all the time you gave it |
bench: add RTX-4050 Laptop GPU results
…real contract sample_and_score unpacked self.planner(...) as (trajectory, ego_hidden) — BasePlanner.forward() has only ever returned a single trajectory tensor. Fixed, plus the integrate_trajectory swap, real per-row initial_speed, and moved tests/test_trajectory_scorer.py -> Model/tests/ (never collected by CI at its old path). See PR comment for full detail. This also drops a compute_planner_loss commit that had landed on this branch by mistake — that work belongs on fix/115-compute-planner-loss (autowarefoundation#124), not here. Reset to 3054caa and rebased cleanly from there. 58 passed, 1 GPU-only skip. ruff clean. Signed-off-by: FLagbusted <justthefourofus@proton.me>
…nes-camera-views feat(kit_scenes): drop the redundant ring-front view and add a tele crop of the long-range camera (autowarefoundation#146)
…dation#115, autowarefoundation#124) See prior commits on this branch and the PR thread for full context. train_il now passes return_planner_loss=True + training_policy=training_policy into model(...) instead of computing loss externally via TrajectoryImitationLoss. return_planner_loss is a new, explicit opt-in flag (default False) on AutoE2E.forward()/ReactiveE2E.forward() -- every other existing caller (~20 call sites across the test suite) is unaffected. Signed-off-by: FLagbusted <justthefourofus@proton.me>
|
Thank you guys for helping out, compute_planner_loss is wired into train_il for real now. Traced the actual call chain (train_il → AutoE2E.forward() → ReactiveE2E.forward() → planner.forward()) and found trajectory_target was reaching all the way down but getting silently absorbed as an inert kwarg at every level — nothing ever used it to trigger a planner's real training objective. Fixed with an explicit opt-in (return_planner_loss=True), not on trajectory_target's mere presence — that alone would have broken ~20 existing call sites across the test suite that already pass it expecting a trajectory tensor back. Caught that the hard way via a failing test before it went anywhere @gcordova10 — for your signal_scales concern, what i did is : training_policy (the object, not derived scalars) now threads from train_il through AutoE2E/ReactiveE2E into BezierPlanner.compute_planner_loss, which builds a real TrajectoryImitationLoss from it. Added a regression test proving the policy actually changes the loss. FlowMatchingPlanner accepts the same param for signature parity but doesn't apply it yet — scaling (accel, curvature) on a direct regression vs. on a velocity target aren't obviously the same operation, so I left that as an explicit, documented open question rather than guess. @riita10069 — ready to take you up on the GPU offer for part 3. Whenever your cluster has room: a FlowMatching checkpoint trained through train_il as it stands now, benchmarked via wf_evaluate_kitscenes_benchmark against the existing Bezier baseline. The FlowMatching+#76-scorer third row will follow as its own commit once that checkpoint exists — evaluate_kitscenes_benchmark_checkpoint doesn't call the scorer at all today, so that's real work I haven't started, and part of it (the DAC score) isn't meaningful until #148/#149 settle anyway. Wanted the first two rows moving rather than block on that. Again thank you guys for help and it really helps me understanding the Architecture more. (;__;) |
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
…rift Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
The player now retains the packed camera count before display filtering so compact v3 shards do not lose front-left or shift every remaining label. Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Canonical v3 compacts six retained cameras while v2 and current smoke shards retain seven slots, so tests lock labels and grid positions for both layouts. Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
A direct v4 fixture check distinguishes codec regressions from stale browser servers before deployment. Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
Signed-off-by: riita10069 <ryota10069.tech5.jizi@gmail.com>
…t/bev-diagnostics-dashboard Add per-encoder BEV diagnostics to DataModelConsole
…towarefoundation#115) BasePlanner.compute_planner_loss is now @AbstractMethod, returning dict[str, Tensor] with a required 'loss' key rather than a bare scalar (per @gcordova10's autowarefoundation#123-motivated ask) — train_il only reads result['loss'] and stays agnostic to which planner/stage produced it; a future stage-3 RL objective can return {'loss': total, 'imitation_loss': ..., 'reward': ...} behind the same entry point with no signature change. FlowMatchingPlanner: proper flow-matching velocity-MSE objective (construct_training_data -> _v_theta -> MSE against target velocity). Replaces the previous train_il path, which regressed forward()'s Euler-from-noise rollout against a fixed target — pushing the network toward the conditional mean rather than training the velocity field. BezierPlanner: SmoothL1 on forward()'s output (a legitimate direct regression target, unlike FlowMatchingPlanner's ODE rollout). 13 new tests, including a regression guard proving forward() (inference) and compute_planner_loss (training) are fully decoupled — same seed, same output, before and after exercising the loss path. Fixes autowarefoundation#115 Signed-off-by: FLagbusted <Justthefourofus@proton.me> Signed-off-by: FLagbusted <justthefourofus@proton.me> Signed-off-by: Flagbusted <justthefourofus@proton.me>
…al_noise lost in sync Flagged by @riita10069. Both planners now match upstream main exactly except for compute_planner_loss (autowarefoundation#115) and the trajectory_dim attribute BasePlanner._validate_trajectory_target needs. Full suite re-run clean: test_planner_loss.py, test_trajectory_planning.py (incl. initial_noise tests), test_reasoning_coupling.py, test_bezier_planner.py — 66 passed, 1 GPU-only skip. ruff clean. Signed-off-by: FLagbusted <justthefourofus@proton.me>
…dation#115, autowarefoundation#124) See prior commits on this branch and the PR thread for full context. train_il now passes return_planner_loss=True + training_policy=training_policy into model(...) instead of computing loss externally via TrajectoryImitationLoss. return_planner_loss is a new, explicit opt-in flag (default False) on AutoE2E.forward()/ReactiveE2E.forward() -- every other existing caller (~20 call sites across the test suite) is unaffected. Signed-off-by: FLagbusted <justthefourofus@proton.me>
db6f36b to
50360ab
Compare
|
I will check it. |
|
I’m sorry for the disruption. Environment-specific infrastructure identifiers, including instance IDs, were inadvertently committed to the repository history, so we had to rewrite the history and force-push the cleaned branches. This caused this pull request to close automatically. I restored your commits in replacement PR #172 from the sanitized history, with the original commit authorship preserved: Before continuing work, please back up any uncommitted changes outside the repository, remove your existing local clone, and clone the repository again. Reusing or pushing from an old clone could reintroduce the removed history. I apologize for the unexpected closure and the additional review noise. |
Summary
Wires BasePlanner.compute_planner_loss (#115) into train_il for real, threads
the dataset-specific training policy through it (#124 review), and exposes
planner_mode so a FlowMatching run can actually be launched.
What's in here
dict[str, Tensor] with "loss" — FlowMatchingPlanner does real velocity-MSE,
BezierPlanner does SmoothL1, both share a trajectory_target shape/device
validator lifted onto BasePlanner.
scalars) threads from train_il through AutoE2E/ReactiveE2E into
BezierPlanner.compute_planner_loss, which builds a real weighted
TrajectoryImitationLoss from it. FlowMatchingPlanner accepts the same
param for signature parity but does not apply it (documented why —
scaling accel/curvature on a direct regression vs. a velocity target
aren't obviously the same operation; left as an open question rather
than guessed at).
return_planner_loss=False opt-in. Default False so the ~20 existing call
sites that already pass trajectory_target expecting a plain trajectory
tensor back are completely unaffected. train_il is the one caller that
sets it True.
loss now read from model(..., return_planner_loss=True,
training_policy=training_policy)'s result["loss"].
into AutoE2E(...) and saved into checkpoint_config. Found while preparing
to actually request a training run — neither function had ANY way to
select flow_matching before this; every run silently trained bezier
regardless of intent, which would have made the compute_planner_loss fix
above untestable in practice.
contained conflict in reactive_e2e.py's forward() signature (both sides
added params to the same line), resolved by keeping Add route-conditioned navigation inputs for KITScenes (#149) #161's new positional
route params and adding ours alongside. Everything else, including this
PR's own dispatch logic, auto-merged cleanly onto the new
NavigationEncoder/fused_features flow.
flow_matching "is NOT correctly trainable via train_il" — no longer true
as of this PR.
Why
The actual #115 bug, traced to its source: train_il called
model(mode="train", trajectory_target=target, ...), but trajectory_target
was silently absorbed as an inert kwarg all the way down to
ReactiveE2E.forward(), which called planner.forward() unconditionally
regardless of mode. FlowMatchingPlanner's Euler-from-noise rollout got
SmoothL1-regressed against the target externally instead of ever running
its real velocity-MSE objective.
Not in this PR
FlowMatching + #76's TrajectoryComplianceScorer as a third benchmark row —
evaluate_kitscenes_benchmark_checkpoint doesn't call the scorer at all
today, so that's real work I haven't started. Will follow as its own PR
once a FlowMatching checkpoint actually exists to test it against.
Testing done
test_planner_loss.py (incl. training_policy regression tests — proves the
policy actually changes BezierPlanner's loss, matching the 71% divergence
measured in review), test_auto_e2e.py (incl. tests exercising
return_planner_loss=True end-to-end: loss dict shape, gradient reaches the
Backbone, training_policy changes the number), test_workflow_training_
lifecycle.py (source-inspection tests for both the training_policy wiring
and the new planner_mode wiring), test_reasoning_integration.py. All
passing, ruff clean, verified against main post-#161 rebase.
Checklist