def compute_reverse_KL(dnm, res): samples = np.load('results/' + dnm + '_samples.npy') samples = np.hstack((samples[:, 1:], samples[:, 0][:, np.newaxis])) mup = samples.mean(axis=0) Sigp = np.cov(samples, rowvar=False) M = res['mus'].shape[0] - 1 kl = np.zeros(M + 1) for m in range(M + 1): mul = res['mus'][m, :] Sigl = res['Sigs'][m, :, :] kl[m] = gaussian.gaussian_KL(mul, np.linalg.inv(Sigl), mup, Sigp) # kl = kl[2:][::plot_every] return kl
#get laplace approximations for each weight setting, and KL divergence to full posterior laplace approx mup Sigp #used for a quick/dirty performance comparison without expensive posterior sample comparisons (e.g. energy distance) mus_laplace = np.zeros((M + 1, D)) Sigs_laplace = np.zeros((M + 1, D, D)) rkls_laplace = np.zeros(M + 1) fkls_laplace = np.zeros(M + 1) print( 'Computing coreset Laplace approximation + approximate KL(posterior || coreset laplace)' ) for m in range(M + 1): mul, LSigl, LSiglInv = get_laplace(w[m], p[m], Z.mean(axis=0)[:D], diag=True) mus_laplace[m, :] = mul Sigs_laplace[m, :, :] = LSigl.dot(LSigl.T) rkls_laplace[m] = gaussian.gaussian_KL(mul, Sigs_laplace[m, :, :], mup, LSigpInv.T.dot(LSigpInv)) fkls_laplace[m] = gaussian.gaussian_KL(mup, Sigp, mul, LSiglInv.T.dot(LSiglInv)) #save results f = open('results/' + dnm + '_' + alg + '_results_' + ID + '.pk', 'wb') if alg != 'DPBPSVI': res = (cputs, w, p, mus_laplace, Sigs_laplace, rkls_laplace, fkls_laplace) else: res = (cputs, w, p, mus_laplace, Sigs_laplace, rkls_laplace, fkls_laplace, dpbpsvi.get_privacy_params()) pk.dump(res, f) f.close()
if alg != 'PRIOR': coreset.build(1, m) # record time and weights cputs[m] = time.perf_counter() - t0 w, idcs = coreset.weights() wts[m, idcs] = w # get laplace approximations for each weight setting, and KL divergence to full posterior laplace approx mup Sigp # used for a quick/dirty performance comparison without expensive posterior sample comparisons (e.g. energy distance) mus_laplace = np.zeros((M + 1, D)) Sigs_laplace = np.zeros((M + 1, D, D)) kls_laplace = np.zeros(M + 1) print( 'Computing coreset Laplace approximation + approximate KL(posterior || coreset laplace)' ) for m in range(M + 1): mul, Sigl = get_laplace(wts[m, :], Z, Z.mean(axis=0)[:D]) mus_laplace[m, :] = mul Sigs_laplace[m, :, :] = Sigl kls_laplace[m] = gaussian.gaussian_KL(mup, Sigp, mul, np.linalg.inv(Sigl)) # save results np.savez('results/' + dnm + '_' + alg + '_results_' + str(ID) + '.npz', cputs=cputs, wts=wts, Ms=np.arange(M + 1), mus=mus_laplace, Sigs=Sigs_laplace, kls=kls_laplace)
for wts, pts, _ in res: w.append(wts) p.append(pts) else: for m in range(1, M + 1): print('trial: ' + str(tr) + ' alg: ' + nm + ' ' + str(m) + '/' + str(M)) alg.build(1) #store weights/pts wts, pts, _ = alg.get() w.append(wts) p.append(pts) # computing kld and saving results muw = np.zeros((M + 1, mu0.shape[0])) Sigw = np.zeros((M + 1, mu0.shape[0], mu0.shape[0])) rklw = np.zeros(M + 1) fklw = np.zeros(M + 1) for m in range(M + 1): muw[m, :], LSigw, LSigwInv = gaussian.weighted_post( mu0, Sig0inv, Siginv, p[m], w[m]) Sigw[m, :, :] = LSigw.dot(LSigw.T) rklw[m] = gaussian.gaussian_KL(muw[m, :], Sigw[m, :, :], mup, SigpInv) fklw[m] = gaussian.gaussian_KL(mup, Sigp, muw[m, :], LSigwInv.T.dot(LSigwInv)) f = open(results_fldr + '/results_' + nm + '_' + str(tr) + '.pk', 'wb') res = (x, mu0, Sig0, Sig, mup, Sigp, w, p, muw, Sigw, rklw, fklw) pk.dump(res, f) f.close()
############################## ############################## # Normally at this point we'd run posterior inference on the coreset # But for this (illustrative) example we will evaluate quality via Laplace posterior approx print('Evaluating coreset quality...') w = np.zeros(N) w[idcs] = wts # compute error using laplace approx res = minimize(lambda mu: -log_joint(Z, mu, w), Z.mean(axis=0), jac=lambda mu: -grad_log_joint(Z, mu, w)) muw = res.x # then find a quadratic expansion around the mode, and assume the distribution is Gaussian covw = -np.linalg.inv(hess_log_joint_w(Z, muw, w)) print('Done!') # compare posterior and coreset np.set_printoptions(linewidth=10000) print('Posterior requires ' + str(N) + ' data') print('mu, cov = ' + str(mu) + '\n' + str(cov)) print('Coreset requires ' + str(idcs.shape[0]) + ' data') print('muw, covw = ' + str(muw) + '\n' + str(covw)) print('KL(coreset || posterior) = ' + str(gaussian.gaussian_KL(muw, covw, mu, np.linalg.inv(cov))))
wts = res['wts'][2:][::plot_every] mu = res['mus'][2:][::plot_every] Sig = res['Sigs'][2:][::plot_every] cszs[tridx, :] = (wts > 0).sum(axis=1) if is_forward_KL is not True: samples = np.load('results/' + dnm + '_samples.npy') samples = np.hstack( (samples[:, 1:], samples[:, 0][:, np.newaxis])) mup = samples.mean(axis=0) Sigp = np.cov(samples, rowvar=False) M = res['mus'].shape[0] - 1 kl = np.zeros(M + 1) for m in range(M + 1): mul = res['mus'][m, :] Sigl = res['Sigs'][m, :, :] kl[m] = gaussian.gaussian_KL(mul, np.linalg.inv(Sigl), mup, Sigp) kl = kl[2:][::plot_every] else: kl = res['kls'][2:][::plot_every] kls[tridx, :] = kl[:len(Ms)] / kl0 if 'PRIOR' in fn: kls[tridx, :] = np.median(kls[tridx, :]) cput50 = np.percentile(cputs, 50, axis=0) cput25 = np.percentile(cputs, 35, axis=0) cput75 = np.percentile(cputs, 65, axis=0) csz50 = np.percentile(cszs, 50, axis=0) csz25 = np.percentile(cszs, 35, axis=0) csz75 = np.percentile(cszs, 65, axis=0)