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

Implement NSGA-III #4436

Merged
merged 86 commits into from
May 11, 2023
Merged

Conversation

Alnusjaponica
Copy link
Collaborator

@Alnusjaponica Alnusjaponica commented Feb 17, 2023

Motivation

Implement NSGA-III algorithm, which is a modified version of NSGA-II for many-objective optimization problem. This algorithm is also desired at #4075.

Description of the changes

Implement NSGAIIISampler which realizes NSGA-III algorithm. The main change in the algorithms is the strategy used to determine who survives from the boundary front, where NSGA-II uses crowding distance while NSGA-III uses reference points.
The difference between NSGA-II and NSGA-III in implementation is the following two points:

  • NSGAIIISampler has attribute reference_points used in _select_elite_population()
  • _crowding_distance_sort() called from _select_elite_population() is replaced with new procedure proposed in NSGA-III algorithm.

Other part of nsgaiii.py is almost the same as nsgaii/_sampler.py.

As confirmed in the following benchmark results on test problems, NSGA-III is competitive enough compared to NSGA-II in terms of hyper volume metric.
WFG6_M_3
WFG6_M_5
WFG6_M_8

In addition, the results of NSGA-III tends to be more diverse as observed in the following plots.

Figure_1

Figure_2

Figure_3

This is because the crowding distance is set to infinite when an individual has the largest or smallest value on any of the objective axes, and such individuals always survive. Therefore, the resulting points of NSGA-II tend to concentrate near the axes (i.e., take extreme values) in situations where the dimension is large and the first front often becomes the boundary rank front.

@github-actions github-actions bot added the optuna.samplers Related to the `optuna.samplers` submodule. This is automatically labeled by github-actions. label Feb 17, 2023
@Alnusjaponica Alnusjaponica marked this pull request as ready for review February 17, 2023 13:26
@toshihikoyanase toshihikoyanase added the feature Change that does not break compatibility, but affects the public interfaces. label Feb 20, 2023
@Alnusjaponica
Copy link
Collaborator Author

Alnusjaponica commented Feb 24, 2023

The detailed descriptions of the experiment are as follows:

  1. How hypervolume is improved as number of trials is increased
    This experiment

    • compares NSGA-II and NSGA-III with dividing parameter p=5,8
    • runs 5000 trials 5 times for each setting
    • uses WFG6 with objective dimension 3, 5, 8
    • determines reference point for hypervolume as the nadir point of best_trials at each step (number of trials = 500,1000,...5000)
  2. What the geometrical feature of the results is like
    This experiment

    • compares NSGA-II and NSGA-III with dividing parameter p=5
    • run 3000 trials and extract best trials among all 6000 trials
    • uses DTLZ1 with objective dimension 9
    • plots the objective values by 3 dimension

@codecov-commenter
Copy link

codecov-commenter commented Mar 2, 2023

Codecov Report

Merging #4436 (7cae1e3) into master (906f6a6) will increase coverage by 0.01%.
The diff coverage is 97.02%.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

@@            Coverage Diff             @@
##           master    #4436      +/-   ##
==========================================
+ Coverage   90.88%   90.90%   +0.01%     
==========================================
  Files         184      186       +2     
  Lines       13959    14269     +310     
==========================================
+ Hits        12687    12971     +284     
- Misses       1272     1298      +26     
Impacted Files Coverage Δ
optuna/samplers/_nsgaiii.py 97.01% <97.01%> (ø)
optuna/samplers/__init__.py 100.00% <100.00%> (ø)

... and 11 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Alnusjaponica and others added 6 commits March 3, 2023 15:55
Co-authored-by: Toshihiko Yanase <toshihiko.yanase@gmail.com>
Co-authored-by: Toshihiko Yanase <toshihiko.yanase@gmail.com>
Copy link
Member

@HideakiImamura HideakiImamura left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. I have some early comments and questions. I will review the details of _normalize,_associate, and _niching in the next week.

optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/nsgaiii.py Outdated Show resolved Hide resolved
Copy link
Member

@HideakiImamura HideakiImamura left a comment

Choose a reason for hiding this comment

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

Thanks for your long running. LGTM!

@toshihikoyanase
Copy link
Member

I found that the module of optuna.samplers.nsgaii was public. I think users import NSGAIIISampler like from optuna.samplers import NSGAIIISampler like the other samplers, and optuna.samplers.nsgaii does not provide any public classes/functions excepting for NSGAIIISampler. So, I guess we can rename nsgaiii.py to _nsgaiii.py.

@Alnusjaponica
Copy link
Collaborator Author

Thanks for your comment. I renamed the module and changed the import paths.

Copy link
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

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

Thank you for your update. I found two functions which are not used in the test cases. Could you check them?

tests/samplers_tests/test_nsgaiii.py Outdated Show resolved Hide resolved
tests/samplers_tests/test_nsgaiii.py Outdated Show resolved Hide resolved
Alnusjaponica and others added 4 commits May 9, 2023 12:32
Co-authored-by: Toshihiko Yanase <toshihiko.yanase@gmail.com>
Co-authored-by: Toshihiko Yanase <toshihiko.yanase@gmail.com>
Copy link
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

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

Thanks for your update. I have two minor comments.

optuna/samplers/_nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/_nsgaiii.py Show resolved Hide resolved
Copy link
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

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

The change basically looks good to me. Let me add some minor comments.

optuna/samplers/_nsgaiii.py Outdated Show resolved Hide resolved
optuna/samplers/_nsgaiii.py Outdated Show resolved Hide resolved
Comment on lines +481 to +484
asf_value = np.max(
np.einsum("nm,dm->dnm", objective_matrix, weights),
axis=2,
)
Copy link
Member

Choose a reason for hiding this comment

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

I guess this corresponds to eq. 4 of https://www.egr.msu.edu/~kdeb/papers/k2012009.pdf. We might mention it in the code comment, but we can work on it in a follow-up PR.

Comment on lines +534 to +544
perpendicular_vectors_to_reference_lines = np.einsum(
"ni,pi,p,pm->npm",
objective_matrix,
reference_points,
1 / reference_point_norm_squared,
reference_points,
)
distance_from_reference_lines = np.linalg.norm(
objective_matrix[:, np.newaxis, :] - perpendicular_vectors_to_reference_lines,
axis=2,
)
Copy link
Member

Choose a reason for hiding this comment

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

ditto. This seems to correspond to L5 to 7 of Algorithm 3 in https://www.egr.msu.edu/~kdeb/papers/k2012009.pdf. We'd like to improve the readability in a follow-up PR.

Copy link
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you for completing such a long-running PR!

We have possible follow-up tasks, but I don't think they are critical:

@toshihikoyanase toshihikoyanase merged commit 3d3aeec into optuna:master May 11, 2023
@toshihikoyanase toshihikoyanase added this to the v3.2.0 milestone May 11, 2023
@Alnusjaponica Alnusjaponica deleted the implement-nsgaiii branch May 11, 2023 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Change that does not break compatibility, but affects the public interfaces. optuna.samplers Related to the `optuna.samplers` submodule. This is automatically labeled by github-actions.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants