From 6e4c2d24687541edeb6092f59a93ef38200c7b8d Mon Sep 17 00:00:00 2001 From: Eddie de Leon Date: Mon, 22 Jun 2026 19:38:15 -0400 Subject: [PATCH 1/3] Add patch to len function. It now returns the number of steps --- benchmarks/run_benchmarks.py | 6 +++--- opacus/accountants/accountant.py | 12 ++++++------ opacus/accountants/gdp.py | 3 --- opacus/accountants/prv.py | 3 --- opacus/accountants/rdp.py | 3 --- opacus/tests/accountants_test.py | 24 ++++++++++++++++++++++++ 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/benchmarks/run_benchmarks.py b/benchmarks/run_benchmarks.py index b6761b1dd..98620c45a 100644 --- a/benchmarks/run_benchmarks.py +++ b/benchmarks/run_benchmarks.py @@ -19,9 +19,9 @@ from os.path import exists from typing import Any, Dict -from benchmarks.benchmark_layer import run_layer_benchmark -from benchmarks.layers import LayerType -from benchmarks.utils import get_layer_set, get_path, save_results +from benchmark.benchmark_layer import run_layer_benchmark +from benchmark.layers import LayerType +from benchmark.utils import get_layer_set, get_path, save_results logger = logging.getLogger(__name__) diff --git a/opacus/accountants/accountant.py b/opacus/accountants/accountant.py index 22695aac1..d55130c4a 100644 --- a/opacus/accountants/accountant.py +++ b/opacus/accountants/accountant.py @@ -51,12 +51,6 @@ def get_epsilon(self, delta: float, *args, **kwargs) -> float: """ pass - @abc.abstractmethod - def __len__(self) -> int: - """ - Number of optimization steps taken so far - """ - pass @classmethod @abc.abstractmethod @@ -66,6 +60,12 @@ def mechanism(cls) -> str: """ pass + def __len__(self) -> int: + """ + Number of optimization steps taken so far + """ + return sum(num_steps for _, _, num_steps in self.history) + def get_optimizer_hook_fn( self, sample_rate: float ) -> Callable[[DPOptimizer], None]: diff --git a/opacus/accountants/gdp.py b/opacus/accountants/gdp.py index 8a147ae09..26d6743f3 100644 --- a/opacus/accountants/gdp.py +++ b/opacus/accountants/gdp.py @@ -67,9 +67,6 @@ def get_epsilon(self, delta: float, poisson: bool = True, **kwargs) -> float: delta=delta, ) - def __len__(self): - return len(self.history) - @classmethod def mechanism(cls) -> str: return "gdp" diff --git a/opacus/accountants/prv.py b/opacus/accountants/prv.py index b1d09ebf6..d8a264028 100644 --- a/opacus/accountants/prv.py +++ b/opacus/accountants/prv.py @@ -157,6 +157,3 @@ def _get_domain( @classmethod def mechanism(cls) -> str: return "prv" - - def __len__(self): - return len(self.history) diff --git a/opacus/accountants/rdp.py b/opacus/accountants/rdp.py index 1697e3528..efa7d8e47 100644 --- a/opacus/accountants/rdp.py +++ b/opacus/accountants/rdp.py @@ -84,9 +84,6 @@ def get_epsilon( eps, _ = self.get_privacy_spent(delta=delta, alphas=alphas) return eps - def __len__(self): - return len(self.history) - @classmethod def mechanism(cls) -> str: return "rdp" diff --git a/opacus/tests/accountants_test.py b/opacus/tests/accountants_test.py index 165232948..0792f276f 100644 --- a/opacus/tests/accountants_test.py +++ b/opacus/tests/accountants_test.py @@ -129,6 +129,30 @@ def test_prv_accountant(self) -> None: epsilon = accountant.get_epsilon(delta=1e-5) self.assertAlmostEqual(epsilon, 6.777395712150674) + def test_len_counts_optimization_steps(self) -> None: + noise_multiplier = 1.5 + sample_rate = 0.04 + steps = 50 + + for accountant in (RDPAccountant(), GaussianAccountant(), PRVAccountant()): + for _ in range(steps): + accountant.step( + noise_multiplier=noise_multiplier, sample_rate=sample_rate + ) + self.assertEqual(len(accountant.history), 1) + self.assertEqual(len(accountant), steps) + + for accountant in (RDPAccountant(), PRVAccountant()): + for _ in range(steps): + accountant.step( + noise_multiplier=noise_multiplier, sample_rate=sample_rate + ) + accountant.step( + noise_multiplier=noise_multiplier * 2, sample_rate=sample_rate + ) + self.assertEqual(len(accountant.history), 2) + self.assertEqual(len(accountant), steps + 1) + def test_get_noise_multiplier_rdp_epochs(self) -> None: delta = 1e-5 sample_rate = 0.04 From 28dc92d2406e9a8ee0d4c8a5246e34b5baf6938b Mon Sep 17 00:00:00 2001 From: Eddie de Leon Date: Mon, 22 Jun 2026 19:39:52 -0400 Subject: [PATCH 2/3] Remove changes to run_benchmarks --- benchmarks/run_benchmarks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/run_benchmarks.py b/benchmarks/run_benchmarks.py index 98620c45a..b6761b1dd 100644 --- a/benchmarks/run_benchmarks.py +++ b/benchmarks/run_benchmarks.py @@ -19,9 +19,9 @@ from os.path import exists from typing import Any, Dict -from benchmark.benchmark_layer import run_layer_benchmark -from benchmark.layers import LayerType -from benchmark.utils import get_layer_set, get_path, save_results +from benchmarks.benchmark_layer import run_layer_benchmark +from benchmarks.layers import LayerType +from benchmarks.utils import get_layer_set, get_path, save_results logger = logging.getLogger(__name__) From 211f34945cb0146b76207ab8ead1f1a82b5741eb Mon Sep 17 00:00:00 2001 From: Eddie de Leon Date: Mon, 22 Jun 2026 19:41:02 -0400 Subject: [PATCH 3/3] Fix new lines to match original format --- opacus/accountants/accountant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opacus/accountants/accountant.py b/opacus/accountants/accountant.py index d55130c4a..a7471579d 100644 --- a/opacus/accountants/accountant.py +++ b/opacus/accountants/accountant.py @@ -51,7 +51,6 @@ def get_epsilon(self, delta: float, *args, **kwargs) -> float: """ pass - @classmethod @abc.abstractmethod def mechanism(cls) -> str: @@ -60,6 +59,7 @@ def mechanism(cls) -> str: """ pass + def __len__(self) -> int: """ Number of optimization steps taken so far