Skip to content

feat(api): add Normal and LogNormal distributions to SearchSpace - #3908

Draft
sanskar-singh-2403 wants to merge 1 commit into
kubeflow:masterfrom
sanskar-singh-2403:feat/normal-lognormal-searchspace-3795
Draft

feat(api): add Normal and LogNormal distributions to SearchSpace#3908
sanskar-singh-2403 wants to merge 1 commit into
kubeflow:masterfrom
sanskar-singh-2403:feat/normal-lognormal-searchspace-3795

Conversation

@sanskar-singh-2403

Copy link
Copy Markdown
Contributor

What this PR does / why we need it

SearchSpace currently supports uniform, logUniform and categorical. All three are uninformative within their bounds: they can express where a hyperparameter lives, but not where it is likely to be. A practitioner who already knows a good region, from a previous run, a paper, or the shape of the architecture, has no way to say so, and every trial is spent re-discovering it.

This adds normal and logNormal as two further members of the union, so a prior can be expressed directly as a center and a spread:

  • NormalSpace is a Gaussian over mean with standard deviation stdDev, concentrating trials near mean while still allowing the tails.
  • LogNormalSpace is a distribution whose logarithm is normal, so mean and stdDev are in log space. Samples are therefore always positive and the spread is multiplicative, which is how positive-only hyperparameters such as learning rate or weight decay are actually reasoned about ("around 1e-3, within a factor of 3").
parameters:
  - name: lr
    searchSpace:
      logNormal:
        mean: "-6.9"     # log space, so exp(-6.9) is about 1e-3
        stdDev: "1.1"
  - name: warmup_fraction
    searchSpace:
      normal:
        mean: "0.06"
        stdDev: "0.02"

Both mirror the existing UniformSpace / LogUniformSpace shape and reuse the Double string type, which keeps numeric values out of the float round-tripping problems JSON and protobuf have, and validates them with the existing decimal pattern.

Design notes

mean is deliberately unconstrained. A Gaussian may legitimately be centered below zero, and for logNormal a negative mean is the common case since it is an exponent. There is a test asserting negative means are accepted, so a lower bound is not added later by mistake.

stdDev must be strictly positive, enforced by a CEL rule in the same XValidation style LogUniformSpace already uses. A zero standard deviation collapses the distribution to a point and a negative one is undefined. Rejecting it at admission keeps the failure next to the offending field rather than surfacing later from inside a suggestion container.

The ExactlyOneOf marker is extended to cover the two new members, so they are mutually exclusive with each other and with the existing three.

No ParameterType field on either struct. trainer_v1alpha1_normal_space.py and trainer_v1alpha1_log_normal_space.py were already generated into the Python API by #3552, but had no Go counterparts and were not referenced by SearchSpace. They declare exactly mean and stdDev, which is the field set generated here, so this wires up models that were already present rather than introducing a new shape. Both distributions are continuous, so a discrete/continuous type discriminator would not carry information. Happy to add one if reviewers prefer.

Grid search needed no new rule. The existing CEL rule requiring categorical parameters under grid already covers the new distributions, since grid enumerates a finite cartesian product that a continuous distribution cannot provide. Only its message needed updating, as it enumerated Uniform and LogUniform by name and would otherwise have gone stale. There is a test covering grid plus normal.

Scope

This is an API change only. Propagating the distributions into the suggestion backend is tracked separately in #3797, which is blocked on the gRPC contract in #3796; no .proto exists in the repository yet. Landing the types first gives that work a defined SearchSpace to map onto Optuna's FloatDistribution.

Testing

New envtest coverage in test/integration/webhooks/optimizationjob_test.go, 10 assertions, all passing against a real API server:

Case Expected
normal with valid mean and stdDev accepted
normal with negative mean accepted
logNormal with negative log-space mean accepted
normal with stdDev: "0" rejected
normal with negative stdDev rejected
logNormal with stdDev: "0" rejected
logNormal with negative stdDev rejected
normal with non-numeric stdDev rejected
normal and logNormal both set rejected
normal and uniform both set rejected
grid search with a normal parameter rejected

go build ./..., go vet and go test ./pkg/webhooks/... are clean.

Generated assets

CRDs, Helm chart CRD templates, deepcopy, openapi, apply configurations, swagger spec and Python API models are all regenerated via make generate.

