Exemple #1
0
 def CAE_infMALA(self):
     """
     infinite dimensional Metropolis Adjusted Langevin Algorithm with AutoEncoder
     """
     logvol=0
     # initialization
     q=self.q.copy()
     rth=np.sqrt(self.h)
     
     # sample velocity
     v=self.randv()
     
     # natural gradient
     ng=self.model.prior.C_act(self.g)
     
     # update velocity
     v.axpy(rth/2,ng)
     
     # current energy
     E_cur = -self.ll - rth/2*self.g.inner(v) + self.h/8*self.g.inner(ng)
     
     # correct volume if requested
     if self.volcrK:
         q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None])
         logvol+=self.cae.logvol(q_,'encode')
     
     # generate proposal according to Langevin dynamics
     q.zero()
     q.axpy((1-self.h/4)/(1+self.h/4),self.q)
     q.axpy(rth/(1+self.h/4),v)
     
     # update velocity
     v_=v.copy();v.zero()
     v.axpy(-(1-self.h/4)/(1+self.h/4),v_)
     v.axpy(rth/(1+self.h/4),self.q)
     
     # update geometry
     ll,g,_,_=self.geom(q)
     
     # natural gradient
     ng=self.model.prior.C_act(g)
     
     # new energy
     E_prp = -ll - rth/2*g.inner(v) + self.h/8*g.inner(ng)
     
     # correct volume if requested
     if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode')
     
     # Metropolis test
     logr=-E_prp+E_cur+logvol
     
     if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr):
         # accept
         self.q=q; self.ll=ll; self.g=g;
         acpt=True
     else:
         acpt=False
     
     # return accept indicator
     return acpt,logr
Exemple #2
0
def logvol(unknown_lat, V_lat, autoencoder, coding):
    if 'Conv' in type(autoencoder).__name__:
        u_latin = fun2img(vec2fun(unknown_lat, V_lat))
        u_latin = chop(u_latin)[None, :, :, None] if autoencoder.activations[
            'latent'] is None else u_latin.flatten()[None, :]
    else:
        u_latin = unknown_lat.get_local()[None, :]
    return autoencoder.logvol({
        'encode': autoencoder.decode(u_latin),
        'decode': u_latin
    }[coding], coding)
Exemple #3
0
 def CAE_pCN(self):
     """
     preconditioned Crank-Nicolson with AutoEncoder
     """
     logvol=0
     # initialization
     q=self.q.copy()
     
     # sample velocity
     v=self.randv()
     
     # correct volume if requested
     if self.volcrK:
         q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) # chop image to have even dimensions
         logvol+=self.cae.logvol(q_,'encode')
     
     # generate proposal according to Crank-Nicolson scheme
     q.zero()
     q.axpy((1-self.h/4)/(1+self.h/4),self.q)
     q.axpy(np.sqrt(self.h)/(1+self.h/4),v)
     
     # update geometry
     ll,_,_,_=self.geom(q)
     
     # correct volume if requested
     if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # TODO: need go back to the original scale too?
     
     # Metropolis test
     logr=ll-self.ll+logvol
     
     if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr):
         # accept
         self.q=q; self.ll=ll;
         acpt=True
     else:
         acpt=False
     
     # return accept indicator
     return acpt,logr
def retrieve_ensemble(bip,
                      dir_name,
                      f_name,
                      ensbl_sz,
                      max_iter,
                      img_out=False,
                      whiten=False):
    f = df.HDF5File(bip.pde.mpi_comm, os.path.join(dir_name, f_name), "r")
    ensbl_f = df.Function(bip.pde.V)
    num_ensbls = max_iter * ensbl_sz
    if img_out:
        gdim = bip.pde.V.mesh().geometry().dim()
        imsz = np.floor(bip.pde.V.dim()**(1. / gdim)).astype('int')
        out_shape = (num_ensbls, np.int(
            bip.pde.V.dim() / imsz**(gdim - 1))) + (imsz, ) * (gdim - 1)
    else:
        out_shape = (num_ensbls, bip.pde.V.dim())
    out = np.zeros(out_shape)
    prog = np.ceil(num_ensbls * (.1 + np.arange(0, 1, .1)))
    for n in range(max_iter):
        for j in range(ensbl_sz):
            f.read(ensbl_f, 'iter{0}_ensbl{1}'.format(n + ('Y' not in TRAIN),
                                                      j))
            s = n * ensbl_sz + j
            if whiten:
                ensbl_v = bip.prior.u2v(ensbl_f.vector())
                out[s] = fun2img(vec2fun(
                    ensbl_v, bip.pde.V)) if img_out else ensbl_v.get_local()
            else:
                out[s] = fun2img(
                    ensbl_f) if img_out else ensbl_f.vector().get_local()
            if s + 1 in prog:
                print('{0:.0f}% ensembles have been retrieved.'.format(
                    np.float(s + 1) / num_ensbls * 100))
    f.close()
    return out
        if u_ref is not None:
            u.axpy(1.0,u_ref)
        
        return u
        
