def dp_variance(mu_list, epsilon): """ Compute a differentially private variance. """ noisy_n = laplace_mech(mu_list.size, 0.3333333, 1.0) noisy_sum_sq = laplace_mech((mu_list * mu_list).sum(), 0.3333333, 100.0**2) noisy_sum = laplace_mech(mu_list.sum(), 0.33333333, 100.0) return noisy_sum_sq / noisy_n - (noisy_sum / noisy_n)**2
def above_threshold(querylist, T, epsilon, sensitivity=1.0, forward=True): """ Above threshold technique for a list of queries with a given sensitivity """ bud_share = epsilon / 3.0 noisy_T = laplace_mech(T, bud_share, sensitivity) noisy_answers = laplace_mech(querylist, bud_share, sensitivity) num_queries = len(querylist) myiter = range(num_queries) if forward else range(num_queries - 1, -1, -1) index = next((x for x in myiter if noisy_answers[x] >= noisy_T), None) return index
def noisy_max(answers: np.ndarray, epsilon: float, sensitivity: float): """ Implementation of the noisy max mechanism with gap using Laplace noise Given a set of queries, this mechanism will return the **index**, not the value, of the query that is probably largest. Args: answers (float or numpy array): the set of queries epsilon (float): the privacy budget sensitivity (float): the global sensitivity of the query """ noisy_answers = laplace_mech(answers, epsilon/2.0, sensitivity) return noisy_answers.argmax()
def matrix_mechanism(x, W, A, epsilon=1.0): ''' Implementation of the Matrix Mechanism. MM follows a “Select - Measure - Reconstruct” paradigm: given a set of target queries on which low accuracy is desired, these mechanisms Select an alternative set of queries, Measure estimated values of these alternative queries using the Laplace mechanism, and perform post-processing to optimally Reconstruct estimates to the original, target queries. Args: x (): W (): the query workload A (): the query strategy epsilon (float): the privacy budget ''' # y = noisy answers to the queries in A y = laplace_mech(A, x, epsilon) # reconstruct from y to get x_hat # x_hat = computed estimate of x that minimizes squared error = pseudo-inverse(A)*y Aplus = np.linalg.pinv(A) x_hat = y @ Aplus # return noisy workload answers: W * x_hat return W @ x_hat
def dp_mean(eps_n, eps_d, top, bot, top_sen=100.0, bot_sen=1.0): noisy_top = laplace_mech(top, eps_n, top_sen) noisy_bot = laplace_mech(bot, eps_d, bot_sen) return noisy_top / noisy_bot