privacy_engine_xl.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import torch
  2. import opacus
  3. from typing import List, Union
  4. import os
  5. def generate_noise(max_norm, parameter, noise_multiplier, noise_type, device):
  6. """
  7. A noise generation function that can utilize different distributions for noise generation.
  8. """
  9. if noise_multiplier > 0:
  10. mean = 0
  11. scale_scalar = noise_multiplier * max_norm
  12. scale = torch.full(size=parameter.shape, fill_value=scale_scalar, dtype=torch.float32, device=device)
  13. if noise_type.lower() in ["normal", "gauss", "gaussian"]:
  14. dist = torch.distributions.normal.Normal(mean, scale)
  15. elif noise_type.lower() in ["laplace", "laplacian"]:
  16. dist = torch.distributions.laplace.Laplace(mean, scale)
  17. elif noise_type.lower() in ["exponential"]:
  18. rate = 1 / scale
  19. dist = torch.distributions.exponential.Exponential(rate)
  20. else:
  21. dist = torch.distributions.normal.Normal(mean, scale)
  22. noise = dist.sample()
  23. return noise
  24. return 0.0
  25. # Server side Noise
  26. def apply_noise(weights, batch_size, noise_multiplier, noise_type, device, loss_reduction="mean"):
  27. """
  28. A function for applying noise to weights on the (intermediate) server side that utilizes the generate_noise function above.
  29. """
  30. for p in weights.values():
  31. noise = generate_noise(0, p, noise_multiplier, noise_type, device)
  32. if loss_reduction == "mean":
  33. noise /= batch_size
  34. p += noise
  35. # Client side Noise
  36. class PrivacyEngineXL(opacus.PrivacyEngine):
  37. """
  38. A privacy engine that can utilize different distributions for noise generation, based on opacus' privacy engine.
  39. It gets attached to the optimizer just like the privacy engine from opacus.
  40. """
  41. def __init__(
  42. self,
  43. module: torch.nn.Module,
  44. batch_size: int,
  45. sample_size: int,
  46. alphas: List[float],
  47. noise_multiplier: float,
  48. max_grad_norm: Union[float, List[float]],
  49. secure_rng: bool = False,
  50. grad_norm_type: int = 2,
  51. batch_first: bool = True,
  52. target_delta: float = 1e-6,
  53. loss_reduction: str = "mean",
  54. noise_type: str="gaussian",
  55. **misc_settings
  56. ):
  57. import warnings
  58. if secure_rng:
  59. warnings.warn(
  60. "Secure RNG was turned on. However it is not yet implemented for the noise distributions of privacy_engine_xl."
  61. )
  62. opacus.PrivacyEngine.__init__(
  63. self,
  64. module,
  65. batch_size,
  66. sample_size,
  67. alphas,
  68. noise_multiplier,
  69. max_grad_norm,
  70. secure_rng,
  71. grad_norm_type,
  72. batch_first,
  73. target_delta,
  74. loss_reduction,
  75. **misc_settings)
  76. self.noise_type = noise_type
  77. def _generate_noise(self, max_norm, parameter):
  78. return generate_noise(max_norm, parameter, self.noise_multiplier, self.noise_type, self.device)