Skip to content

Commit d86a17b

Browse files
blethamfacebook-github-bot
authored andcommitted
Remove parameter constraints when expanding model space in Adapter (#3408)
Summary: Pull Request resolved: #3408 By default we expand range parameters in the model space so that the training data include all modelable data, not just those that fall within the box bounds. A similar argument suggests that we should also include training data that violate parameter constraints in the model. They are modelable and can be used to improve predictions at points that satisfy parameter constraints. We do this by simply dropping parameter constraints from the model space, if the model space is specified to be expanded. This will also fix #1568 . The issue there is that generated points violated parameter constraints due to numerical issues, and so then were left out of the training data and repeatedly generated. With this change, those points would be included in the training data and so likely not re-generated. Note, however, that the purpose of this change is not just to fix this issue; it is a change that is right because it better fits the concept of the modeling space. Reviewed By: sdaulton, saitcakmak Differential Revision: D69880066 fbshipit-source-id: c5bc5d042b567eceefe9ef956240b4577c0fb5cb
1 parent 7c2788f commit d86a17b

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

ax/modelbridge/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def __init__(
140140
expand_model_space: If True, expand range parameter bounds in model
141141
space to cover given training data. This will make the modeling
142142
space larger than the search space if training data fall outside
143-
the search space.
143+
the search space. Will also include training points that violate
144+
parameter constraints in the modeling.
144145
fit_out_of_design: If specified, all training data are used.
145146
Otherwise, only in design points are used.
146147
fit_abandoned: Whether data for abandoned arms or trials should be
@@ -442,6 +443,8 @@ def _set_model_space(self, observations: list[Observation]) -> None:
442443
if isinstance(p, RangeParameter):
443444
p.lower = min(p.lower, min(param_vals[p.name]))
444445
p.upper = max(p.upper, max(param_vals[p.name]))
446+
# Remove parameter constraints from the model space.
447+
self._model_space.set_parameter_constraints([])
445448

446449
def _set_status_quo(
447450
self,

ax/modelbridge/tests/test_base_modelbridge.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from ax.core.observation import ObservationData, ObservationFeatures
2323
from ax.core.optimization_config import OptimizationConfig
2424
from ax.core.parameter import FixedParameter, ParameterType, RangeParameter
25+
from ax.core.parameter_constraint import SumConstraint
2526
from ax.core.search_space import SearchSpace
2627
from ax.exceptions.core import UnsupportedError, UserInputError
2728
from ax.modelbridge.base import (
@@ -1000,10 +1001,21 @@ def test_SetModelSpace(self) -> None:
10001001
experiment.attach_data(get_branin_data_batch(batch=trial, fill_vals=sq_vals))
10011002
trial.mark_completed()
10021003
data = experiment.lookup_data()
1004+
# Make search space with a parameter constraint
1005+
ss = experiment.search_space.clone()
1006+
ss.set_parameter_constraints(
1007+
[
1008+
SumConstraint(
1009+
parameters=list(ss.parameters.values()),
1010+
is_upper_bound=True,
1011+
bound=30.0,
1012+
)
1013+
]
1014+
)
10031015

10041016
# Check that SQ and custom are OOD
10051017
m = Adapter(
1006-
search_space=experiment.search_space,
1018+
search_space=ss,
10071019
model=None,
10081020
experiment=experiment,
10091021
data=data,
@@ -1014,10 +1026,11 @@ def test_SetModelSpace(self) -> None:
10141026
self.assertEqual(set(ood_arms), {"status_quo", "custom"})
10151027
self.assertEqual(m.model_space.parameters["x1"].lower, -5.0) # pyre-ignore[16]
10161028
self.assertEqual(m.model_space.parameters["x2"].upper, 15.0) # pyre-ignore[16]
1029+
self.assertEqual(len(m.model_space.parameter_constraints), 1)
10171030

10181031
# With expand model space, custom is not OOD, and model space is expanded
10191032
m = Adapter(
1020-
search_space=experiment.search_space,
1033+
search_space=ss,
10211034
model=None,
10221035
experiment=experiment,
10231036
data=data,
@@ -1027,10 +1040,11 @@ def test_SetModelSpace(self) -> None:
10271040
self.assertEqual(set(ood_arms), {"status_quo"})
10281041
self.assertEqual(m.model_space.parameters["x1"].lower, -20.0)
10291042
self.assertEqual(m.model_space.parameters["x2"].upper, 18.0)
1043+
self.assertEqual(m.model_space.parameter_constraints, [])
10301044

10311045
# With fill values, SQ is also in design, and x2 is further expanded
10321046
m = Adapter(
1033-
search_space=experiment.search_space,
1047+
search_space=ss,
10341048
model=None,
10351049
experiment=experiment,
10361050
data=data,
@@ -1039,6 +1053,7 @@ def test_SetModelSpace(self) -> None:
10391053
)
10401054
self.assertEqual(sum(m.training_in_design), 7)
10411055
self.assertEqual(m.model_space.parameters["x2"].upper, 20)
1056+
self.assertEqual(m.model_space.parameter_constraints, [])
10421057

10431058
@mock.patch(
10441059
"ax.modelbridge.base.observations_from_data",

0 commit comments

Comments
 (0)