From 9975ff700dc7a5406ae1adeb53dd04957a13065c Mon Sep 17 00:00:00 2001 From: Louis Tiao Date: Wed, 21 Oct 2026 20:22:49 -0700 Subject: [PATCH] Register Log10 for model configuration serialization Summary: # Why Saving a model configuration with BoTorch's native `Log10` input transform fails because the shared input-transform registry does not recognize the class. # Changes - Register BoTorch's native `Log10` input transform in the existing serialization registry. - Add a JSON round-trip test that preserves the transform class and its options in a `ModelConfig`. # Examples Input: ```python config = ModelConfig( input_transform_classes=[Log10], input_transform_options={"Log10": {"indices": [1]}}, ) ``` ## Before ```python object_to_json(config) # ValueError: Log10 is not in the Type[InputTransform] registry ``` ## After ```python restored = object_from_json(json.loads(json.dumps(object_to_json(config)))) assert restored == config ``` Differential Revision: D126825222 --- ax/storage/botorch_modular_registry.py | 2 ++ ax/storage/json_store/tests/test_json_store.py | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ax/storage/botorch_modular_registry.py b/ax/storage/botorch_modular_registry.py index 4dba5039f44..6cea569550c 100644 --- a/ax/storage/botorch_modular_registry.py +++ b/ax/storage/botorch_modular_registry.py @@ -88,6 +88,7 @@ InputPerturbation, InputTransform, LearnedFeatureImputation, + Log10, Normalize, Round, Warp, @@ -219,6 +220,7 @@ INPUT_TRANSFORM_REGISTRY: dict[type[InputTransform], str] = { ChainedInputTransform: "ChainedInputTransform", LearnedFeatureImputation: "LearnedFeatureImputation", + Log10: "Log10", Normalize: "Normalize", Round: "Round", Warp: "Warp", diff --git a/ax/storage/json_store/tests/test_json_store.py b/ax/storage/json_store/tests/test_json_store.py index 70928b484d4..9e3f11b9238 100644 --- a/ax/storage/json_store/tests/test_json_store.py +++ b/ax/storage/json_store/tests/test_json_store.py @@ -197,7 +197,7 @@ AdditiveMapSaasSingleTaskGP, EnsembleMapSaasSingleTaskGP, ) -from botorch.models.transforms.input import Normalize +from botorch.models.transforms.input import Log10, Normalize from botorch.models.transforms.outcome import Standardize from botorch.sampling.normal import SobolQMCNormalSampler from gpytorch.mlls.exact_marginal_log_likelihood import ExactMarginalLogLikelihood @@ -653,6 +653,14 @@ def test_EncodeDecode(self) -> None: else: raise e + def test_model_config_with_log10_roundtrip(self) -> None: + config = ModelConfig( + input_transform_classes=[Log10], + input_transform_options={"Log10": {"indices": [1]}}, + ) + decoded = object_from_json(json.loads(json.dumps(object_to_json(config)))) + self.assertEqual(decoded, config) + def test_EncodeDecode_dataclass_with_initvar(self) -> None: @dataclasses.dataclass class TestDataclass: