Skip to content

test: Add Valley-Bowl, optimizer and LR options to trajectories - #843

Open
rkhosrowshahi wants to merge 6 commits into
SimplexLab:mainfrom
rkhosrowshahi:test/valley-bowl
Open

rkhosrowshahi wants to merge 6 commits into
SimplexLab:mainfrom
rkhosrowshahi:test/valley-bowl

Conversation

@rkhosrowshahi

Copy link
Copy Markdown
Member

Adds the two-objective Valley-Bowl toy problem from CAGrad (Liu et al., 2021), also used by Nash-MTL (Navon et al., 2022), to the trajectory experiments, and lets optimize.py choose the optimizer and override the learning rate.

Reference implementations:

  • CAGrad: toy.py

  • Nash-MTL: experiments/toy

  • New ValleyBowl objective with its reference Pareto set, registered as VB and VB01 (first objective scaled by 0.1) in _constants.py, to compare aggregators under loss rescaling. Its scale and scale_both_losses parameters follow the Nash-MTL implementation.

  • optimize.py: new --optimizer {sgd,adam} (default sgd) and --lr flags; the optimizer is saved in metadata.json.

  • plot_params.py / plot_values.py: Valley-Bowl-specific heatmaps, Pareto set/front and optimum marker.

  • Typed AGGREGATORS as dict[str, Aggregator].

Learning rate. Both Valley-Bowl variants use a base learning rate of 0.001 for SGD and Adam. Each trajectory is deterministic for a given starting point. A large step can jump over a valley or push the trajectory far outside the plotting window. A small, fixed rate keeps the comparison focused on the direction each aggregator chooses toward the Pareto set from each starting point. It also matches the runs we already have with both optimizers. Per-aggregator multipliers still apply on top of this, unless --lr is given.

Initial points. There are 5 starting points. Three of them, (0, 0), (-7.5, -0.5) and (9, -1), lie near the boundary between the valleys and the bowls. The other two, (-8.5, 7.5) and (9, 9), start high up in the valleys, which makes them harder to optimize from.

Usage:

uv run python tests/trajectories/optimize.py VB upgrad mgda --optimizer adam
uv run python tests/trajectories/optimize.py VB01 upgrad mgda --optimizer adam

@rkhosrowshahi
rkhosrowshahi requested a review from a team as a code owner November 6, 2026 19:54
@rkhosrowshahi rkhosrowshahi added the cc: test Conventional commit type for changes to tests. label Nov 6, 2026
Add the Valley-Bowl toy problem from CAGrad and Nash-MTL as the VB and VB01
objectives, and add --optimizer and --lr flags to optimize.py.

@ValerianRey ValerianRey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't review the maths, I trust you on that. I have a concern about how we represent the mean objective, but apart from that LGTM.

Comment thread tests/trajectories/_objectives.py Outdated
Comment on lines +191 to +197
@property
def optimum(self) -> Tensor:
"""
Pareto-optimal point that (approximately) minimizes the mean of the unscaled objectives. It
does not depend on ``scale`` or ``scale_both_losses``.
"""
return torch.tensor([0.0, self.PARETO_SET_X2])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of calling this "optimum" and emphasizing it too much as the natural objective of the optimization problem. This is just an arbitrary choice of target. Maybe we could call it mean_optimum or something like that.

Also, I'm not a fan of representing this point / its image, as a star on the plot. The star is for the pareto set / front, when it consists of a single point (as in the EWQ objective).
This would also give the idea that not converging to the star is a bad thing, while in reality converging to the star is an arbitrary choice, that some aggregators make and some don't.

@rkhosrowshahi rkhosrowshahi Nov 9, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, agreed. I removed the star from both plots and dropped the optimum property, since nothing else used it. The plots now only show the Pareto set/front. See the below for change:
upgrad_star_comparison

@rkhosrowshahi

Copy link
Copy Markdown
Member Author

I realized the x-axis needs to be wider than the y-axis with a 5:6 ratio, so the auto ticks cover the right values and don't miss any. See the figure comparison with square-box subplots and the 2 × 2.5-inch figure (before) with a 5:6 box ratio and 3 x 3-inch figure (new):
layout_comparison
-0.5 and 0.5 are shown after the change.
layout_comparison
In param plots, -5 and 5 are shown after the change. In value plots, only (VB: -20 and 0) and (VB01: -2 and 0) were shown, but after the change, it shows (VB: -20, -10, 0, and 10) and (VB01: -2, -1, 0, and 1). In both settings, the xlim and ylim are set in constants.

Make the subplots slightly wider than tall (box aspect 5/6), so that
matplotlib's automatic ticks on the x-axis are as complete as on the
y-axis instead of skipping values.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cc: test Conventional commit type for changes to tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants