neuroprob/base.py
def sample_XZ(self, b, samples, net_input=None, entropy=False):
        """
        Draw samples from the covariate distribution, provides an implementation of SVI.
        In [1] we amortise the variational parameters with a recognition network. Note the input 
        to this network is the final output, i.e. all latents in each layer of a deep GP are mapped 
        from the final output layer.
        
        History in GLMs is incorporated through the offset before the batch_edge values indicating the 
        batching timepoints. AR(1) structure is incorporated by appending the first timestep of the next 
        batch into the current one, which is then used for computing the Markovian prior.
        
        Note that in LVM + GLM, the first filter_len-1 number of LVs is not inferred.
        
        Note when input is trialled, we can only have MC samples flag equal to trials (one per trial).
        
        :param int b: the batch ID to sample from
        :param int samples: the number of samples to take
        :param torch.tensor net_input: direct input for VAE amortization of shape (dims, time)
        :returns: covariates sample of shape (samples, timesteps, dims), log_prior
        :rtype: tuple
        
        References:
        
        [1] `Variational auto-encoded deep Gaussian Processes`,
        Zhenwen Dai, Andreas Damianou, Javier Gonzalez & Neil Lawrence
        
        """
        if self.regressor_mode: # regressor mode, no lv, trial blocks are repeated
            XZ, kl_stim = self._time_slice(self._XZ(self.XZ[b], samples))
            dummy = torch.zeros(samples*self.trials).to(self.dummy.device)
            return XZ, dummy, 0 if entropy else dummy, kl_stim
            
        ### LVM ###
        log_prior = 0
        nlog_q = 0
        KL_prior = 0
        cov = []
            
        for k, vi in enumerate(self.VI_tuples):
            p, v, topo, dims = vi
            
            if p is None or isinstance(self.XZ[k], list): # regressor variable
                cov.append(self._XZ(self.XZ[k][b], samples))
                continue
                
            ### continuous latent variables ###      
            if v == 'VAE': # compute the variational parameters
                mu, std = self._VAE(k, net_input.t().to(self.dummy.device))
            else:
                mu, std = self._latents(b, k, dims, topo)       

            vd = self.variational[k](mu, std)#.to_event()
            v_samp = vd((samples,)) # samples, time, event_dims
            if v == 'NF':
                NF_net = getattr(self, 'lv_NF_{}'.format(k))
                v_samp, log_jacob = NF_net(v_samp)

            ### prior setup ###            
            if self.AR_p == 1: # AR(1) structure
                
                if p == 'RW_mapping':
                    loc, std = self.prior_moments(k)
                    pd = self.prior_dist[k](loc, std)
                    
                    f_loc, f_var, log_p_m, nlog_q_m, kl_p = self._mapping(b, k, dims, net_input, entropy)
                    
                    log_prior = log_prior + log_p_m
                    nlog_q = nlog_q + nlog_q_m
                    KL_prior = KL_prior + kl_p
                    
                    #if GP.cov_type == 'full':
                    #    rd = distributions.Rn_MVN(f_loc, covariance_matrix=f_var)
                    rd = distributions.Rn_Normal(f_loc, f_var.sqrt())
                    
                    dv = v_samp[:, 1:]-v_samp[:, :-1]
                    if topo == 'torus': # geodesic distance
                        dv = dv % (2*np.pi)
                        dv[dv > np.pi] = dv[dv > np.pi] - 2*np.pi
                    
                    rw_term = self._log_p(rd, dv)

                elif p == 'RW':                    
                    loc, std = self.prior_moments(k)

                    if topo == 'euclid': # stationary linear 
                        loc =  torch.sigmoid(loc)
                        rd = self.rw_dist[k](loc*v_samp[:, :-1], std*torch.sqrt(1-loc**2))
                        pd = self.prior_dist[k](0., std)
                    elif topo == 'torus': # drift DS
                        rd = self.rw_dist[k](v_samp[:, :-1]+loc, std)
                        pd = self.prior_dist[k](loc)
                    elif topo == 'sphere':
                        rd = self.rw_dist[k](v_samp[:, :-1, :], std)
                        pd = self.prior_dist[k](loc)#.to_event()

                    rw_term = self._log_p(rd, v_samp[:, 1:])
                                 
                if self.batch_link[b]:
                    prior_term = rw_term
                else: # add log prob of first initial time step
                    prior_term = rw_term + self._log_p(pd, v_samp[:, 0:1]) # sum over time (and dims if > 1)
                    
                start = self.AR_p if self.batch_link[b] else 0 # avoid overlap from AR structure
                # RW prior case, don't double count edge parameter, v_samp contains extra overlap when batch_link True
                var_term = self._nlog_q(vd, v_samp, entropy, start)
                v_samp_ = v_samp[:, start:]
                    
            else:
                if p == 'mapping':
                    f_loc, f_var, log_p_m, nlog_q_m, kl_p = self._mapping(b, k, dims, net_input, entropy)
                    
                    log_prior = log_prior + log_p_m
                    nlog_q = nlog_q + nlog_q_m
                    KL_prior = KL_prior + kl_p
                        
                    #if GP.cov_type == 'full':
                    #    pd = distributions.Rn_MVN(f_loc[0], covariance_matrix=f_var[0])
                    pd = distributions.Rn_Normal(f_loc, f_var.sqrt())

                else:
                    loc, std = self.prior_moments(k)
                    pd = self.prior_dist[k](loc, std)#.to_event()
                    
                prior_term = self._log_p(pd, v_samp)
                var_term = self._nlog_q(vd, v_samp, entropy)
                v_samp_ = v_samp
            
            ### compute log probability terms ###
            fac = self.tsteps / v_samp_.shape[1] # subsampling in batched mode
            log_prior = log_prior + fac*prior_term
            nlog_q = nlog_q + fac*var_term
            if len(v_samp_.shape) == 2: # one-dimensional latent variables expanded
                v_samp_ = v_samp_[..., None]
            cov.append(v_samp_)

        XZ, kl_stim = self._time_slice(torch.cat(cov, dim=-1))
        return XZ, log_prior, nlog_q, KL_prior+kl_stim

        Draw samples from the covariate distribution, provides an implementation of SVI.
        In [1] we amortise the variational parameters with a recognition network. Note the input 
        to this network is the final output, i.e. all latents in each layer of a deep GP are mapped 
        from the final output layer.
        
        History in GLMs is incorporated through the offset before the batch_edge values indicating the 
        batching timepoints. AR(1) structure is incorporated by appending the first timestep of the next 
        batch into the current one, which is then used for computing the Markovian prior.
        
        Note that in LVM + GLM, the first filter_len-1 number of LVs is not inferred.
        
        Note when input is trialled, we can only have MC samples flag equal to trials (one per trial).
        
        :param int b: the batch ID to sample from
        :param int samples: the number of samples to take
        :param torch.tensor net_input: direct input for VAE amortization of shape (dims, time)
        :returns: covariates sample of shape (samples, timesteps, dims), log_prior
        :rtype: tuple
        
        References:
        
        [1] `Variational auto-encoded deep Gaussian Processes`,
        Zhenwen Dai, Andreas Damianou, Javier Gonzalez & Neil Lawrence
        
        
