Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLT - add visualization of objective as function of stop_val #479

Merged
merged 17 commits into from Mar 5, 2023

Conversation

Badr-MOUFAD
Copy link
Member

@Badr-MOUFAD Badr-MOUFAD commented Nov 9, 2022

This adds a toggle to enable visualizing the objectives as function stop_val, namely n_iter.

Link to a dummy benchmark to preview the feature. (credit to @mathurinm for the idea of the benchmark).
A link to the benchmark repo to reproduce.


PR related to #287

@Badr-MOUFAD
Copy link
Member Author

any thoughts @mathurinm?

@mathurinm
Copy link
Contributor

mathurinm commented Nov 15, 2022

Thanks for having a look @Badr-MOUFAD ! I can't see anything for the other objective, is it normal ?
https://hal.archives-ouvertes.fr/hal-01941152v2/document

image

How does this handle combination of solvers that use iteration stop_val and tol stop val ?

I'd try to find an explicit name for the toggle button, like "plot a function of stopping criterion" but shorter... not easy :)

@Badr-MOUFAD
Copy link
Member Author

Thanks for having a look @Badr-MOUFAD ! I can't see anything for the other objective, is it normal ?

@mathurinm, the values of the objective are negative and hence can't be visualized using a log-y scale.
Try linear scale or in the sidebar set the objective to Affine[with_exp=True]

@Badr-MOUFAD
Copy link
Member Author

How does this handle combination of solvers that use iteration stop_val and tol stop val ?

Actually, it doesn't handle this case and I don't see how we can achieve that (also, I don't find a column in the .parquet file that informs about the type of stop criterion).

IMO, plotting as a function of stop_crit would make sense if all solvers use the same stop_crit and that stop_crit has the same scale for all solvers (e.g. a solver that converges in 10 iterations, yet under the hood runs several epochs, versus a solver that converges in 1000 iterations).

@jeandut
Copy link

jeandut commented Dec 29, 2022

Some minor comments after @mathurinm's invitation (to take with a grain of salt):

  • Stopping Criterion is not intuitive for the name of such a toggle, an alternative name would at least include "X-axis" somewhere
  • Stop_value is also unintuitive #iterations is better
  • I would avoid scientific notation for the x-axis in the case of iterations and use the integer prior over the indices to have a better visualization (as in matplotlib MaxNLocator(integer=True))
  • The default scale for a plot function of iterations should be linear

(Not linked to this PR, but with benchopt the kind of ZigZag pattern that can be observed in the current result plot is not rare and a little bit puzzling)

@tomMoral
Copy link
Member

tomMoral commented Jan 2, 2023

Actually, I am not sure we want to add a switch.
I would be more in favor of a solution to have a selector that allows to put any metric as x and any as y? (keeping the default to time and first objective value).
This would make the UI very explicit that one is choosing the axis value.
And it would also solve extra use cases, where people want to look for pareto front with multiple objectives.

Also, this would allow to separate iterations/tolerance, which I think is a pain to handle right now (and probably why it is called stop_value in the PR).

WDYT?

@jeandut
Copy link

jeandut commented Feb 23, 2023

I would like to reiterate that the completion of this PR would be extremely valuable for a lot of us in the community.
I side with @tomMoral on the selector for x instead of a toggle. It would allow to very easily add more resampling options in the long-term.

I also remain adamant that at least on the display html, names should reflect what the user is interested in and not variable names from the codebase i.e. iterations/tolerance and not StoppingCriterion or stop_val.

It would be really great as well if we can have integer ticks if x == iterations.

Cheers.

@tomMoral
Copy link
Member

As discussed with @mathurinm IRL, I propose the following solution to move on with this PR:

  • We add a drop-down menu with ['iteration', 'tolerance'] on the page.
  • In the solver_data[solver]['scatter'] dictionary, we add a value 'strategy' in iteration, tolerance.
  • Depending on the drop-down menu, we display only the solver with the strategy that matches the one selected in the drop-down menu.

I would say this looks like a good first step, without adding too much complexity? WDYT @Badr-MOUFAD ?

@codecov-commenter
Copy link

codecov-commenter commented Feb 23, 2023

Codecov Report

Merging #479 (0e1b40f) into main (1487639) will decrease coverage by 0.07%.
The diff coverage is 33.33%.

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@            Coverage Diff             @@
##             main     #479      +/-   ##
==========================================
- Coverage   54.64%   54.58%   -0.07%     
==========================================
  Files          43       43              
  Lines        2796     2805       +9     
  Branches      511      514       +3     
==========================================
+ Hits         1528     1531       +3     
- Misses       1153     1159       +6     
  Partials      115      115              

@Badr-MOUFAD
Copy link
Member Author

Yes, it sounds good to me.

@Badr-MOUFAD Badr-MOUFAD force-pushed the add-iteration-plot branch 2 times, most recently from 030ea2e to d673c7b Compare February 28, 2023 16:37
@Badr-MOUFAD
Copy link
Member Author

@tomMoral, I have a little concern about this point

In the solver_data[solver]['scatter'] dictionary, we add a value 'strategy' in iteration, tolerance.

In fact, we don't store the strategy in the data frame of results and hence we cannot determine the stopping strategy at the plotting stage: generate_html.py.

One workaround is to add the stopping strategy attribute in meta when running the benchmark. That way the stopping_startegy would be available in the final data frame

benchopt/benchopt/runner.py

Lines 187 to 192 in 1487639

meta = dict(
objective_name=str(objective),
solver_name=str(solver),
data_name=str(dataset),
idx_rep=rep,
)

WDYT @tomMoral? Do you see another workaround?

@tomMoral
Copy link
Member

tomMoral commented Mar 1, 2023

WDYT @tomMoral? Do you see another workaround?

I would have suggested the same so perfect :) As the dataframe is stored as a parquet (thus compressed), the impact on the output file's size should be minim so works for me.

@Badr-MOUFAD
Copy link
Member Author

Badr-MOUFAD commented Mar 2, 2023

With the latter remarks being taken into account here is a preview of the feature.

The xaxis type drop menu acts also as a filter: only the solver with a stopping strategy matching xaxis type will be shown.

@tomMoral, @jeandut I am open to suggestions.

Copy link
Member

@tomMoral tomMoral left a comment

Choose a reason for hiding this comment

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

LGTM! a few comments but I really like the result, it looks very smooth! thanks a lot @Badr-MOUFAD

the two things to fix:

  • callback strategy should be mapped to iteration
  • the drop down menu should contain only values present in the dataframe

Comment on lines 99 to 101
<option value="time">Time</option>
<option value="iteration">Iteration</option>
<option value="tolerance">Tolerance</option>
Copy link
Member

Choose a reason for hiding this comment

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

can this be parametrized to avoid putting iteration or tolerance if it does not exists in the data?
Actually, all these values should come from the ['time'] + list(df['stopping_strategy'].unique())

Copy link
Member Author

Choose a reason for hiding this comment

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

I opted for dynamically creating the options depending on the selected dataset and objective columns. In fact, some solvers might be skipped in some cases.

Any thoughts?

benchopt/runner.py Outdated Show resolved Hide resolved
benchopt/plotting/html/static/result.js Outdated Show resolved Hide resolved
benchopt/plotting/html/static/result.js Show resolved Hide resolved
benchopt/plotting/html/static/result.js Outdated Show resolved Hide resolved
benchopt/plotting/html/static/result.js Outdated Show resolved Hide resolved
@jeandut
Copy link

jeandut commented Mar 3, 2023

With the latter remarks being taken into account here is a preview of the feature.

The xaxis type drop menu acts also as a filter: only the solver with a stopping strategy matching xaxis type will be shown.

@tomMoral, @jeandut I am open to suggestions.

Very cool work it looks very good !
A few disorganised comments on the preview:

  • I would remove the word type after X-axis.
  • Tolerance axis does not seem to work in this example
  • would love to have integer tick labels when switching to iterations but this is a detail

Overall it's very nice !

@Badr-MOUFAD
Copy link
Member Author