if __name__ == '__main__':
    from pde import *
    np.random.seed(2016)
    PDE = ellipticPDE()
    mpi_comm = PDE.mesh.mpi_comm()
    prior = Gaussian_prior(V=PDE.V,mpi_comm=mpi_comm)
    whiten = False
    u=prior.sample(whiten=whiten)
    logpri,gradpri=prior.logpdf(u, whiten=whiten, grad=True)
    print('The logarithm of prior density at u is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri,gradpri.norm('l2')))
    df.plot(vec2fun(u,PDE.V))
#     df.interactive()
    v=prior.u2v(u)
    logpri_wt,gradpri_wt=prior.logpdf(v, whiten=True, grad=True)
    print('The logarithm of prior density at whitened v is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri_wt,gradpri_wt.norm('l2')))
    df.plot(vec2fun(v,PDE.V))
#     df.interactive()
    
    whiten = True
    v=prior.sample(whiten=whiten)
    logpri,gradpri=prior.logpdf(v, whiten=whiten, grad=True)
    print('The logarithm of prior density at whitened v is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri,gradpri.norm('l2')))
    df.plot(vec2fun(v,PDE.V))
#     df.interactive()
    u=prior.v2u(v)
    logpri_wt,gradpri_wt=prior.logpdf(u, whiten=False, grad=True)
                    os.path.join('./result', "MAP_SNR" + str(SNR) + ".h5"),
                    "r")
    f.read(u_f, "parameter")
    f.close()
except:
    pass
u = u_f.vector()
# u=elliptic.prior.sample()
loglik = lambda y: -0.5 * elliptic.misfit.prec * tf.math.reduce_sum(
    (y - elliptic.misfit.obs)**2, axis=1)
loglik_cnn = lambda x: loglik(cnn.model(x))
loglik_dnn = lambda x: loglik(dnn.model(x))
# calculate gradient
dll_xact = elliptic.get_geom(u, [0, 1])[1]
# emulate gradient
u_img = fun2img(vec2fun(u, elliptic.pde.V))
dll_cnn = cnn.gradient(u_img[None, :, :, None], loglik_cnn)
dll_dnn = dnn.gradient(u.get_local()[None, :], loglik_dnn)

# plot
import matplotlib.pyplot as plt
import matplotlib as mp
plt.rcParams['image.cmap'] = 'jet'
fig, axes = plt.subplots(nrows=1,
                         ncols=3,
                         sharex=True,
                         sharey=True,
                         figsize=(15, 5))
sub_figs = [None] * 3
# plot
plt.axes(axes.flat[0])
        samp_std=elliptic.prior.gen_vector(); samp_std.zero()
#         num_read=0
        for f_i in hdf5_files:
            if '_'+algs[i]+'_' in f_i:
                try:
                    f=df.HDF5File(bip.pde.mpi_comm,os.path.join(folder,f_i),"r")
                    samp_mean.zero(); samp_std.zero(); num_read=0
                    for s in range(num_samp):
                        if s+1 in prog:
                            print('{0:.0f}% has been completed.'.format(np.float(s+1)/num_samp*100))
                        f.read(samp_f,'sample_{0}'.format(s))
                        u=samp_f.vector()
                        if '_whitened_latent' in f_i: u=bip.prior.v2u(u)
                        if 'DREAM' in algs[i]:
                            if 'c' in AE:
                                u_latin=fun2img(vec2fun(u, elliptic_latent.pde.V))
                                width=tuple(np.mod(i,2) for i in u_latin.shape)
                                u_latin=chop(u_latin,width)[None,:,:,None] if autoencoder.activations['latent'] is None else u_latin.flatten()[None,:]
                                u=img2fun(pad(np.squeeze(autoencoder.decode(u_latin)),width),elliptic.pde.V).vector()
                            else:
                                u_latin=u.get_local()[None,:]
                                u=elliptic.prior.gen_vector(autoencoder.decode(u_latin).flatten())
#                         else:
#                             u=u_
                        if '_whitened_emulated' in f_i: u=elliptic.prior.v2u(u)
                        samp_mean.axpy(wts[s],u)
                        samp_std.axpy(wts[s],u*u)
#                         num_read+=1
                    f.close()
                    print(f_i+' has been read!')
                    f_read=f_i
Exemple #8
0
def geom(unknown_lat,
         V_lat,
         V,
         autoencoder,
         geom_ord=[0],
         whitened=False,
         **kwargs):
    loglik = None
    gradlik = None
    metact = None
    rtmetact = None
    eigs = None

    # un-whiten if necessary
    if whitened == 'latent':
        bip_lat = kwargs.get('bip_lat')
        unknown_lat = bip_lat.prior.v2u(unknown_lat)

#     u_latin={'AutoEncoder':unknown_lat.get_local()[None,:],'ConvAutoEncoder':chop(fun2img(vec2fun(unknown_lat, V_lat)))[None,:,:,None]}[type(autoencoder).__name__]
    if 'Conv' in type(autoencoder).__name__:
        u_latin = fun2img(vec2fun(unknown_lat, V_lat))
        width = tuple(np.mod(i, 2) for i in u_latin.shape)
        u_latin = chop(u_latin,
                       width)[None, :, :, None] if autoencoder.activations[
                           'latent'] is None else u_latin.flatten()[None, :]
        unknown = img2fun(pad(np.squeeze(autoencoder.decode(u_latin)), width),
                          V).vector()
    else:
        u_latin = unknown_lat.get_local()[None, :]
        unknown = df.Function(V).vector()
        unknown.set_local(autoencoder.decode(u_latin).flatten())

    emul_geom = kwargs.pop('emul_geom', None)
    full_geom = kwargs.pop('full_geom', None)
    bip_lat = kwargs.pop('bip_lat', None)
    bip = kwargs.pop('bip', None)
    try:
        if len(kwargs) == 0:
            loglik, gradlik, metact_, rtmetact_ = emul_geom(
                unknown, geom_ord, whitened == 'emulated')
        else:
            loglik, gradlik, metact_, eigs_ = emul_geom(
                unknown, geom_ord, whitened == 'emulated', **kwargs)
    except:
        try:
            if len(kwargs) == 0:
                loglik, gradlik, metact_, rtmetact_ = full_geom(
                    unknown, geom_ord, whitened == 'original')
            else:
                loglik, gradlik, metact_, eigs_ = full_geom(
                    unknown, geom_ord, whitened == 'original', **kwargs)
        except:
            raise RuntimeError('No geometry in the original space available!')

    if any(s >= 1 for s in geom_ord):
        if whitened == 'latent':
            gradlik = bip.prior.C_act(gradlik, .5, op='C', transp=True)
#         jac_=autoencoder.jacobian(u_latin,'decode')
        if 'Conv' in type(autoencoder).__name__:
            #             if autoencoder.activations['latent'] is None:
            # #                 jac__=np.zeros(jac_.shape[:2]+tuple(i+1 for i in jac_.shape[2:]))
            # #                 jac__[:,:,:-1,:-1]=jac_; jac_=jac__
            #                 jac_=pad(jac_,(0,)*2+width)
            #                 jac_=jac_.reshape(jac_.shape[:2]+(-1,))
            #             d2v = df.dof_to_vertex_map(V_lat)
            #             jac_=jac_[:,:,d2v]
            #         jac=MultiVector(unknown,V_lat.dim())
            # #         [jac[i].set_local(img2fun(pad(jac_[:,:,i]), V).vector() if 'Conv' in type(autoencoder).__name__ else jac_[:,i]) for i in range(V_lat.dim())] # not working: too many indices?
            #         if 'Conv' in type(autoencoder).__name__:
            #             [jac[i].set_local(img2fun(pad(jac_[:,:,i],width), V).vector()) for i in range(V_lat.dim())] # for loop is too slow
            #         else:
            #             [jac[i].set_local(jac_[:,i]) for i in range(V_lat.dim()) for i in range(V_lat.dim())] # for loop is too slow
            #         gradlik_=jac.dot(gradlik)
            jac_ = autoencoder.jacobian(u_latin, 'decode')
            jac_ = pad(
                jac_, width *
                2 if autoencoder.activations['latent'] is None else width +
                (0, ))
            jac_ = jac_.reshape(
                (np.prod(jac_.shape[:2]), np.prod(jac_.shape[2:])))
            jac_ = jac_[np.ix_(df.dof_to_vertex_map(V),
                               df.dof_to_vertex_map(V_lat))]
            #         try:
            #         import timeit
            #         t_start=timeit.default_timer()
            #         jac=create_PETScMatrix(jac_.shape,V.mesh().mpi_comm(),range(jac_.shape[0]),range(jac_.shape[1]),jac_)
            #         gradlik_=df.as_backend_type(gradlik).vec()
            #         gradlik1=df.Vector(unknown_lat)
            #         jac.multTranspose(gradlik_,df.as_backend_type(gradlik1).vec())
            #         print('time consumed:{}'.format(timeit.default_timer()-t_start))
            #         except:
            #         t_start=timeit.default_timer()
            gradlik_ = jac_.T.dot(gradlik.get_local())
        gradlik_ = autoencoder.jacvec(u_latin, gradlik.get_local()[None, :])
        gradlik = df.Vector(unknown_lat)
        gradlik.set_local(gradlik_)
#         print('time consumed:{}'.format(timeit.default_timer()-t_start))

    if any(s >= 1.5 for s in geom_ord):

        def _get_metact_misfit(u_actedon):
            if type(u_actedon) is df.Vector:
                u_actedon = u_actedon.get_local()
            tmp = df.Vector(unknown)
            tmp.zero()
            jac.reduce(tmp, u_actedon)
            v = df.Vector(unknown_lat)
            v.set_local(jac.dot(metact_(tmp)))
            return v

        def _get_rtmetact_misfit(u_actedon):
            if type(u_actedon) is not df.Vector:
                u_ = df.Vector(unknown)
                u_.set_local(u_actedon)
                u_actedon = u_
            v = df.Vector(unknown_lat)
            v.set_local(jac.dot(rtmetact_(u_actedon)))
            return v

        metact = _get_metact_misfit
        rtmetact = _get_rtmetact_misfit

    if any(s > 1 for s in geom_ord) and len(kwargs) != 0:
        if bip_lat is None:
            raise ValueError('No latent inverse problem defined!')
        # compute eigen-decomposition using randomized algorithms
        if whitened == 'latent':
            # generalized eigen-decomposition (_C^(1/2) F _C^(1/2), M), i.e. _C^(1/2) F _C^(1/2) = M V D V', V' M V = I
            def invM(a):
                a = bip_lat.prior.gen_vector(a)
                invMa = bip_lat.prior.gen_vector()
                bip_lat.prior.Msolver.solve(invMa, a)
                return invMa

            eigs = geigen_RA(metact,
                             lambda u: bip_lat.prior.M * u,
                             invM,
                             dim=bip_lat.pde.V.dim(),
                             **kwargs)
        else:
            # generalized eigen-decomposition (F, _C^(-1)), i.e. F = _C^(-1) U D U^(-1), U' _C^(-1) U = I, V = _C^(-1/2) U
            eigs = geigen_RA(metact,
                             lambda u: bip_lat.prior.C_act(u, -1, op='K'),
                             lambda u: bip_lat.prior.C_act(u, op='K'),
                             dim=bip_lat.pde.V.dim(),
                             **kwargs)
        if any(s > 1.5 for s in geom_ord):
            # adjust the gradient
            # update low-rank approximate Gaussian posterior
            bip_lat.post_Ga = Gaussian_apx_posterior(bip_lat.prior, eigs=eigs)
#             Hu = bip_lat.prior.gen_vector()
#             bip_lat.post_Ga.Hlr.mult(unknown, Hu)
#             gradlik.axpy(1.0,Hu)

    if len(kwargs) == 0:
        return loglik, gradlik, metact, rtmetact
    else:
        return loglik, gradlik, metact, eigs
Exemple #9
0
                # emulation by GP
                t_start = timeit.default_timer()
                ll_emul = logLik_g(u.get_local()[None, :]).numpy()
                dll_emul = gp.gradient(u.get_local()[None, :], logLik_g)
                t_used[1] += timeit.default_timer() - t_start
                # record difference
                dif_fun = np.abs(ll_xact - ll_emul)
                dif_grad = dll_xact.get_local() - dll_emul
                fun_errors[0, s, t, n] = dif_fun
                grad_errors[0, s, t,
                            n] = np.linalg.norm(dif_grad) / dll_xact.norm('l2')

                # emulation by CNN
                t_start = timeit.default_timer()
                u_img = fun2img(vec2fun(u, elliptic.pde.V))
                ll_emul = logLik_c(u_img[None, :, :, None]).numpy()
                dll_emul = cnn.gradient(u_img[None, :, :, None],
                                        logLik_c)  #* grad_scalfctr
                t_used[2] += timeit.default_timer() - t_start
                # record difference
                dif_fun = np.abs(ll_xact - ll_emul)
                dif_grad = dll_xact - img2fun(dll_emul,
                                              elliptic.pde.V).vector()
                fun_errors[1, s, t, n] = dif_fun
                grad_errors[1, s, t,
                            n] = dif_grad.norm('l2') / dll_xact.norm('l2')

            print(
                'Time used for calculation: {} vs GP-emulation: {} vs CNN-emulation: {}'
                .format(*t_used.tolist()))
Exemple #10
0
    def CAE_DRinfmHMC(self):
        """
        dimension-reduced infinite dimensional manifold HMC with AutoEncoder
        """
        logvol=0
        # initialization
        q=self.q.copy()
        rth=np.sqrt(self.h) # make the scale comparable to MALA
#         cos_=np.cos(rth); sin_=np.sin(rth);
        cos_=(1-self.h/4)/(1+self.h/4); sin_=rth/(1+self.h/4);

        # sample velocity
        v=self.randv(self.model.post_Ga)

        # natural gradient
        ng=self.model.post_Ga.postC_act(self.g) # use low-rank posterior Hessian solver

        # accumulate the power of force
        pw = rth/2*self.model.prior.C_act(v,-1).inner(ng)

        # current energy
        E_cur = -self.ll + self.h/4*self.model.prior.logpdf(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+self.eigs[0])) # use low-rank Hessian inner product

        # correct volume if requested
        if self.volcrK:
            q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None])
            logvol+=self.cae.logvol(q_,'encode')
        
        randL=np.int(np.ceil(np.random.uniform(0,self.L)))

        for l in range(randL):
            # a half step for velocity
            v.axpy(rth/2,ng)

            # a full step rotation
            q_=q.copy();q.zero()
            q.axpy(cos_,q_)
            q.axpy(sin_,v)
            v_=v.copy();v.zero()
            v.axpy(cos_,v_)
            v.axpy(-sin_,q_)

            # update geometry
            ll,g,_,eigs=self.geom(q)
            self.model.post_Ga.eigs=eigs # update the eigen-pairs in low-rank approximation --important!
            ng=self.model.post_Ga.postC_act(g)

            # another half step for velocity
            v.axpy(rth/2,ng)

            # accumulate the power of force
            if l!=randL-1: pw+=rth*self.model.prior.C_act(v,-1).inner(ng)

        # accumulate the power of force
        pw += rth/2*self.model.prior.C_act(v,-1).inner(ng)

        # new energy
        E_prp = -ll + self.h/4*self.model.prior.logpdf(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+eigs[0]))
        
        # correct volume if requested
        if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode')

        # Metropolis test
        logr=-E_prp+E_cur-pw+logvol

        if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr):
            # accept
            self.q=q; self.ll=ll; self.g=g; self.eigs=eigs;
            acpt=True
        else:
            acpt=False

        # return accept indicator
        return acpt,logr
