Skip to content

Commit

Permalink
feat: each step sampled mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
Dariush Wahdany committed Jan 8, 2024
1 parent d709190 commit 72ce727
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
14 changes: 12 additions & 2 deletions src/dp_learning_ff/mean_estimation/coinpress.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ def __init__(
dist: Optional[str] = None,
Ps: Optional[Iterable[float]] = None,
p_sampling: float = 1,
sample_each_step: bool = False,
seed: int = 42,
order: float = 1,
verbose: bool = False,
):
self.epsilon = epsilon
self.delta = delta
Expand All @@ -26,8 +28,10 @@ def __init__(
self.steps = steps
self.Ps = Ps
self.p_sampling = p_sampling
self.sample_each_step = sample_each_step
self.seed = seed
self.mechanism = None
self.verbose = verbose

def prototypes(self, train_preds, train_targets):
if self.mechanism is None:
Expand All @@ -38,6 +42,7 @@ def prototypes(self, train_preds, train_targets):
self.mechanism.params["Ps"],
seed=self.seed,
subsampling=self.p_sampling,
sample_each_step=self.sample_each_step,
poisson_sampling=True,
)

Expand Down Expand Up @@ -139,11 +144,12 @@ def scaled_mechanism(scale):
dist=self.dist,
ord=self.order,
p_sampling=self.p_sampling,
sample_each_step=self.sample_each_step,
name="ScaledCoinpressGM",
)

calibrated_mechanism = calibrate_single_param(
scaled_mechanism, self.epsilon, self.delta
scaled_mechanism, self.epsilon, self.delta, verbose=self.verbose
)
epsilon = calibrated_mechanism.get_approxDP(self.delta)
print(
Expand All @@ -165,11 +171,12 @@ def scaled_mechanism(scale):
scale=scale,
Ps=self.Ps,
p_sampling=self.p_sampling,
sample_each_step=self.sample_each_step,
name="ScaledCoinpressGM",
)

calibrated_mechanism = calibrate_single_param(
scaled_mechanism, self.epsilon, self.delta
scaled_mechanism, self.epsilon, self.delta, verbose=self.verbose
)
epsilon = calibrated_mechanism.get_approxDP(self.delta)
print(
Expand Down Expand Up @@ -205,6 +212,7 @@ def give_private_prototypes(
Ps: np.ndarray,
seed: int = 42,
subsampling: float = 1.0,
sample_each_step: bool = False,
poisson_sampling: bool = True,
):
"""Returns a private prototype for each class.
Expand All @@ -221,6 +229,8 @@ def give_private_prototypes(
Returns:
np.ndarray: (k, d)-array containing the private prototypes for each class.
"""
if sample_each_step:
raise NotImplementedError("Sampling each step is not implemented")
targets = np.unique(train_targets)
train_preds_sorted = [
train_preds[train_targets == target].copy() for target in targets
Expand Down
28 changes: 23 additions & 5 deletions src/dp_learning_ff/mechanisms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
import numpy as np
from autodp.autodp_core import Mechanism
from autodp.mechanism_zoo import GaussianMechanism, zCDP_Mechanism
from autodp.transformer_zoo import AmplificationBySampling, ComposeGaussian
from autodp.transformer_zoo import AmplificationBySampling, ComposeGaussian, Composition

from .utils import binary_optimize


class CoinpressGM(Mechanism):
def __init__(self, Ps: list, p_sampling: float = 1, name: str = "CoinpressGM"):
def __init__(
self,
Ps: list,
p_sampling: float = 1,
sample_each_step: bool = False,
name: str = "CoinpressGM",
):
"""
Initialize the CoinpressGM object.
Expand All @@ -28,8 +34,16 @@ def __init__(self, Ps: list, p_sampling: float = 1, name: str = "CoinpressGM"):
compose = ComposeGaussian()
mech = compose(mechanisms, [1 for _ in mechanisms])
if p_sampling < 1:
preprocessing = AmplificationBySampling()
mech = preprocessing.amplify(mech, p_sampling)
preprocessing = AmplificationBySampling(PoissonSampling=True)
if sample_each_step:
compose = Composition()
mechanisms = [
preprocessing.amplify(mech, p_sampling, improved_bound_flag=True)
for mech in mechanisms
]
mech = compose(mechanisms, [1 for _ in mechanisms])
else:
mech = preprocessing.amplify(mech, p_sampling)
self.set_all_representation(mech)


Expand All @@ -41,6 +55,7 @@ def __init__(
dist: Literal["lin", "exp", "log", "eq"] = "exp",
ord: float = 1,
p_sampling: float = 1,
sample_each_step: bool = False,
name="ScaledCoinpressGM",
Ps: Optional[Iterable[float]] = None,
):
Expand All @@ -60,6 +75,7 @@ def __init__(
assert steps > 0, "steps must be positive"

self.scale = scale
self.sample_each_step = sample_each_step
if Ps is not None:
Ps = [scale * p for p in Ps]
elif dist == "lin":
Expand All @@ -70,7 +86,9 @@ def __init__(
Ps = [math.pow(scale * math.log(t + 1), ord) for t in range(steps)]
elif dist == "eq":
Ps = [scale] * steps
super().__init__(name=name, p_sampling=p_sampling, Ps=Ps)
super().__init__(
name=name, p_sampling=p_sampling, sample_each_step=sample_each_step, Ps=Ps
)


class LeastSquaresCDPM(Mechanism):
Expand Down

0 comments on commit 72ce727

Please sign in to comment.