Draw samples from the covariate distribution, provides an implementation of SVI.
In [1] we amortise the variational parameters with a recognition network. Note the input
to this network is the final output, i.e. all latents in each layer of a deep GP are mapped
from the final output layer.

History in GLMs is incorporated through the offset before the batch_edge values indicating the
batching timepoints. AR(1) structure is incorporated by appending the first timestep of the next
batch into the current one, which is then used for computing the Markovian prior.

Note that in LVM + GLM, the first filter_len-1 number of LVs is not inferred.

Note when input is trialled, we can only have MC samples flag equal to trials (one per trial).
Draw samples from the covariate distribution provides an implementation of SVI . In [ 1 ] we amortise the variational parameters with a recognition network . Note the input to this network is the final output i . e . all latents in each layer of a deep GP are mapped from the final output layer . History in GLMs is incorporated through the offset before the batch_edge values indicating the batching timepoints . AR ( 1 ) structure is incorporated by appending the first timestep of the next batch into the current one which is then used for computing the Markovian prior . Note that in LVM + GLM the first filter_len - 1 number of LVs is not inferred . Note when input is trialled we can only have MC samples flag equal to trials ( one per trial ) .
def sample_XZ(self, b, samples, net_input=None, entropy=False):
        if self.regressor_mode: 
            XZ, kl_stim = self._time_slice(self._XZ(self.XZ[b], samples))
            dummy = torch.zeros(samples*self.trials).to(self.dummy.device)
            return XZ, dummy, 0 if entropy else dummy, kl_stim
        log_prior = 0
        nlog_q = 0
        KL_prior = 0
        cov = []
        for k, vi in enumerate(self.VI_tuples):
            p, v, topo, dims = vi
            if p is None or isinstance(self.XZ[k], list): 
                cov.append(self._XZ(self.XZ[k][b], samples))
                continue
            if v == 'VAE': 
                mu, std = self._VAE(k, net_input.t().to(self.dummy.device))
            else:
                mu, std = self._latents(b, k, dims, topo)       
            vd = self.variational[k](mu, std)
            v_samp = vd((samples,)) 
            if v == 'NF':
                NF_net = getattr(self, 'lv_NF_{}'.format(k))
                v_samp, log_jacob = NF_net(v_samp)
            if self.AR_p == 1: 
                if p == 'RW_mapping':
                    loc, std = self.prior_moments(k)
                    pd = self.prior_dist[k](loc, std)
                    f_loc, f_var, log_p_m, nlog_q_m, kl_p = self._mapping(b, k, dims, net_input, entropy)
                    log_prior = log_prior + log_p_m
                    nlog_q = nlog_q + nlog_q_m
                    KL_prior = KL_prior + kl_p
                    rd = distributions.Rn_Normal(f_loc, f_var.sqrt())
                    dv = v_samp[:, 1:]-v_samp[:, :-1]
                    if topo == 'torus': 
                        dv = dv % (2*np.pi)
                        dv[dv > np.pi] = dv[dv > np.pi] - 2*np.pi
                    rw_term = self._log_p(rd, dv)
                elif p == 'RW':                    
                    loc, std = self.prior_moments(k)
                    if topo == 'euclid': 
                        loc =  torch.sigmoid(loc)
                        rd = self.rw_dist[k](loc*v_samp[:, :-1], std*torch.sqrt(1-loc**2))
                        pd = self.prior_dist[k](0., std)
                    elif topo == 'torus': 
                        rd = self.rw_dist[k](v_samp[:, :-1]+loc, std)
                        pd = self.prior_dist[k](loc)
                    elif topo == 'sphere':
                        rd = self.rw_dist[k](v_samp[:, :-1, :], std)
                        pd = self.prior_dist[k](loc)
                    rw_term = self._log_p(rd, v_samp[:, 1:])
                if self.batch_link[b]:
                    prior_term = rw_term
                else: 
                    prior_term = rw_term + self._log_p(pd, v_samp[:, 0:1]) 
                start = self.AR_p if self.batch_link[b] else 0 
                var_term = self._nlog_q(vd, v_samp, entropy, start)
                v_samp_ = v_samp[:, start:]
            else:
                if p == 'mapping':
                    f_loc, f_var, log_p_m, nlog_q_m, kl_p = self._mapping(b, k, dims, net_input, entropy)
                    log_prior = log_prior + log_p_m
                    nlog_q = nlog_q + nlog_q_m
                    KL_prior = KL_prior + kl_p
                    pd = distributions.Rn_Normal(f_loc, f_var.sqrt())
                else:
                    loc, std = self.prior_moments(k)
                    pd = self.prior_dist[k](loc, std)
                prior_term = self._log_p(pd, v_samp)
                var_term = self._nlog_q(vd, v_samp, entropy)
                v_samp_ = v_samp
            fac = self.tsteps / v_samp_.shape[1] 
            log_prior = log_prior + fac*prior_term
            nlog_q = nlog_q + fac*var_term
            if len(v_samp_.shape) == 2: 
                v_samp_ = v_samp_[..., None]
            cov.append(v_samp_)
        XZ, kl_stim = self._time_slice(torch.cat(cov, dim=-1))
        return XZ, log_prior, nlog_q, KL_prior+kl_stim
