Skip to content

Commit ec63d73

Browse files
vizier-teamcopybara-github
vizier-team
authored andcommitted
Update the Eagle Strategy to support multiplicative continuous feature perturbation.
PiperOrigin-RevId: 723098266
1 parent 7ce0ae8 commit ec63d73

File tree

2 files changed

+93
-7
lines changed

2 files changed

+93
-7
lines changed

vizier/_src/algorithms/optimizers/eagle_strategy.py

+36-7
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ class MutateNormalizationType(enum.IntEnum):
9797
UNNORMALIZED = 2
9898

9999

100+
@enum.unique
101+
class ContinuousFeaturePerturbationType(enum.IntEnum):
102+
"""The type of perturbation to apply to continuous features."""
103+
104+
# Add the perturbation to the feature value.
105+
ADDITIVE = 0
106+
# Multiply the feature value by exp(perturbation).
107+
MULTIPLICATIVE = 1
108+
109+
100110
@struct.dataclass
101111
class EagleStrategyConfig:
102112
"""Eagle Strategy optimizer config.
@@ -106,6 +116,8 @@ class EagleStrategyConfig:
106116
gravity: The maximum amount of attraction pull.
107117
negative_gravity: The maximum amount of repulsion pull.
108118
perturbation: The default amount of noise for perturbation.
119+
continuous_feature_perturbation_type: The type of perturbation to apply to
120+
continuous features.
109121
categorical_perturbation_factor: A factor to apply on categorical params.
110122
pure_categorical_perturbation_factor: A factor on purely categorical space.
111123
prob_same_category_without_perturbation: Baseline probability of selecting
@@ -130,6 +142,9 @@ class EagleStrategyConfig:
130142
negative_gravity: float = 0.008
131143
# Perturbation
132144
perturbation: float = 0.16
145+
continuous_feature_perturbation_type: ContinuousFeaturePerturbationType = (
146+
ContinuousFeaturePerturbationType.ADDITIVE
147+
)
133148
categorical_perturbation_factor: float = 1.0
134149
pure_categorical_perturbation_factor: float = 30
135150
prob_same_category_without_perturbation: float = 0.98
@@ -873,14 +888,28 @@ def _create_features(
873888
features_changes_continuous = jnp.matmul(
874889
scale, flat_features
875890
) - flat_features_batch * jnp.sum(scale, axis=-1, keepdims=True)
876-
877-
new_features_continuous = (
878-
features_batch.continuous
879-
+ jnp.reshape(
880-
features_changes_continuous, features_batch.continuous.shape
881-
)
882-
+ perturbations_batch.continuous
891+
moved_features_continuous = features_batch.continuous + jnp.reshape(
892+
features_changes_continuous, features_batch.continuous.shape
883893
)
894+
if (
895+
self.config.continuous_feature_perturbation_type
896+
== ContinuousFeaturePerturbationType.ADDITIVE
897+
):
898+
new_features_continuous = (
899+
moved_features_continuous + perturbations_batch.continuous
900+
)
901+
elif (
902+
self.config.continuous_feature_perturbation_type
903+
== ContinuousFeaturePerturbationType.MULTIPLICATIVE
904+
):
905+
new_features_continuous = moved_features_continuous * jnp.exp(
906+
perturbations_batch.continuous
907+
)
908+
else:
909+
raise ValueError(
910+
"Unsupported continuous feature perturbation type:"
911+
f" {self.config.continuous_feature_perturbation_type}"
912+
)
884913
if self.max_categorical_size > 0:
885914
features_categorical_logits = (
886915
self._create_categorical_feature_logits(

vizier/_src/algorithms/optimizers/eagle_strategy_test.py

+57
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
from absl.testing import absltest
3232

3333
tfd = tfp.distributions
34+
ContinuousFeaturePerturbationType = (
35+
eagle_strategy.ContinuousFeaturePerturbationType
36+
)
3437

3538

3639
def _create_logits_vector_simple(
@@ -437,6 +440,60 @@ def test_optimize_with_eagle(self):
437440
score_fn=lambda x, _: -jnp.sum(x.continuous.padded_array, 1), count=1
438441
)
439442

443+
def test_continuous_feature_perturbation_type(self):
444+
optimizer_additive_perturbation = vb.VectorizedOptimizerFactory(
445+
strategy_factory=eagle_strategy.VectorizedEagleStrategyFactory(
446+
eagle_config=eagle_strategy.EagleStrategyConfig(
447+
continuous_feature_perturbation_type=(
448+
ContinuousFeaturePerturbationType.ADDITIVE
449+
)
450+
)
451+
),
452+
max_evaluations=50,
453+
)(self.converter)
454+
expected_count = 4
455+
new_features_additive_perturbation = optimizer_additive_perturbation(
456+
score_fn=lambda x, _: -jnp.sum(x.continuous.padded_array, 1),
457+
count=expected_count,
458+
).features
459+
self.assertSequenceEqual(
460+
new_features_additive_perturbation.continuous.shape,
461+
(expected_count, 1, 2),
462+
)
463+
self.assertSequenceEqual(
464+
new_features_additive_perturbation.categorical.shape,
465+
(expected_count, 1, 2),
466+
)
467+
optimizer_mult_perturbation = vb.VectorizedOptimizerFactory(
468+
strategy_factory=eagle_strategy.VectorizedEagleStrategyFactory(
469+
eagle_config=eagle_strategy.EagleStrategyConfig(
470+
continuous_feature_perturbation_type=(
471+
ContinuousFeaturePerturbationType.MULTIPLICATIVE
472+
)
473+
)
474+
),
475+
max_evaluations=50,
476+
)(self.converter)
477+
new_features_mult_perturbation = optimizer_mult_perturbation(
478+
score_fn=lambda x, _: -jnp.sum(x.continuous.padded_array, 1),
479+
count=expected_count,
480+
).features
481+
self.assertSequenceEqual(
482+
new_features_mult_perturbation.continuous.shape,
483+
(expected_count, 1, 2),
484+
)
485+
self.assertSequenceEqual(
486+
new_features_mult_perturbation.categorical.shape,
487+
(expected_count, 1, 2),
488+
)
489+
self.assertGreater(
490+
np.abs(
491+
new_features_additive_perturbation.continuous
492+
- new_features_mult_perturbation.continuous
493+
).max(),
494+
1e-1,
495+
)
496+
440497
def test_optimize_with_eagle_continuous_only(self):
441498
problem = vz.ProblemStatement()
442499
root = problem.search_space.select_root()

0 commit comments

Comments
 (0)