示例#1
0
 def sampler_w(n, wts, pts):
     if wts is None or pts is None or pts.shape[0] == 0:
         muw = mu0
         USigw = np.linalg.cholesky(Sig0) #Note: USigw is lower triangular here, below is upper tri. Doesn't matter, just need Sigw = MM^T
     else:
         muw, USigw, _ = model_linreg.weighted_post(mu0, Sig0inv, datastd**2, pts, wts)
     return muw + np.random.randn(n, muw.shape[0]).dot(USigw.T)
示例#2
0
def sampler_w(n, wts, pts):
    if pts.shape[0] == 0:
        wts = np.zeros(1)
        pts = np.zeros((1, Z.shape[1]))
    muw, LSigw, LSigwInv = model_linreg.weighted_post(mu0, Sig0inv, datastd**2,
                                                      pts, wts)
    return muw + np.random.randn(n, muw.shape[0]).dot(LSigw.T)
示例#3
0
 def update(self, wts, pts):
     if wts is None or pts is None or pts.shape[0] == 0:
         self.muw = mu0
         self.USigw = np.linalg.cholesky(
             Sig0
         )  #Note: USigw here is lower triangular, but keeping naming convention for below stuff. Doesn't matter, just need Sigw = MM^T
     else:
         self.muw, self.USigw, _ = model_linreg.weighted_post(
             mu0, Sig0inv, datastd**2, pts, wts)
示例#4
0
def tsf_exact_w(wts, idcs):
    w = np.zeros(X.shape[0])
    w[idcs] = wts
    muw, Sigw = model_linreg.weighted_post(mu0, Sig0inv, datastd ** 2, X, Y, w)
    lmb, V = np.linalg.eigh(Sigw)
    beta = X.dot(V * np.sqrt(np.maximum(lmb, 0.)))
    nu = Y - X.dot(muw)

    # project the matrix term down to 20*20 = 400 dimensions
    lmb, V = np.linalg.eigh(beta.T.dot(beta))
    n_dim = 20
    beta_proj = beta.dot(V[:, -n_dim:])

    return np.hstack((nu[:, np.newaxis] * beta,
                      1. / np.sqrt(2.) * (beta_proj[:, :, np.newaxis] * beta_proj[:, np.newaxis, :]).reshape(
                          beta.shape[0], n_dim ** 2))) / datastd ** 2
示例#5
0
    idcs = np.random.choice(np.arange(x.shape[0]),
                            replace=False,
                            size=basis_unique_counts[i])
    basis_locs = np.vstack((basis_locs, x[idcs, :2]))

print('Converting bases and observations into X/Y matrices')
#convert basis functions + observed data locations into a big X matrix
X = np.zeros((x.shape[0], basis_scales.shape[0]))
for i in range(basis_scales.shape[0]):
    X[:, i] = np.exp(-((x[:, :2] - basis_locs[i, :])**2).sum(axis=1) /
                     (2 * basis_scales[i]**2))
Y = x[:, 2]

#get true posterior
print('Computing true posterior')
mup, Sigp = model_linreg.weighted_post(mu0, Sig0inv, datastd**2, X, Y,
                                       np.ones(X.shape[0]))
Sigpinv = np.linalg.inv(Sigp)

#create function to output log_likelihood given param samples
print('Creating log-likelihood function')
log_likelihood = lambda samples: model_linreg.potentials(
    datastd**2, X, Y, samples)

#create tangent space for well-tuned Hilbert coreset alg
print('Creating tuned tangent space for Hilbert coreset construction')
sampler_optimal = lambda n, w, ids: np.random.multivariate_normal(mup, Sigp, n)
tsf_optimal = bc.BayesianTangentSpaceFactory(log_likelihood, sampler_optimal,
                                             proj_dim)

#create tangent space for poorly-tuned Hilbert coreset alg
print('Creating untuned tangent space for Hilbert coreset construction')
示例#6
0
def run(arguments):
    # check if result already exists for this run, and if so, quit
    if results.check_exists(arguments):
        print('Results already exist for arguments ' + str(arguments))
        print('Quitting.')
        quit()

    #######################################
    #######################################
    ## Step 0: Setup
    #######################################
    #######################################

    np.random.seed(arguments.trial)
    bc.util.set_verbosity(arguments.verbosity)

    if arguments.coreset_size_spacing == 'log':
        Ms = np.unique(
            np.logspace(0.,
                        np.log10(arguments.coreset_size_max),
                        arguments.coreset_num_sizes,
                        dtype=np.int32))
    else:
        Ms = np.unique(
            np.linspace(1,
                        arguments.coreset_size_max,
                        arguments.coreset_num_sizes,
                        dtype=np.int32))

    #make sure the first size to record is 0
    if Ms[0] != 0:
        Ms = np.hstack((0, Ms))

    #######################################
    #######################################
    ## Step 1: Load and preprocess data
    #######################################
    #######################################

    #load data and compute true posterior
    #each row of x is [lat, lon, price]
    print('Loading data')

    x = np.load('../data/prices2018.npy')
    print('dataset size : ', x.shape)

    print('Subsampling down to ' + str(arguments.data_num) + ' points')
    idcs = np.arange(x.shape[0])
    np.random.shuffle(idcs)
    x = x[idcs[:arguments.data_num], :]

    #log transform the prices
    x[:, 2] = np.log10(x[:, 2])

    #get empirical mean/std
    datastd = x[:, 2].std()
    datamn = x[:, 2].mean()

    #bases of increasing size; the last one is effectively a constant
    basis_unique_scales = np.array([.2, .4, .8, 1.2, 1.6, 2., 100])
    basis_unique_counts = np.hstack(
        (arguments.n_bases_per_scale * np.ones(6, dtype=np.int64), 1))

    #the dimension of the scaling vector for the above bases
    d = basis_unique_counts.sum()
    print('Basis dimension: ' + str(d))

    #model params
    mu0 = datamn * np.ones(d)
    Sig0 = (datastd**2 + datamn**2) * np.eye(d)
    Sig0inv = np.linalg.inv(Sig0)

    #generate basis functions by uniformly randomly picking locations in the dataset
    print('Trial ' + str(arguments.trial))
    print('Creating bases')
    basis_scales = np.array([])
    basis_locs = np.zeros((0, 2))
    for i in range(basis_unique_scales.shape[0]):
        basis_scales = np.hstack(
            (basis_scales,
             basis_unique_scales[i] * np.ones(basis_unique_counts[i])))
        idcs = np.random.choice(np.arange(x.shape[0]),
                                replace=False,
                                size=basis_unique_counts[i])
        basis_locs = np.vstack((basis_locs, x[idcs, :2]))

    print('Converting bases and observations into X/Y matrices')
    #convert basis functions + observed data locations into a big X matrix
    X = np.zeros((x.shape[0], basis_scales.shape[0]))
    for i in range(basis_scales.shape[0]):
        X[:, i] = np.exp(-((x[:, :2] - basis_locs[i, :])**2).sum(axis=1) /
                         (2 * basis_scales[i]**2))
    Y = x[:, 2]
    Z = np.hstack((X, Y[:, np.newaxis]))

    _, bV = np.linalg.eigh(X.T.dot(X))
    bV = bV[:, -arguments.proj_dim:]

    #######################################
    #######################################
    ## Step 2: Calculate Likelihoods/Projectors
    #######################################
    #######################################

    #get true posterior
    print('Computing true posterior')
    mup, USigp, LSigpInv = model_linreg.weighted_post(mu0, Sig0inv, datastd**2,
                                                      Z, np.ones(X.shape[0]))
    Sigp = USigp.dot(USigp.T)
    SigpInv = LSigpInv.dot(LSigpInv.T)

    #create function to output log_likelihood given param samples
    print('Creating log-likelihood function')
    log_likelihood = lambda z, th: model_linreg.log_likelihood(
        z, th, datastd**2)

    print('Creating gradient log-likelihood function')
    grad_log_likelihood = lambda z, th: model_linreg.grad_x_log_likelihood(
        z, th, datastd**2)

    #create tangent space for well-tuned Hilbert coreset alg
    print('Creating tuned projector for Hilbert coreset construction')
    sampler_optimal = lambda n, w, pts: mup + np.random.randn(n, mup.shape[0]
                                                              ).dot(USigp.T)
    prj_optimal = bc.BlackBoxProjector(sampler_optimal, arguments.proj_dim,
                                       log_likelihood, grad_log_likelihood)

    #create tangent space for poorly-tuned Hilbert coreset alg
    print('Creating untuned projector for Hilbert coreset construction')
    Zhat = Z[np.random.randint(0, Z.shape[0], int(np.sqrt(Z.shape[0]))), :]
    muhat, USigHat, LSigHatInv = model_linreg.weighted_post(
        mu0, Sig0inv, datastd**2, Zhat, np.ones(Zhat.shape[0]))
    sampler_realistic = lambda n, w, pts: muhat + np.random.randn(
        n, muhat.shape[0]).dot(USigHat.T)
    prj_realistic = bc.BlackBoxProjector(sampler_realistic, arguments.proj_dim,
                                         log_likelihood, grad_log_likelihood)

    print('Creating black box projector')

    def sampler_w(n, wts, pts):
        if wts is None or pts is None or pts.shape[0] == 0:
            muw = mu0
            USigw = np.linalg.cholesky(
                Sig0
            )  #Note: USigw is lower triangular here, below is upper tri. Doesn't matter, just need Sigw = MM^T
        else:
            muw, USigw, _ = model_linreg.weighted_post(mu0, Sig0inv,
                                                       datastd**2, pts, wts)
        return muw + np.random.randn(n, muw.shape[0]).dot(USigw.T)

    prj_bb = bc.BlackBoxProjector(sampler_w, arguments.proj_dim,
                                  log_likelihood, grad_log_likelihood)

    print('Creating exact projectors')

    ##############################
    ###Exact projection in SparseVI for gradient computation
    #for this model we can do the tangent space projection exactly
    class LinRegProjector(bc.Projector):
        def __init__(self, bV):
            self.bV = bV

        def project(self, pts, grad=False):
            X = pts[:, :-1]
            Y = pts[:, -1]
            #beta = X.dot(self.V*np.sqrt(np.maximum(self.lmb, 0.)))
            beta = X.dot(self.USigw)
            nu = Y - X.dot(self.muw)
            #approximation to avoid high memory cost: project the matrix term down to bV.shape[1]**2 dimensions
            beta_proj = beta.dot(self.bV)
            #lmb2, V2 = np.linalg.eigh(beta.T.dot(beta))
            #beta_proj = beta.dot(V2[:, -arguments.proj_dim:])
            return np.hstack(
                (nu[:, np.newaxis] * beta, 1. / np.sqrt(2.) *
                 (beta_proj[:, :, np.newaxis] * beta_proj[:, np.newaxis, :]).
                 reshape(beta.shape[0], arguments.proj_dim**2))) / datastd**2

        def update(self, wts, pts):
            if wts is None or pts is None or pts.shape[0] == 0:
                self.muw = mu0
                self.USigw = np.linalg.cholesky(
                    Sig0
                )  #Note: USigw here is lower triangular, but keeping naming convention for below stuff. Doesn't matter, just need Sigw = MM^T
            else:
                self.muw, self.USigw, _ = model_linreg.weighted_post(
                    mu0, Sig0inv, datastd**2, pts, wts)
            #if pts.shape[0] == 0:
            #    self.muw = mu0
            #    self.Sigw = Sig0
            #else:
            #    self.muw, self.Sigw = model_linreg.weighted_post(mu0, Sig0inv, datastd**2, pts, wts)
            #self.lmb, self.V = np.linalg.eigh(self.LSigw.dot(self.LSigw.T))

    prj_optimal_exact = LinRegProjector(bV)
    prj_optimal_exact.update(np.ones(Z.shape[0]), Z)
    prj_realistic_exact = LinRegProjector(bV)
    prj_realistic_exact.update(np.ones(Zhat.shape[0]), Zhat)

    #######################################
    #######################################
    ## Step 3: Construct Coreset
    #######################################
    #######################################

    ##############################
    print('Creating coreset construction objects')
    #create coreset construction objects
    sparsevi_exact = bc.SparseVICoreset(Z,
                                        LinRegProjector(bV),
                                        opt_itrs=arguments.opt_itrs,
                                        step_sched=eval(arguments.step_sched))
    sparsevi = bc.SparseVICoreset(Z,
                                  prj_bb,
                                  opt_itrs=arguments.opt_itrs,
                                  step_sched=eval(arguments.step_sched))
    giga_optimal = bc.HilbertCoreset(Z, prj_optimal)
    giga_optimal_exact = bc.HilbertCoreset(Z, prj_optimal_exact)
    giga_realistic = bc.HilbertCoreset(Z, prj_realistic)
    giga_realistic_exact = bc.HilbertCoreset(Z, prj_realistic_exact)
    unif = bc.UniformSamplingCoreset(Z)

    algs = {
        'SVI-EXACT': sparsevi_exact,
        'SVI': sparsevi,
        'GIGA-OPT': giga_optimal,
        'GIGA-OPT-EXACT': giga_optimal_exact,
        'GIGA-REAL': giga_realistic,
        'GIGA-REAL-EXACT': giga_realistic_exact,
        'US': unif
    }
    alg = algs[arguments.alg]

    print('Building coreset')
    w = []
    p = []
    cputs = np.zeros(Ms.shape[0])
    t_build = 0
    for m in range(Ms.shape[0]):
        print('M = ' + str(Ms[m]) + ': coreset construction, ' +
              arguments.alg + ' ' + str(arguments.trial))
        t0 = time.process_time()
        itrs = (Ms[m] if m == 0 else Ms[m] - Ms[m - 1])
        alg.build(itrs)
        t_build += time.process_time() - t0
        wts, pts, idcs = alg.get()

        #store weights/pts/runtime
        w.append(wts)
        p.append(pts)
        cputs[m] = t_build

    ##############################
    ##############################
    ## Step 4: Evaluate coreset
    ##############################
    ##############################

    # computing kld and saving results
    muw = np.zeros((Ms.shape[0], mu0.shape[0]))
    Sigw = np.zeros((Ms.shape[0], mu0.shape[0], mu0.shape[0]))
    rklw = np.zeros(Ms.shape[0])
    fklw = np.zeros(Ms.shape[0])
    mu_errs = np.zeros(Ms.shape[0])
    Sig_errs = np.zeros(Ms.shape[0])
    csizes = np.zeros(Ms.shape[0])
    for m in range(Ms.shape[0]):
        csizes[m] = (w[m] > 0).sum()
        muw[m, :], USigw, LSigwInv = model_linreg.weighted_post(
            mu0, Sig0inv, datastd**2, p[m], w[m])
        Sigw[m, :, :] = USigw.dot(USigw.T)
        rklw[m] = model_linreg.KL(muw[m, :], Sigw[m, :, :], mup, SigpInv)
        fklw[m] = model_linreg.KL(mup, Sigp, muw[m, :],
                                  LSigwInv.dot(LSigwInv.T))
        mu_errs[m] = np.sqrt(((mup - muw[m, :])**2).sum()) / np.sqrt(
            (mup**2).sum())
        Sig_errs[m] = np.sqrt(((Sigp - Sigw[m, :, :])**2).sum()) / np.sqrt(
            (Sigp**2).sum())

    results.save(arguments,
                 csizes=csizes,
                 Ms=Ms,
                 cputs=cputs,
                 rklw=rklw,
                 fklw=fklw,
                 mu_errs=mu_errs,
                 Sig_errs=Sig_errs)

    #also save muw/Sigw/etc for plotting coreset visualizations
    f = open('results/coreset_data.pk', 'wb')
    res = (x, mu0, Sig0, datastd, mup, Sigp, w, p, muw, Sigw)
    pk.dump(res, f)
    f.close()
示例#7
0
w_true = np.random.randn(d)
X, Y = build_synthetic_dataset(N, w_true)
Z = np.hstack((X, Y[:, np.newaxis]))

#get empirical mean/std
datastd = Y.std()
datamn = Y.mean()

#model params
mu0 = datamn * np.ones(d)
ey = np.eye(d)
Sig0 = (datastd**2 + datamn**2) * ey
Sig0inv = np.linalg.inv(Sig0)
#get true posterior
mup, LSigp, LSigpInv = model_linreg.weighted_post(mu0, Sig0inv, datastd**2, Z,
                                                  np.ones(X.shape[0]))
Sigp = LSigp.dot(LSigp.T)
SigpInv = LSigpInv.T.dot(LSigpInv)

#create function to output log_likelihood given param samples
print('Creating log-likelihood function')
log_likelihood = lambda z, th: model_linreg.gaussian_loglikelihood(
    z, th, datastd**2)

print('Creating gradient log-likelihood function')
grad_log_likelihood = lambda z, th: model_linreg.gaussian_grad_x_loglikelihood(
    z, th, datastd**2)

#create tangent space for well-tuned Hilbert coreset alg
print('Creating tuned projector for Hilbert coreset construction')
sampler_optimal = lambda n, w, pts: mup + np.random.randn(n, mup.shape[0]).dot(