-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
[Tune] Fix and optimize sample search algorithm quantization logic #28187
Conversation
Signed-off-by: ilee300a <[email protected]>
Signed-off-by: ilee300a <[email protected]>
"lograndint": tune.lograndint(1, 10), # Random integer in log space | ||
"qlograndint": tune.qlograndint(1, 10, 2), # Round to increments of 2 | ||
"qlograndint": tune.qlograndint(1, 10, 2), # Round to multiples of 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering maybe an example is easier to understand than wording?
e.g. the qrandint(1, 10, 3) translates to choosing randomly among [3, 6, 9] as we were discussing yesterday?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should choose between [1, 4, 7, 10] though, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The quantized sampling rounds the sampled values to multiples of q rather than integer increment of q from the lower bound. So qrandint(1,10,3)
will randomly sample from [3,6,9]
rather than [1,4,7,10]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilee300a do you want to provide more details as to why the decision was made so? My understanding is there is some impl that is shared with other sampling methods, which may require [3, 6, 9] instead of [1, 4, 7, 10].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using other libraries, the expected behavior of quantization is to select those that are divisible by the given q within the bounds. For example, when using BOHB, it expects the provided lower and upper bound to be a multiple of q and provides multiples of q within those bounds as the samples. So if we run qrandint(1,10,3)
, it actually samples multiples of 3 between 3 and 9(inclusive).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes me wonder if we should raise an exception during domain initialisation if the bounds are not divisible instead. Or at least a warning - if we silently change the bounds it may be surprising to some users
Thanks! Left some comment.. |
Could you also rebase/merge on the current upstream/master? That should hopefully fix the tests :) |
python/ray/tune/search/sample.py
Outdated
@@ -532,8 +532,15 @@ def sample( | |||
): | |||
if not isinstance(random_state, _BackwardsCompatibleNumpyRng): | |||
random_state = _BackwardsCompatibleNumpyRng(random_state) | |||
values = self.sampler.sample(domain, spec, size, random_state=random_state) | |||
|
|||
quantized_domain = Domain() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we deepcopy the existing domain instead of creating a new one? seems like we are losing subclass type here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Can we add some test cases here (in test_sample.py
):
self.config = {
# ...
"qrandint": tune.qrandint(-21, 12, 3),
"qrandint_q3": tune.qrandint(1, 10, 3),
"qrandint_q1": tune.qrandint(1, 5, 1),
if "qrandint_q3" not in ignore:
self.assertGreaterEqual(out["qrandint_q3"], 1)
self.assertLessEqual(out["qrandint_q3"], 10)
self.assertEqual(out["qrandint_q3"] % 3, 0)
self.assertTrue(isinstance(out["qrandint_q3"], int))
if "qrandint_q1" not in ignore:
self.assertGreaterEqual(out["qrandint_q1"], 1)
self.assertLessEqual(out["qrandint_q1"], 5)
self.assertEqual(out["qrandint_q1"] % 1, 0)
self.assertTrue(isinstance(out["qrandint_q1"], int))
elif k == "qrandint_q3":
for i in range(1, 10, 3):
self.assertIn(i, v, msg=f"qrandint_q3 failed for i={i}")
elif k == "qrandint_q1":
for i in range(1, 5, 1):
self.assertIn(i, v, msg=f"qrandint_q1 failed for i={i}")
Thanks!
Signed-off-by: ilee300a <[email protected]>
Signed-off-by: ilee300a <[email protected]>
Signed-off-by: Kai Fricke <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks!
Signed-off-by: Kai Fricke <[email protected]>
…ay-project#28187) Co-authored-by: Kai Fricke <[email protected]> Signed-off-by: PaulFenton <[email protected]>
Why are these changes needed?
Current quantization logic incorrectly rounds sampled values. In this PR, this error is fixed and quantization for q = 1 is optimized by omitting quantization.
Related issue number
Closes #28045
Checks
git commit -s
) in this PR.scripts/format.sh
to lint the changes in this PR.