def create_complex_mech(sigma1, sigma2, eps, coeffs): gm1 = ExactGaussianMechanism(sigma1, name='GM1') gm2 = ExactGaussianMechanism(sigma2, name='GM2') SVT = PureDP_Mechanism(eps=eps, name='SVT') # run gm1 for 3 rounds # run gm2 for 5 times # run SVT for once # compose them with the transformation: compose. compose = Composition() composed_mech = compose([gm1, gm2, SVT], coeffs) return composed_mech
def testcase_single_para(): test_case = [] # each test_case = {'noise_para','delta','eps'} range sigma from 1 to 100 sigma_list = [ int(1.6**i) for i in range(int(math.floor(math.log(100, 1.6))) + 1) ] for sigma in sigma_list: for delta in [1e-3, 1e-4, 1e-5, 1e-6]: gm = ExactGaussianMechanism(sigma, name='GM') cur_test = { 'sigma': sigma, 'delta': delta, 'eps': gm.get_approxDP(delta) } test_case.append(cur_test) return test_case
def testcase_multi_para(): """ create test cases when there are multi parameters (e.g., #coeff and sigma in Composed Gaussian mechanism) """ test_case = [] # each test_case = {'noise_para','delta','coeff','eps'} range sigma from 1 to 100, coeff is the number of composition sigma_list = [ int(1.6**i) for i in range(int(math.floor(math.log(100, 1.6))) + 1) ] for sigma in sigma_list: for coeff in [1, 10, 100, 1000]: for delta in [1e-3, 1e-4, 1e-5, 1e-6]: gm = ExactGaussianMechanism(sigma, name='GM') compose = Composition() composed_mech = compose([gm], [coeff]) cur_test = { 'sigma': sigma, 'delta': delta, 'coeff': coeff, 'eps': composed_mech.get_approxDP(delta) } test_case.append(cur_test) return test_case
sigma1 = 5 gm1 = GaussianMechanism(sigma1, phi_off=False, name='phi_GM1') compose = ComposeAFA() composed_mech = compose([gm1], [10]) delta1 = 1e-6 eps1 = composed_mech.get_approxDP(delta1) # RDP-based accountant. gm2 = GaussianMechanism(sigma1, name='rdp_GM2') compose_rdp = Composition() composed_mech_rdp = compose_rdp([gm2], [10]) #Exact Gaussian mechanism. gm3 = ExactGaussianMechanism(sigma1, name='exact_GM3') compose_exact = ComposeGaussian() composed_mech_exact = compose_exact([gm3], [10]) # Get name of the composed object, a structured description of the mechanism generated automatically print('Mechanism name is \"', composed_mech.name, '\"') print('Parameters are: ', composed_mech.params) print('epsilon(delta) = ', eps1, ', at delta = ', delta1) print('Results from rdp_based accountant, epsilon(delta) = ', composed_mech_rdp.get_approxDP(delta1), ', at delta = ', delta1) print('Results from AFA, epsilon(delta) = ', eps1, ', at delta = ', delta1) print('Results from exact Gaussian accountant, epsilon(delta) = ', composed_mech_exact.get_approxDP(delta1), ', at delta = ', delta1) ## Example 2: Composition of a heterogeneous sequence of mechanisms [Gaussian mechanism, randomized response ...]. """
from autodp.mechanism_zoo import ExactGaussianMechanism from autodp.transformer_zoo import Composition, ComposeGaussian import matplotlib.pyplot as plt sigma1 = 5.0 sigma2 = 8.0 gm1 = ExactGaussianMechanism(sigma1, name='GM1') gm2 = ExactGaussianMechanism(sigma2, name='GM2') # run gm1 for 3 rounds # run gm2 for 5 times # compose them with the transformation: compose and rdp_compose = Composition() rdp_composed_mech = rdp_compose([gm1, gm2], [3, 5]) compose = ComposeGaussian() composed_mech = compose([gm1, gm2], [3, 5]) # Query for eps given delta delta1 = 1e-6 eps1 = composed_mech.get_approxDP(delta1) eps1b = rdp_composed_mech.get_approxDP(delta1) delta2 = 1e-4 eps2 = composed_mech.get_approxDP(delta2) eps2b = rdp_composed_mech.get_approxDP(delta2) # Get name of the composed object, a structured description of the mechanism generated automatically print('Mechanism name is \"', composed_mech.name, '\"')
def exp5_subsample_fixed_eps(): """ Evaluate poisson subsample Gaussian mechanism sample probability = 0.02, fix delta to 1e-5 and compare epsilon over composition x axis is # composition y axis is epsilon(delta) Evaluate four methods BBGHS_RDP :eps_rdp Our phi-function lower bound: eps_phi_left Our phi-function upper bound: eps_phi_right Double quadrature:eps_quadrature """ delta = 1e-5 import pickle prob = 0.02 klist = [100 * i for i in range(2, 16)] doc = {} exp4_path = 'exp5.pkl' if os.path.exists(exp4_path): with open(exp4_path, 'rb') as f: doc = pickle.load(f) klist = klist[:] eps_phi_left = doc['phi_left'] eps_phi_right = doc['phi_right'] eps_rdp = doc['rdp'] eps_quarture = doc['quarture'] else: for sigma in [2]: eps_rdp = [] eps_phi_left = [] eps_phi_right = [] eps_quarture = [] for coeff in klist: gm1 = ExactGaussianMechanism(sigma, name='GM1') compose = Composition() poisson_sample = AmplificationBySampling(PoissonSampling=True) composed_mech = compose( [poisson_sample(gm1, prob, improved_bound_flag=True)], [coeff]) #phi_subsample_left = SubSampleGaussian(sigma, prob,coeff, CDF_off=False, lower_bound = True) #phi_subsample_right = SubSampleGaussian(sigma, prob,coeff, CDF_off=False, upper_bound = True) phi_quarture = SubSampleGaussian(sigma, prob, coeff, CDF_off=False) eps_rdp.append(composed_mech.approxDP(delta)) eps_quarture.append(phi_quarture.get_approxDP(delta)) #eps_phi_left.append(phi_subsample_left.approxDP(delta)) #eps_phi_right.append(phi_subsample_right.approxDP(delta)) print('eps using double quarture', eps_quarture) #print('eps using phi lower bound', eps_phi_left) #print('eps using phi right bound', eps_phi_right) print('eps using the optimal rdp conversion', eps_rdp) cur_result = {} cur_result['rdp'] = eps_rdp cur_result['phi_left'] = eps_phi_left cur_result['phi_right'] = eps_phi_right cur_result['quarture'] = eps_quarture with open(exp4_path, 'wb') as f: pickle.dump(cur_result, f) for sigma in [2]: naive_rdp = [] eps_optimal_rdp = [] for coeff in klist: gm1 = ExactGaussianMechanism(sigma, name='GM1') compose = Composition() poisson_sample = AmplificationBySampling(PoissonSampling=True) composed_mech = compose( [poisson_sample(gm1, prob, improved_bound_flag=True)], [coeff]) eps_optimal_rdp.append(composed_mech.approxDP(delta)) print('RDP optimal conversion', eps_optimal_rdp) print('quarture result', eps_quarture) # copy the results from fourier paper and our previous experimental results eps_quarture = [ 0.5732509555915974, 0.7058115513738935, 0.8194825434078763, 0.9209338664859984, 1.0136435019043732, 1.099702697374365, 1.1804867199047775, 1.2569025991868228, 1.3296691895163435, 1.3993259169003278, 1.4662601850161303, 1.5308113615711694, 1.5932321716160407, 1.6637669337344212 ] eps_phi_left = [ 0.5553297955867375, 0.6832218356617155, 0.7928056642133938, 0.8906191704210357, 0.9799696230766813, 1.0628838022920961, 1.1406664339350132, 1.2142613396519286, 1.2843523223848659, 1.3513924639580124, 1.4158316082377795, 1.4779534607841263, 1.5380153993392631, 1.5962516845946515 ] eps_phi_right = [ 0.5866220805156243, 0.7223973520962709, 0.8387942691051304, 0.9426878979377773, 1.0376345860832061, 1.1257547173351041, 1.2084450581608812, 1.2867150182217082, 1.3612194904959256, 1.4325246778969292, 1.5010566850456206, 1.567135674028485, 1.6310457295344567, 1.6929980332709857 ] fft_lower = [ 0.5738987073827246, 0.7070330939276875, 0.8213662927173179, 0.92358900507979, 1.0171625920742302, 1.1041565229625558, 1.1859259173798518, 1.2634158671679698, 1.3373168083154394, 1.4081514706603082, 1.4763269642671626, 1.54216775460533, 1.605937390055278, 1.667853467197358 ] fft_higher = [ 0.5738987073827246, 0.7070330939276875, 0.8213662927173179, 0.92358900507979, 1.0171625920742302, 1.1041565229625558, 1.1859259173798518, 1.2634158671679698, 1.3373168083154394, 1.4081514706603082, 1.4763269642671626, 1.54216775460533, 1.605937390055278, 1.667853467197358 ] import matplotlib.pyplot as plt #epsusingphi[1.7183697391746319e-06, 1.735096619083328e-06, 2.090003729609751e-06] #epsusingrdp[1.1702248059464182e-09, 4.4203574134371593e-10, 3.824438543631459e-10] props = fm.FontProperties(family='Gill Sans', fname='/Library/Fonts/GillSans.ttc') f, ax = plt.subplots() plt.figure(num=0, figsize=(12, 8), dpi=80, facecolor='w', edgecolor='k') #plt.plot(klist,naive_rdp, 'g.-.', linewidth=2) plt.plot(klist, eps_rdp, 'm.-.', linewidth=2) #plt.plot(klist, eps_optimal_rdp, 'y.-', linewidth=2) plt.plot(klist, eps_phi_left, 'cx-', linewidth=2) plt.plot(klist, eps_phi_right, 'rx-', linewidth=2) plt.plot(klist, eps_quarture, 'y.-', linewidth=2) plt.plot(klist, fft_lower, 'gs--', linewidth=1) plt.plot(klist, fft_higher, 'rs--', linewidth=1) #plt.plot(klist, doc['20']['rdp'], '--k', linewidth=2) #plt.plot(klist, doc['20']['eps'], '--r^', linewidth=2) plt.legend([ r'BBGHS_RDP', 'our AFA lower bound', 'our AFA higher bound', 'Double quadrature', 'FA lower bound', 'FA higher bound' ], loc='best', fontsize=17) plt.grid(True) plt.xticks(fontsize=22) plt.yticks(fontsize=22) plt.xlabel(r'Number of Compositions $k$', fontsize=22) plt.ylabel(r'$\epsilon$', fontsize=22) ax.set_title('Title', fontproperties=props) #plt.show() plt.savefig('exp4_eps.pdf', bbox_inches='tight')
def exp4_subsample_fixed_eps(): """ Evaluate poisson subsample Gaussian mechanism sample probability = 0.02, fix epsilon to 1.0 and compare delta over composition x axis is # composition y axis is delta(epsilon) Evaluate four methods BBGHS_RDP :eps_rdp Our phi-function lower bound: eps_phi_left Our phi-function upper bound: eps_phi_right Double quadrature:eps_quadrature """ eps = 1.0 import pickle prob = 0.02 klist = [100 * i for i in range(2, 16)] exp4_path = 'gamma_0.02_sigma_12.pkl' if os.path.exists(exp4_path): with open(exp4_path, 'rb') as f: doc = pickle.load(f) klist = klist[:] eps_phi_left = doc['phi_left'] eps_phi_right = doc['phi_right'] eps_rdp = doc['rdp'] eps_quarture = doc['quarture'] else: for sigma in [2]: eps_rdp = [] eps_phi_left = [] eps_phi_right = [] eps_quarture = [] for coeff in klist: gm1 = ExactGaussianMechanism(sigma, name='GM1') compose = Composition() poisson_sample = AmplificationBySampling(PoissonSampling=True) composed_mech = compose( [poisson_sample(gm1, prob, improved_bound_flag=True)], [coeff]) #uncomment the code below to run upper and lower bounds, which is much slower #phi_subsample_left = SubSampleGaussian(sigma, prob,coeff, CDF_off=False, lower_bound = True) #phi_subsample_right = SubSampleGaussian(sigma, prob,coeff, CDF_off=False, upper_bound = True) phi_quarture = SubSampleGaussian(sigma, prob, coeff, CDF_off=False) eps_rdp.append(composed_mech.approx_delta(eps)) eps_quarture.append(phi_quarture.get_approx_delta(eps)) #eps_phi_left.append(phi_subsample_left.approx_delta(eps)) #eps_phi_right.append(phi_subsample_right.approx_delta(eps)) print('eps using double quarture', eps_quarture) print('eps using phi lower bound', eps_phi_left) print('eps using phi right bound', eps_phi_right) print('eps using rdp', eps_rdp) cur_result = {} cur_result['rdp'] = eps_rdp #eps_phi = [8.126706321817492e-11, 1.680813696457811e-08, 3.7171456678093376e-07, 2.8469414374309687e-06, 1.2134517188197369e-05, 3.612046366420398e-05, 8.487142126792672e-05, 0.00016916885963894502] # previous experimental records for the sigma = 2.0, eps =1.0 cur_result['phi_left'] = [ 1.9705163375286992e-11, 6.54413434131078e-09, 1.8172415920878554e-07, 1.5912195465344071e-06, 7.408024600416465e-06, 2.3476597821679127e-05, 5.780615396550352e-05, 0.0001194871003954497, 0.00021761168363315566, 0.00036048564689211086, 0.0005551755399635068, 0.0008073269983187659, 0.0011211655514957834, 0.0014996039591825359 ] cur_result['phi_right'] = [ 1.4208450705963226e-10, 2.7065873453364222e-08, 5.615768975610223e-07, 4.101636149422114e-06, 1.6856443667586166e-05, 4.875023579764651e-05, 0.00011190249522187185, 0.00021878046437442066, 0.00038078926980138466, 0.0006074760381444841, 0.0009062357815770332, 0.0012823422696145335, 0.0017391548126395213, 0.0022783994671059515 ] #cur_result['phi_left'] = eps_phi_left #cur_result['phi_right'] = eps_phi_right cur_result['quarture'] = eps_quarture with open(exp4_path, 'wb') as f: pickle.dump(cur_result, f) # copy the results from Fourier accountant paper fft_lower = [ 7.887405682751439e-11, 1.621056159906838e-08, 3.547744440606434e-07, 2.6891898301208684e-06, 1.1344617219024322e-05, 3.342412117224878e-05, 7.773514229351955e-05, 0.00015336724020791973, 0.00026855202090630444, 0.00042999375546865035, 0.0006426099200177218, 0.0009095489321732455, 0.00123236372576394, 0.0016112544734264512 ] fft_higher = [ 8.195861133559092e-11, 1.7175792871794577e-08, 3.8343699421628997e-07, 2.9650469214763064e-06, 1.2761325748530785e-05, 3.836009767606709e-05, 9.10255425945141e-05, 0.0001832372011979862, 0.00032737944462639086, 0.0005348503868262945, 0.0008155844687884689, 0.0011778834943758018, 0.001628443617837156, 0.002172490405255 ] for sigma in [2]: eps_optimal_rdp = [] for coeff in klist: gm1 = ExactGaussianMechanism(sigma, name='GM1') compose = Composition() poisson_sample = AmplificationBySampling(PoissonSampling=True) composed_mech = compose( [poisson_sample(gm1, prob, improved_bound_flag=True)], [coeff]) eps_optimal_rdp.append(composed_mech.approx_delta(eps)) print('optimal conversion', eps_optimal_rdp) print('quarture result', eps_quarture) print('RDP result', eps_rdp) import matplotlib.pyplot as plt props = fm.FontProperties(family='Gill Sans', fname='/Library/Fonts/GillSans.ttc') f, ax = plt.subplots() plt.figure(num=0, figsize=(12, 8), dpi=80, facecolor='w', edgecolor='k') #plt.plot(klist,naive_rdp, 'g.-.', linewidth=2) plt.plot(klist, eps_rdp, 'm.-.', linewidth=2) plt.plot(klist, eps_optimal_rdp, 'y.-', linewidth=2) plt.plot(klist, eps_phi_left, 'cx--', linewidth=2) plt.plot(klist, eps_phi_right, 'rx--', linewidth=2) plt.plot(klist, eps_quarture, 'bx--', linewidth=2) plt.plot(klist, fft_lower, 'gs-', linewidth=1) plt.plot(klist, fft_higher, 'rs-', linewidth=1) plt.ylim([1e-12, 1e-1]) plt.yscale('log') #plt.plot(klist, doc['20']['rdp'], '--k', linewidth=2) #plt.plot(klist, doc['20']['eps'], '--r^', linewidth=2) plt.legend([ r'BBGHS_RDP_conversion', 'Optimal_RDP_Conversion', '$\phi$-function_lower', '$\phi$-function_upper', 'Double quadrature method', 'FA lower bound', 'FA higher bound' ], loc='best', fontsize=17) plt.grid(True) plt.xticks(fontsize=20) plt.yticks(fontsize=20) plt.xlabel( r'Number of Composition ($\epsilon=1.0, \sigma=2$, sample probability=$0.02$)', fontsize=20) plt.ylabel(r'$\delta$', fontsize=20) ax.set_title('Title', fontproperties=props) #plt.show() plt.savefig('exp4_delta.pdf', bbox_inches='tight')
def exp_2a(): eps_a = [] #standard SVT eps_e = [] #Laplace-SVT (via RDP) eps_g = [] #Gaussian SVT c>1 eps_g_c = [] #c=1 for Gaussian SVT eps_i = [] eps_kov = [] #generalized SVT eps_noisy = [] k_list = [int(1.4**i) for i in range(int(math.floor(math.log(n,1.4)))+1)] print(len(k_list)) query = np.zeros(n) rho = np.random.normal(scale=sigma_1) lap_rho = np.random.laplace(loc=0.0, scale=lambda_rho) """ compute eps for noisy screening p = Prob[ nu > Margin] q = Prob[ nu - 1 > margin] count_gau counts #tops in Gaussian-SVT count_lap counts #tops in Laplace-SVT """ count_gau = 0 count_lap = 0 # the following is for data-dependent screening in CVPR-20 p = scipy.stats.norm.logsf(margin, scale=sigma_2) q = scipy.stats.norm.logsf(margin + 1, scale=sigma_2) params = {} params['logp'] = p params['logq'] = q per_screen_mech = NoisyScreenMechanism(params, name='NoisyScreen') per_gaussian_mech = ExactGaussianMechanism(sigma_2,name='GM1') index = [] compose = Composition() for idx, qu in enumerate(query): nu = np.random.normal(scale=sigma_2) lap_nu = np.random.laplace(loc=0.0, scale=lambda_nu) if nu >= rho + margin: count_gau += 1 if lap_nu >= lap_rho + margin: count_lap += 1 count_gau = max(count_gau, 1) count_lap = max(count_lap, 1) if idx in k_list: index.append(idx) print('number of queries passing threshold', count_gau) #eps_a records the standard SVT eps_a.append(eps_1 * count_lap + eps_1) # compose data-dependent screening screen_mech = compose([per_screen_mech], [idx]) gaussian_mech = compose([per_gaussian_mech], [idx]) # standard SVT with RDP calculation param_lap_svt = {} param_lap_svt['b'] = lambda_rho param_lap_svt['k'] = idx param_lap_svt['c'] = count_lap lapsvtrdp_mech = LaplaceSVT_Mechanism(param_lap_svt) eps_e.append(lapsvtrdp_mech.get_approxDP(delta)) # stage-wise generalized SVT, k is the maximum length of each chunk k = int(idx / np.sqrt(count_gau)) generalized_mech = StageWiseMechanism({'sigma':sigma_1,'k':k, 'c':count_gau}) eps_kov.append(generalized_mech.get_approxDP(delta)) # Gaussian-SVT c>1 with RDP, k is the total length before algorithm stops gaussianSVT_c = GaussianSVT_Mechanism({'sigma':sigma_1,'k':idx, 'c':count_gau}, rdp_c_1=False) eps_g.append(gaussianSVT_c.get_approxDP(delta)) #Gaussian-SVT with c=1, we use average_k as the approximate maximum length of each chunk, margin is used in Proposition 10 average_k = int(idx / max(count_gau, 1)) params_SVT = {} params_SVT['k'] = average_k params_SVT['sigma'] = sigma_1 params_SVT['margin'] = margin per_gaussianSVT_mech = GaussianSVT_Mechanism(params_SVT) gaussianSVT_mech = compose([per_gaussianSVT_mech],[max(count_gau, 1)]) eps_g_c.append(gaussianSVT_mech.get_approxDP(delta)) eps_i.append(gaussian_mech.get_approxDP(delta)) # Gaussian Mechanism eps_noisy.append(screen_mech.get_approxDP(delta)) import matplotlib import matplotlib.pyplot as plt font = {'family': 'times', 'weight': 'bold', 'size': 18} props = fm.FontProperties(family='Gill Sans', fname='/Library/Fonts/GillSans.ttc') f, ax = plt.subplots() plt.figure(num=0, figsize=(12, 8), dpi=80, facecolor='w', edgecolor='k') plt.loglog(index, eps_a, '-r', linewidth=2) plt.loglog(index, eps_e, '--g^', linewidth=2) plt.loglog(index, eps_g, '-c^', linewidth=2) plt.loglog(index, eps_g_c, '-bs', linewidth=2) plt.loglog(index, eps_i, '--k', linewidth=2) plt.loglog(index, eps_noisy, color='brown', linewidth=2) plt.loglog(index, eps_kov, color='hotpink', linewidth=2) plt.legend( ['Laplace-SVT (Pure-DP from Lyu et al., 2017)', 'Laplace-SVT (via RDP)', 'Gaussian-SVT c>1 (RDP by Theorem 11)', 'Gaussian-SVT c=1 (RDP by Theorem 8)', 'Gaussian Mechanism', 'Noisy Screening (data-dependent RDP)', 'Stage-wise generalized SVT'], loc='best', fontsize=17) plt.grid(True) plt.xticks(fontsize=20) plt.yticks(fontsize=20) plt.xlabel(r'Iterations', fontsize=20) plt.ylabel(r'$\epsilon$', fontsize=20) ax.set_title('Title', fontproperties=props) plt.savefig('exp2a.pdf', bbox_inches='tight')
from autodp.mechanism_zoo import ExactGaussianMechanism, PureDP_Mechanism from autodp.transformer_zoo import Composition, AmplificationBySampling import matplotlib.pyplot as plt sigma1 = 5.0 sigma2 = 8.0 gm1 = ExactGaussianMechanism(sigma1, name='GM1') gm2 = ExactGaussianMechanism(sigma2, name='GM2') SVT = PureDP_Mechanism(eps=0.1, name='SVT') # run gm1 for 3 rounds # run gm2 for 5 times # run SVT for once # compose them with the transformation: compose. compose = Composition() poisson_sample = AmplificationBySampling(PoissonSampling=True) subsample = AmplificationBySampling(PoissonSampling=False) prob = 0.1 coeffs = [30, 50, 10] composed_mech = compose([gm1, gm2, SVT], coeffs) composed_poissonsampled_mech = compose([ poisson_sample(gm1, prob), poisson_sample(gm2, prob), poisson_sample(SVT, prob) ], coeffs)