Exemple #11
0
    def CAE_DRinfmMALA(self):
        """
        dimension-reduced infinite dimensional manifold MALA with AutoEncoder
        """
        logvol=0
        # initialization
        q=self.q.copy()
        rth=np.sqrt(self.h)
        
        # sample velocity
        v=self.randv(self.model.post_Ga)

        # natural gradient
        ng=self.model.post_Ga.postC_act(self.g) # use low-rank posterior Hessian solver

        # update velocity
        v.axpy(rth/2,ng)

        # current energy
        E_cur = -self.ll - rth/2*self.g.inner(v) + self.h/8*self.g.inner(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+self.eigs[0])) # use low-rank Hessian inner product

        # correct volume if requested
        if self.volcrK:
            q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None])
            logvol+=self.cae.logvol(q_,'encode')
        
        # generate proposal according to simplified manifold Langevin dynamics
        q.zero()
        q.axpy((1-self.h/4)/(1+self.h/4),self.q)
        q.axpy(rth/(1+self.h/4),v)

        # update velocity
        v_=v.copy();v.zero()
        v.axpy(-(1-self.h/4)/(1+self.h/4),v_)
        v.axpy(rth/(1+self.h/4),self.q)

        # update geometry
        ll,g,_,eigs=self.geom(q)
        self.model.post_Ga.eigs=eigs # update the eigen-pairs in low-rank approximation --important!

        # natural gradient
        ng=self.model.post_Ga.postC_act(g)

        # new energy
        E_prp = -ll - rth/2*g.inner(v) + self.h/8*g.inner(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+eigs[0]))
        
        # correct volume if requested
        if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode')

        # Metropolis test
        logr=-E_prp+E_cur+logvol

        if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr):
            # accept
            self.q=q; self.ll=ll; self.g=g; self.eigs=eigs;
            acpt=True
        else:
            acpt=False

        # return accept indicator
        return acpt,logr
