-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsamplers.py
More file actions
152 lines (120 loc) · 5 KB
/
Copy pathsamplers.py
File metadata and controls
152 lines (120 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import numpy as np
import pandas as pd
from utils import (epsilon2r,
epsilon2scale,
adp2epsilon_optim,
r2epsilon)
class DirichletMechanism:
def __init__(self, epsilon, prior=1, lambda_=2, Delta_2sq=2, Delta_inf=1):
self.epsilon = epsilon
self.lambda_ = lambda_
self.Delta_2sq = Delta_2sq
self.Delta_inf = Delta_inf
self.prior = prior
self.r = epsilon2r(self.epsilon,
self.prior,
self.lambda_,
self.Delta_2sq,
self.Delta_inf)
self.alpha = self.prior + 4*(self.lambda_-1)*self.r*self.Delta_inf
def sample(self, x, seed=None):
r = np.random.default_rng(seed).standard_gamma(self.r*np.array(x)+self.alpha)
return r / r.sum(-1, keepdims=True)
def sample_series(self, x, seed=None):
r = np.random.default_rng(seed).standard_gamma(self.r*np.array(x)+self.alpha)
r = r / r.sum(-1, keepdims=True)
return pd.Series(r, index=x.index)
def set_epsilon(self, new_epsilon):
self.epsilon = new_epsilon
self.r = epsilon2r(self.epsilon,
self.prior,
self.lambda_,
self.Delta_2sq,
self.Delta_inf)
self.alpha = self.prior + (self.lambda_-1)*self.r*self.Delta_inf
def set_lambda(self, new_lambda):
self.lambda_ = new_lambda
self.r = epsilon2r(self.epsilon,
self.prior,
self.lambda_,
self.Delta_2sq,
self.Delta_inf)
self.alpha = self.prior + (self.lambda_-1)*self.r*self.Delta_inf
def set_r(self, r):
self.r = r
self.epsilon = r2epsilon(self.r,
self.prior,
self.lambda_,
self.Delta_2sq,
self.Delta_inf)
self.alpha = self.prior + 4*(self.lambda_-1)*self.r*self.Delta_inf
def get_alpha(self):
return self.alpha
def set_dp_epsilon(self, eps_hat, delta):
self.epsilon = adp2epsilon_optim(eps_hat, delta)
self.lambda_ = 1 / self.epsilon + 1
self.r = epsilon2r(self.epsilon,
self.prior,
self.lambda_,
self.Delta_2sq,
self.Delta_inf)
self.alpha = self.prior + (self.lambda_-1)*self.r*self.Delta_inf
class GaussianMechanism:
def __init__(self, epsilon, lambda_=2, Delta_2sq=2):
self.epsilon = epsilon
self.lambda_ = lambda_
self.Delta_2sq = Delta_2sq
self.sigma = np.sqrt(self.lambda_*self.Delta_2sq/(2*self.epsilon))
def sample(self, x, tol=1e-6, seed=None):
p = np.clip(x+np.random.default_rng(seed).normal(0, self.sigma, np.shape(x)), a_min=tol, a_max=None)
p = p/p.sum(-1, keepdims=True)
return p
def sample_series(self, x, tol=1e-6, seed=None):
p = np.clip(x+np.random.default_rng(seed).normal(0, self.sigma, np.shape(x)), a_min=tol, a_max=None)
p = p/p.sum()
return p
def set_epsilon(self, new_epsilon):
self.epsilon = new_epsilon
self.sigma = np.sqrt(self.lambda_*self.Delta_2sq/(2*self.epsilon))
def get_sigma(self):
return self.sigma
def set_dp_epsilon(self, eps_hat, delta):
self.epsilon = None
self.lambda_ = None
self.sigma = np.sqrt(2 * np.log(1.25/delta) * self.Delta_2sq) / eps_hat
class LaplaceMechanism:
def __init__(self, epsilon, lambda_=2, Delta_1=2, d=None):
self.epsilon = epsilon
self.lambda_ = lambda_
self.Delta_1 = Delta_1
self.d = d
self.scale = epsilon2scale(self.epsilon, self.lambda_, self.Delta_1)
def sample(self, x, tol=1e-6, seed=None):
p = np.clip(x+np.random.default_rng(seed).laplace(0, self.scale, np.shape(x)), a_min=tol, a_max=None)
p = p/p.sum(-1, keepdims=True)
return p
def sample_series(self, x, tol=1e-6, seed=None):
p = np.clip(x+np.random.default_rng(seed).laplace(0, self.scale, np.shape(x)), a_min=tol, a_max=None)
p = p/p.sum()
return p
def set_rho(self, new_epsilon):
self.epsilon = new_epsilon
self.scale = self.Delta_1*np.sqrt(self.lambda_/(2*self.epsilon))
def get_scale(self):
return self.scale
def set_dp_epsilon(self, eps_hat, delta):
self.epsilon = None
self.lambda_ = None
self.scale = self.Delta_1 / eps_hat
self.scale *= np.sqrt(np.log(0.5 / delta) / np.log(1 / delta))
class MLECalculator:
def __init__(self, prior):
self.prior = prior
def sample(self, x, seed=None):
p = x + self.prior
p = p/p.sum(-1, keepdims=True)
return p
def sample_series(self, x, seed=None):
p = x + self.prior
p = p/p.sum()
return p