def sample_XZ ( self , b , samples , net_input = None , entropy = False ) : if self . regressor_mode : XZ , kl_stim = self . _time_slice ( self . _XZ ( self . XZ [ b ] , samples ) ) dummy = torch . zeros ( samples * self . trials ) . to ( self . dummy . device ) return XZ , dummy , 0 if entropy else dummy , kl_stim log_prior = 0 nlog_q = 0 KL_prior = 0 cov = [ ] for k , vi in enumerate ( self . VI_tuples ) : p , v , topo , dims = vi if p is None or isinstance ( self . XZ [ k ] , list ) : cov . append ( self . _XZ ( self . XZ [ k ] [ b ] , samples ) ) continue if v == 'VAE' : mu , std = self . _VAE ( k , net_input . t ( ) . to ( self . dummy . device ) ) else : mu , std = self . _latents ( b , k , dims , topo ) vd = self . variational [ k ] ( mu , std ) v_samp = vd ( ( samples , ) ) if v == 'NF' : NF_net = getattr ( self , 'lv_NF_{}' . format ( k ) ) v_samp , log_jacob = NF_net ( v_samp ) if self . AR_p == 1 : if p == 'RW_mapping' : loc , std = self . prior_moments ( k ) pd = self . prior_dist [ k ] ( loc , std ) f_loc , f_var , log_p_m , nlog_q_m , kl_p = self . _mapping ( b , k , dims , net_input , entropy ) log_prior = log_prior + log_p_m nlog_q = nlog_q + nlog_q_m KL_prior = KL_prior + kl_p rd = distributions . Rn_Normal ( f_loc , f_var . sqrt ( ) ) dv = v_samp [ : , 1 : ] - v_samp [ : , : - 1 ] if topo == 'torus' : dv = dv % ( 2 * np . pi ) dv [ dv > np . pi ] = dv [ dv > np . pi ] - 2 * np . pi rw_term = self . _log_p ( rd , dv ) elif p == 'RW' : loc , std = self . prior_moments ( k ) if topo == 'euclid' : loc = torch . sigmoid ( loc ) rd = self . rw_dist [ k ] ( loc * v_samp [ : , : - 1 ] , std * torch . sqrt ( 1 - loc ** 2 ) ) pd = self . prior_dist [ k ] ( 0. , std ) elif topo == 'torus' : rd = self . rw_dist [ k ] ( v_samp [ : , : - 1 ] + loc , std ) pd = self . prior_dist [ k ] ( loc ) elif topo == 'sphere' : rd = self . rw_dist [ k ] ( v_samp [ : , : - 1 , : ] , std ) pd = self . prior_dist [ k ] ( loc ) rw_term = self . _log_p ( rd , v_samp [ : , 1 : ] ) if self . batch_link [ b ] : prior_term = rw_term else : prior_term = rw_term + self . _log_p ( pd , v_samp [ : , 0 : 1 ] ) start = self . AR_p if self . batch_link [ b ] else 0 var_term = self . _nlog_q ( vd , v_samp , entropy , start ) v_samp_ = v_samp [ : , start : ] else : if p == 'mapping' : f_loc , f_var , log_p_m , nlog_q_m , kl_p = self . _mapping ( b , k , dims , net_input , entropy ) log_prior = log_prior + log_p_m nlog_q = nlog_q + nlog_q_m KL_prior = KL_prior + kl_p pd = distributions . Rn_Normal ( f_loc , f_var . sqrt ( ) ) else : loc , std = self . prior_moments ( k ) pd = self . prior_dist [ k ] ( loc , std ) prior_term = self . _log_p ( pd , v_samp ) var_term = self . _nlog_q ( vd , v_samp , entropy ) v_samp_ = v_samp fac = self . tsteps / v_samp_ . shape [ 1 ] log_prior = log_prior + fac * prior_term nlog_q = nlog_q + fac * var_term if len ( v_samp_ . shape ) == 2 : v_samp_ = v_samp_ [ ... , None ] cov . append ( v_samp_ ) XZ , kl_stim = self . _time_slice ( torch . cat ( cov , dim = - 1 ) ) return XZ , log_prior , nlog_q , KL_prior + kl_stim
Draw samples from the covariate distribution, provides an implementation of SVI.
Draw samples from the covariate distribution provides an implementation of SVI .
"""
        Draw samples from the covariate distribution, provides an implementation of SVI.
        In [1] we amortise the variational parameters with a recognition network. Note the input 
        to this network is the final output, i.e. all latents in each layer of a deep GP are mapped 
        from the final output layer.
        
        History in GLMs is incorporated through the offset before the batch_edge values indicating the 
        batching timepoints. AR(1) structure is incorporated by appending the first timestep of the next 
        batch into the current one, which is then used for computing the Markovian prior.
        
        Note that in LVM + GLM, the first filter_len-1 number of LVs is not inferred.
        
        Note when input is trialled, we can only have MC samples flag equal to trials (one per trial).
        
        :param int b: the batch ID to sample from
        :param int samples: the number of samples to take
        :param torch.tensor net_input: direct input for VAE amortization of shape (dims, time)
        :returns: covariates sample of shape (samples, timesteps, dims), log_prior
        :rtype: tuple
        
        References:
        
        [1] `Variational auto-encoded deep Gaussian Processes`,
        Zhenwen Dai, Andreas Damianou, Javier Gonzalez & Neil Lawrence
        
        """ # regressor mode, no lv, trial blocks are repeated ### LVM ### # regressor variable ### continuous latent variables ###       # compute the variational parameters #.to_event() # samples, time, event_dims ### prior setup ###             # AR(1) structure #if GP.cov_type == 'full': #    rd = distributions.Rn_MVN(f_loc, covariance_matrix=f_var) # geodesic distance # stationary linear  # drift DS #.to_event() # add log prob of first initial time step # sum over time (and dims if > 1) # avoid overlap from AR structure # RW prior case, don't double count edge parameter, v_samp contains extra overlap when batch_link True #if GP.cov_type == 'full': #    pd = distributions.Rn_MVN(f_loc[0], covariance_matrix=f_var[0]) #.to_event() ### compute log probability terms ### # subsampling in batched mode # one-dimensional latent variables expanded
covariates sample of shape (samples, timesteps, dims), log_prior
covariates sample of shape ( samples timesteps dims ) log_prior
tuple
References:

[1] `Variational auto-encoded deep Gaussian Processes`,
Zhenwen Dai, Andreas Damianou, Javier Gonzalez & Neil Lawrence
self
b
the batch ID to sample from
the batch ID to sample from
samples
the number of samples to take
the number of samples to take
net_input
direct input for VAE amortization of shape (dims, time)
direct input for VAE amortization of shape ( dims time )
entropy