Badr-MOUFAD commented Mar 3, 2023

Thanks, @jeandut for the feedback! Here is the updated preview of the feature.

@tomMoral
Copy link
Member

tomMoral commented Mar 4, 2023

Could not check on my computer right now but any idea why the x-axis is not visible on mobile?
Screenshot_20230304-005854.jpg

I will review it tomorrow but the changes look good and good idea to create the drop down menu dynamically, it is better to only have non empty option 😁

@Badr-MOUFAD
Copy link
Member Author

Badr-MOUFAD commented Mar 4, 2023

Could not check on my computer right now but any idea why the x-axis is not visible on mobile?

I have just become aware that the responsiveness (mobile support) was implemented by duplicating the sidebar's content and styling it separately.

<body>
<!-- Two main columns container -->
<div class="flex">
<!-- Left column on big screen (plot selectors) -->

</div>
<!-- Right column on big screen and main column on mobile -->
<div class="w-full flex flex-col overflow-scroll">

Hence to fix #479 (comment), we should make the same changes we did for the sidebar of the big screen to the one on the mobile screen.

Responsiveness is usually implemented through breakpoints that specify the style to be applied according to the screen size.
A follow-up TODO of this PR is to remove the content duplication and implement properly the responsiveness.


P.S. I updated the feature preview

@jeandut
Copy link

jeandut commented Mar 4, 2023

Thanks, @jeandut for the feedback! Here is the updated preview of the feature.

Awesome !!!

@jeandut
Copy link

jeandut commented Mar 4, 2023

Although there might be a bug see values in iteration axis when converting to log-log ?:
1-2-5-10-2-5-100-2-5-1000 etc.
Capture d’écran 2023-03-04 à 16 12 52

Copy link
Member

@tomMoral tomMoral left a comment

Choose a reason for hiding this comment

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

Ok, it looks good! Just a small fix for the xticks and 2 nitpicks and we are good to go!
Thx @Badr-MOUFAD !

benchopt/plotting/generate_html.py Outdated Show resolved Hide resolved
benchopt/plotting/html/static/result.js Outdated Show resolved Hide resolved
benchopt/runner.py Outdated Show resolved Hide resolved
@tomMoral
Copy link
Member

tomMoral commented Mar 4, 2023

Could not check on my computer right now but any idea why the x-axis is not visible on mobile?

I have just become aware that the responsiveness (mobile support) was implemented by duplicating the sidebar's content and styling it separately.

<body>
<!-- Two main columns container -->
<div class="flex">
<!-- Left column on big screen (plot selectors) -->

</div>
<!-- Right column on big screen and main column on mobile -->
<div class="w-full flex flex-col overflow-scroll">

Hence to fix #479 (comment), we should make the same changes we did for the sidebar of the big screen to the one on the mobile screen.

Responsiveness is usually implemented through breakpoints that specify the style to be applied according to the screen size. A follow-up TODO of this PR is to remove the content duplication and implement properly the responsiveness.

P.S. I updated the feature preview

Thanks a lot for the explanation, indeed it would be much better to implement it with the right synthax.

@Badr-MOUFAD
Copy link
Member Author

Although there might be a bug see values in iteration axis when converting to log-log ?: 1-2-5-10-2-5-100-2-5-1000 etc.

Looking at Plotly log scale doc, I don't think it is a bug.
Looks fine to me. Do you think it might be misleading @jeandut?

@jeandut
Copy link

jeandut commented Mar 4, 2023

Although there might be a bug see values in iteration axis when converting to log-log ?: 1-2-5-10-2-5-100-2-5-1000 etc.

Looking at Plotly log scale doc, I don't think it is a bug. Looks fine to me. Do you think it might be misleading @jeandut?

You are totally right. The tick values do make sense somehow on log-scale. Looks like it's ready to be merged ! Great work !

@tomMoral tomMoral merged commit 6b67c3c into benchopt:main Mar 5, 2023
@tomMoral
Copy link
Member

tomMoral commented Mar 5, 2023

merged, thanks a lot for making this feature @Badr-MOUFAD !

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.

None yet

5 participants