Exemple #12
0
    def CAE_infHMC(self):
        """
        infinite dimensional Hamiltonian Monte Carlo with AutoEncoder
        """
        logvol=0
        # initialization
        q=self.q.copy()
        rth=np.sqrt(self.h) # make the scale comparable to MALA
        cos_=np.cos(rth); sin_=np.sin(rth);

        # sample velocity
        v=self.randv()

        # natural gradient
        ng=self.model.prior.C_act(self.g)

        # accumulate the power of force
        pw = rth/2*self.g.inner(v)

        # current energy
        E_cur = -self.ll - self.h/8*self.g.inner(ng)
        
        # correct volume if requested
        if self.volcrK:
            q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None])
            logvol+=self.cae.logvol(q_,'encode')

        randL=np.int(np.ceil(np.random.uniform(0,self.L)))

        for l in range(randL):
            # a half step for velocity
            v.axpy(rth/2,ng)

            # a full step for position
            q_=q.copy();q.zero()
            q.axpy(cos_,q_)
            q.axpy(sin_,v)
            v_=v.copy();v.zero()
            v.axpy(-sin_,q_)
            v.axpy(cos_,v_)

            # update geometry
            ll,g,_,_=self.geom(q)
            ng=self.model.prior.C_act(g)

            # another half step for velocity
            v.axpy(rth/2,ng)

            # accumulate the power of force
            if l!=randL-1: pw+=rth*g.inner(v)

        # accumulate the power of force
        pw += rth/2*g.inner(v)

        # new energy
        E_prp = -ll - self.h/8*g.inner(ng)
        
        # correct volume if requested
        if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode')

        # Metropolis test
        logr=-E_prp+E_cur-pw+logvol

        if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr):
            # accept
            self.q=q; self.ll=ll; self.g=g;
            acpt=True
        else:
            acpt=False

        # return accept indicator
        return acpt,logr
