Skip to content

Conversation

@Aaditya93
Copy link

Title
Add get_noise_multiplier(model) API to expose calculated noise multiplier (Fixes #26)

Description
Fixes #26 — When DPKerasConfig.noise_multiplier is None, the auto-calculated value was not accessible because the config is immutable.
This update introduces a public API to retrieve the effective noise multiplier from a DP-wrapped Keras model.

What Changed

  • Added get_noise_multiplier(model: keras.Model) in keras_api.py
    • Returns explicit or auto-calculated value
    • Raises a clear error for non-DP models
  • Added precomputation and caching of noise multiplier in make_private() to prevent double-calculation
  • Exported get_noise_multiplier in jax_privacy/keras/init.py
  • Added unit tests for:
    • Explicit noise multiplier retrieval
    • Auto-calculated noise multiplier retrieval
    • Error handling for non-DP models
  • Updated examples to demonstrate API usage

Why
Maintains DPKerasConfig immutability while giving users a simple, reliable way to log or inspect the effective noise multiplier for transparency and debugging.

Testing

  • New unit tests added and passing locally
  • Example confirms noise multiplier is correctly printed before training
  • No breaking changes to existing APIs

- Add public API to retrieve calculated noise multiplier
- Maintain DPKerasConfig immutability
- Add comprehensive unit tests
- Update example with usage demonstration
- Pre-calculate noise multiplier in make_private for efficiency

Addresses user feedback about accessing auto-calculated noise multiplier for logging purposes.
@google-cla
Copy link

google-cla bot commented Nov 1, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@RamSaw RamSaw self-requested a review November 4, 2025 15:42
Copy link
Collaborator

@RamSaw RamSaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for such a great contribution!

In general LGTM but left few minor comments.

In PR description you write that you update examples, but in PR changed files there are no changes to examples. Not saying that it is necessary, without it PR is also fine, but just doulbe checking in case you forgot to push a commit with these changes.

# that updates the metrics variables for DP-SGD training.

# Pre-calculate noise multiplier if not provided
if params.noise_multiplier is None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we should remove

noise_multiplier = (
      dp_params.noise_multiplier
      if dp_params.noise_multiplier is not None
      else dp_params.update_with_calibrated_noise_multiplier().noise_multiplier
  )

in _noised_clipped_grads function

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Since make_private guarantees that noise_multiplier is initialized, I went ahead and replaced the conditional logic with an assertion to keep things cleaner.


# Otherwise, calculate it (this will use the cached value if already computed)
updated_params = dp_params.update_with_calibrated_noise_multiplier()
return updated_params.noise_multiplier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add a new line in the end of the file

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that. Fixed

dp_params = model._dp_params # pylint: disable=protected-access

# If noise_multiplier was provided, return it directly
if dp_params.noise_multiplier is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we come here only if make_private was called, then it means dp_params must have noise multiplier, so we can just return here asserting that it is not None.

if dp_params.noise_multiplier is not None:
return dp_params.noise_multiplier

# Otherwise, calculate it (this will use the cached value if already computed)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just fyi, there is no caching because it is not cached property

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh got it.

model = keras_api.make_private(model, params)
retrieved_noise_mult = keras_api.get_noise_multiplier(model)

self.assertIsInstance(retrieved_noise_mult, float)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it really necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — this check is probably redundant since get_noise_multiplier is already type-hinted to return a float.

@RamSaw
Copy link
Collaborator

RamSaw commented Nov 4, 2025

Also, to merge you need to sign CLA.

@Aaditya93
Copy link
Author

Thanks for the feedback, This is my first open source contribution, so I appreciate you taking the time to review it. I've pushed the fix.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide a way to get the calculated noise multiplier through public Keras API

2 participants