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
Exemplo n.º 2
0
#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)
Exemplo n.º 4
0
    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)