-
Notifications
You must be signed in to change notification settings - Fork 551
MNT: improved check_dimension type inference, added warnings, tests #1067
base: master
Are you sure you want to change the base?
MNT: improved check_dimension type inference, added warnings, tests #1067
Conversation
Hello @QuentinSoubeyran! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found: There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻 Comment last updated at 2021-10-18 20:30:55 UTC |
6fe0e96
to
55cefce
Compare
skopt/space/space.py
Outdated
def _check_dimension(dimension, transform=None): | ||
if isinstance(dimension, Dimension): | ||
return dimension | ||
elif isinstance(dimension, (list, np.ndarray)): |
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 don't like that a tuple of strings is no longer supported. Why does it need to be a list?
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 idea was to tighten the interface to prevent user errors leading to valid, but unwanted, dimension objects. This is most surely inspired by my uses of type-checkers in python, as the above makes the signature of check_dimension
not depend on the actual values contained in the passed sequence:
list
becomes aCategorical
tuple[int, int]
(and the 3- and 4-long forms) becomeInteger
tuple[int, float]
,tuple[float, int]
andtuple[float, float]
(and corresponding 3 and 4-long forms) becomeReal
It was also to avoid an incorrect tuple silently becoming a Categorical
, e.g.
(0, 1, "uniform", base)
wherebase="10"
was no parsed from a data source, silently returning aCategorical
instead of the intendedInteger
(0, 1, *params)
whereparams=(5, "log-uniform", 2)
because the semantic/content ofparams
is wrong, silently falling back to aCategorical
[True, False]
being inferred to anInteger
(though the old implementation has a dedicated branch to avoid that).
We could make it so that tuple
s that fail the Integer
/Real
inference default to a Categorical
as before. This would also allow to use any Iterable
, like so:
if isinstance(dimension, tuple) and 2 <= len(dimension) <= 4:
low, high, *args = dimension
if (not args or isinstance(args[0], str)) and (len(args) < 2 or isinstance(args[1], int)):
if isinstance(low, numbers.Integral) and isinstance(high, numbers.Integral):
return Integer(...)
elif isinstance(low, numbers.Real) and isinstance(high, numbers.Real):
return Real(...)
# not an else, fallback
if isinstance(dimension, Iterable):
return Categorical(...)
raise ValueError(...)
Do you prefer that other type-tightness ?
skopt/space/space.py
Outdated
if (isinstance(low, numbers.Integral) | ||
and isinstance(high, numbers.Integral)): | ||
return Integer(int(low), int(high), *args, transform=transform) | ||
elif isinstance(low, numbers.Real) and isinstance(high, numbers.Real): | ||
return Real(float(low), float(high), *args, transform=transform) |
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.
low
and high
are already int
(or float
). Why cast?
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 float
cast is because one of the boundaries might be an int
, and a Real
dimension asks for two float
in its doc.
The int
cast was to support other integral types like bool
or np.int32
.
Since int
is not a sublcass of float
, I think the float
cast is necessary to respect Real
's interface. I'm not too sure about the int
cast, I mostly did it for symmetry.
elif all(isinstance(dim, numbers.Integral) for dim in dimension): | ||
return Integer(*map(int, dimension), transform=transform) |
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.
Likewise, why this map()
?
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.
see above
ac9d5de
to
fde2119
Compare
@kernc I made tuples fall back to |
Fixes:
This PR fixes
skopt.space.check_dimension
to actually follow its own documentation:list
always lead toCategorical
objecttuple
lead toInteger
orReal
object, as inferred by the bound typescheck_dimension
is retained, and a warning is raised if the improved tightened inference would be different or fail.The new behaviour would fix:
int
andfloat
bounds may lead to an Integer object storing a float in one of its bounds, leading to crashes when generated points fall outside the float bound due to roundingint
s but meant aReal
object