Which issue(s) this PR fixes

Fixes #3795

Part of KEP-3562 (#3562).

Checklist

  • Regenerated assets are committed (make generate)
  • Unit / integration tests added
  • Commit is signed off (DCO)

SearchSpace supports uniform, logUniform and categorical distributions.
All three are uninformative within their bounds: they can express where a
hyperparameter lives, but not where it is likely to be. Practitioners who
already know a good region, from a previous run, a paper, or the shape of
the architecture, have no way to say so, and every trial is spent
re-discovering it.

Add Normal and LogNormal as two further members of the SearchSpace union
so a prior can be expressed directly as a center and a spread:

- NormalSpace is a Gaussian over Mean with standard deviation StdDev,
  concentrating trials near Mean while still allowing the tails.
- LogNormalSpace is a distribution whose logarithm is normal, so Mean and
  StdDev are in log space. Samples are therefore always positive and the
  spread is multiplicative, which is how positive-only hyperparameters
  such as learning rate or weight decay are actually reasoned about
  ("around 1e-3, within a factor of 3"). Mean may be negative there,
  since it is an exponent.

Both mirror the existing UniformSpace and LogUniformSpace shape and reuse
the Double string type, which keeps numeric values out of the float
round-tripping problems that JSON and protobuf have, and validates them
with the existing decimal pattern.

Mean is deliberately unconstrained: a Gaussian may legitimately be
centered below zero, and for LogNormal a negative Mean is the common
case. StdDev is constrained to be strictly positive by a CEL rule,
matching the XValidation style already used by LogUniformSpace, because
a zero standard deviation collapses the distribution to a point and a
negative one is undefined. Rejecting it at admission keeps the failure
next to the offending field instead of surfacing later from inside a
suggestion container.

The ExactlyOneOf marker on SearchSpace is extended to cover the two new
members, so they are mutually exclusive with each other and with the
existing three.

Two structs, trainer_v1alpha1_normal_space.py and
trainer_v1alpha1_log_normal_space.py, were already generated into the
Python API by kubeflow#3552 but had no Go counterparts and were not referenced by
SearchSpace. They declare exactly mean and stdDev, which is the field set
generated here, so this change wires up models that were already present
rather than introducing a new shape. Following those files, neither struct
carries a ParameterType: both distributions are continuous.

The pre-existing CEL rule requiring categorical parameters under grid
search already covers the new distributions, since grid enumerates a
finite cartesian product that a continuous distribution cannot provide.
Only its message needed updating, as it enumerated uniform and logUniform
by name and would otherwise have gone stale.

This is an API change only. Propagating the distributions into the
suggestion backend is tracked separately in kubeflow#3797, which is blocked on
the gRPC contract in kubeflow#3796; no .proto exists in the repository yet.
Landing the types first gives that work a defined SearchSpace to map onto
Optuna's FloatDistribution.

Add envtest coverage for both distributions: the accepted cases including
a negative normal mean and a negative log-space logNormal mean, the
rejected zero, negative and non-numeric stdDev, union violations against
each other and against uniform, and grid search with a continuous
parameter.

Regenerate the CRDs, Helm chart CRD templates, deepcopy, openapi, apply
configurations, swagger spec and Python API models.

Signed-off-by: Sanskar Singh <sanskarsinghty1234@gmail.com>
@google-oss-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign tenzen-y for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@robert-bell

Copy link
Copy Markdown
Member

Thanks for creating this @sanskar-singh-2403

I think we need to wait for #3828 and #3797 are finalised before we can move this forward. I think we should look to implement both the api changes and wiring up to optuna within the same pr.

/hold

@robert-bell robert-bell moved this from Needs Triage to Needs Discussion in Kubeflow Trainer Aug 28, 2026
@sanskar-singh-2403

Copy link
Copy Markdown
Contributor Author

Thanks for creating this @sanskar-singh-2403

I think we need to wait for #3828 and #3797 are finalised before we can move this forward. I think we should look to implement both the api changes and wiring up to optuna within the same pr.

/hold

Thanks @robert-bell, makes sense thus I kept this as draft and sure i will wire up optuna as well as soon as #3797 gets merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Needs Discussion

Development

Successfully merging this pull request may close these issues.

KEP-3562: [OptimizationJob] Add Normal and LogNormal distribution support to SearchSpace API

3 participants