Exemple #13
0
def geom(unknown, bip, emulator, geom_ord=[0], whitened=False, **kwargs):
    loglik = None
    gradlik = None
    metact = None
    rtmetact = None
    eigs = None

    # un-whiten if necessary
    if whitened:
        unknown = bip.prior.v2u(unknown)

    u_input = {
        'DNN': unknown.get_local()[None, :],
        'CNN': fun2img(vec2fun(unknown, bip.pde.V))[None, :, :, None]
    }[type(emulator).__name__]

    ll_f = lambda x: -0.5 * bip.misfit.prec * tf.math.reduce_sum(
        (emulator.model(x) - bip.misfit.obs)**2, axis=1)

    if any(s >= 0 for s in geom_ord):
        loglik = ll_f(u_input).numpy()

    if any(s >= 1 for s in geom_ord):
        gradlik_ = emulator.gradient(u_input, ll_f)
        #         gradlik = {'DNN':bip.prior.gen_vector(gradlik_), 'CNN':img2fun(gradlik_, bip.pde.V).vector()}[type(emulator).__name__] # not working
        if type(emulator).__name__ == 'DNN':
            gradlik = bip.prior.gen_vector(gradlik_)
        elif type(emulator).__name__ == 'CNN':
            gradlik = img2fun(gradlik_, bip.pde.V).vector()
        if whitened:
            gradlik = bip.prior.C_act(gradlik, .5, op='C', transp=True)

    if any(s >= 1.5 for s in geom_ord):
        jac_ = emulator.jacobian(u_input)
        n_obs = len(bip.misfit.idx)
        jac = MultiVector(unknown, n_obs)
        [
            jac[i].set_local({
                'DNN': jac_[i],
                'CNN': img2fun(jac_[i], bip.pde.V).vector()
            }[type(emulator).__name__]) for i in range(n_obs)
        ]

        def _get_metact_misfit(u_actedon):  # GNH
            if type(u_actedon) is not df.Vector:
                u_actedon = bip.prior.gen_vector(u_actedon)
            v = bip.prior.gen_vector()
            jac.reduce(v, bip.misfit.prec * jac.dot(u_actedon))
            return bip.prior.M * v

        def _get_rtmetact_misfit(u_actedon):
            if type(u_actedon) is df.Vector:
                u_actedon = u_actedon.get_local()
            v = bip.prior.gen_vector()
            jac.reduce(v, np.sqrt(bip.misfit.prec) * u)
            return bip.prior.rtM * v

        metact = _get_metact_misfit
        rtmetact = _get_rtmetact_misfit
        if whitened:
            metact = lambda u: bip.prior.C_act(_get_metact_misfit(
                bip.prior.C_act(u, .5, op='C')),
                                               .5,
                                               op='C',
                                               transp=True)  # ppGNH
            rtmetact = lambda u: bip.prior.C_act(
                _get_rtmetact_misfit(u), .5, op='C', transp=True)

    if any(s > 1 for s in geom_ord) and len(kwargs) != 0:
        if whitened:
            # generalized eigen-decomposition (_C^(1/2) F _C^(1/2), M), i.e. _C^(1/2) F _C^(1/2) = M V D V', V' M V = I
            def invM(a):
                a = bip.prior.gen_vector(a)
                invMa = bip.prior.gen_vector()
                bip.prior.Msolver.solve(invMa, a)
                return invMa

            eigs = geigen_RA(metact,
                             lambda u: bip.prior.M * u,
                             invM,
                             dim=bip.pde.V.dim(),
                             **kwargs)
        else:
            # generalized eigen-decomposition (F, _C^(-1)), i.e. F = _C^(-1) U D U^(-1), U' _C^(-1) U = I, V = _C^(-1/2) U
            eigs = geigen_RA(metact,
                             lambda u: bip.prior.C_act(u, -1, op='K'),
                             lambda u: bip.prior.C_act(u, op='K'),
                             dim=bip.pde.V.dim(),
                             **kwargs)
        if any(s > 1.5 for s in geom_ord):
            # adjust the gradient
            # update low-rank approximate Gaussian posterior
            bip.post_Ga = Gaussian_apx_posterior(bip.prior, eigs=eigs)
            Hu = bip.prior.gen_vector()
            bip.post_Ga.Hlr.mult(unknown, Hu)
            gradlik.axpy(1.0, Hu)

    if len(kwargs) == 0:
        return loglik, gradlik, metact, rtmetact
    else:
        return loglik, gradlik, metact, eigs