def setbeta(self, ep_beta): sz = self.size_pars() if not helpers.check_vecsize(ep_beta, sz): raise TypeError('EP_BETA must be vector of size {0}'.format(sz)) if self.ep_beta is None: self.ep_beta = np.empty(sz) self.ep_beta[:] = ep_beta
def setpi(self, ep_pi): sz = self.size_pars() if not helpers.check_vecsize(ep_pi, sz): raise TypeError('EP_PI must be vector of size {0}'.format(sz)) if self.ep_pi is None: self.ep_pi = np.empty(sz) self.ep_pi[:] = ep_pi
def mat_btdb(self,v,out=None): if not helpers.check_vecsize(v,self.m): raise TypeError('V wrong') if out is None: return np.diag(v) else: self._matbtdb_setdgout(out,v) return out
def mat_btdb(self, v, out=None): if not helpers.check_vecsize(v, self.m): raise TypeError('V wrong') if out is None: return np.diag(v) else: self._matbtdb_setdgout(out, v) return out
def predict(self, pbfact, pmeans, pvars=None): if not isinstance(pbfact, cf.MatFactorizedInf): raise TypeError('PBFACT must be apbsint.MatFactorizedInf') pm, n = pbfact.shape() if n != self.bfact.shape(1): raise TypeError('PBFACT has wrong size') if not (helpers.check_vecsize(pmeans, pm) and (pvars is None or helpers.check_vecsize(pvars, pm))): raise TypeError('PMEANS or PVARS wrong') tvec = 1. / self.marg_pi if pvars is not None: # 'pbfact.b2fact' is B_test**2 pvars[:] = pbfact.b2fact.dot(tvec) tvec *= self.marg_beta if pmeans.flags['C_CONTIGUOUS']: pbfact.mvm(tvec, pmeans) else: pmeans[:] = pbfact.mvm(tvec)
def _mvm_checkin(self, v, out): """ Tests input arguments to 'mvm'. Returns buffer vector for result, which is 'out' if given, otherwise a new vector. """ m, n = self.shape() if not helpers.check_vecsize(v, n): raise TypeError('V wrong') return self._check_resultvec(out, m)
def _mvm_checkin(self,v,out): """ Tests input arguments to 'mvm'. Returns buffer vector for result, which is 'out' if given, otherwise a new vector. """ m, n = self.shape() if not helpers.check_vecsize(v,n): raise TypeError('V wrong') return self._check_resultvec(out,m)
def _check_resultvec(self,out,sz): """ If 'out' is not None, checks that it is a contiguous vector of size 'sz'. Otherwise, a vector of this size is created. In any case, the vector is returned. """ if out is None: out = np.empty(sz) elif not (helpers.check_vecsize(out,sz) and out.flags['C_CONTIGUOUS']): raise TypeError('OUT argument wrong (must be contiguous)') return out
def __init__(self,dg): if isinstance(dg,MatDiag): Mat.__init__(self,dg) self.dg = dg.dg self.sqdg = dg.sqdg else: if not helpers.check_vecsize(dg) or dg.shape[0] == 0: raise TypeError('DG wrong type or size') n = dg.shape[0] Mat.__init__(self,n,n) self.dg = dg self.sqdg = dg**2
def __init__(self, dg): if isinstance(dg, MatDiag): Mat.__init__(self, dg) self.dg = dg.dg self.sqdg = dg.sqdg else: if not helpers.check_vecsize(dg) or dg.shape[0] == 0: raise TypeError('DG wrong type or size') n = dg.shape[0] Mat.__init__(self, n, n) self.dg = dg self.sqdg = dg**2
def _check_resultvec(self, out, sz): """ If 'out' is not None, checks that it is a contiguous vector of size 'sz'. Otherwise, a vector of this size is created. In any case, the vector is returned. """ if out is None: out = np.empty(sz) elif not (helpers.check_vecsize(out, sz) and out.flags['C_CONTIGUOUS']): raise TypeError('OUT argument wrong (must be contiguous)') return out
def predict(self, pbfact, pmeans, pvars=None, use_cov=False): """ Compute predictive means (and variances, optional), given test set coupling factor B_p (in 'pbfact'). Predictive variances require A^-1. If 'post_cov' is defined and 'use_cov'==True, A^-1 is taken from 'post_cov'. Otherwise, it is computed here (and written into 'post_cov'). NOTE: Use 'use_cov'=True if 'refresh' with 'keep_margs'=True has been called just before. """ if not isinstance(pbfact, cf.Mat): raise TypeError('PBFACT must be instance of apbsint.Mat') pm, n = pbfact.shape() if n != self.bfact.shape(1): raise TypeError('PBFACT has wrong size') if not (helpers.check_vecsize(pmeans, pm) and (pvars is None or helpers.check_vecsize(pvars, pm))): raise TypeError('PMEANS or PVARS wrong') # Predictive means pbfact.mvm( sla.solve_triangular(self.lfact, self.cvec, lower=True, trans='T'), pmeans) if pvars is not None: # Predictive variances: Need inverse A^-1 try: if self.post_cov.shape != (n, n): raise TypeError( 'Internal error: POST_COV attribute has wrong size') except AttributeError: if use_cov: raise ValueError('POST_COV is not defined') self.post_cov = np.empty((n, n)) amat = self.post_cov if not use_cov: self._comp_inva(amat) pbfact.diag_bsbt(amat, pvars)
def mat_btdb(self,v,out=None): if self.transp: raise NotImplementedError("NOT IMPLEMENTED") if not helpers.check_vecsize(v,self.m): raise TypeError('V wrong') off = 0 m, n = self.shape() if out is None: out = np.empty((n,n)) else: self._matbtdb_checkout(out) out.fill(0.) # 'buffmat1' is allocated once, then reused try: self.buffmat1.resize((n,n),refcheck=False) except AttributeError: self.buffmat1 = np.empty((n,n)) for chd in self.child: sz = chd.shape(0) chd.mat_btdb(v[off:off+sz],self.buffmat1) out += self.buffmat1 off += sz return out
def mat_btdb(self, v, out=None): if self.transp: raise NotImplementedError("NOT IMPLEMENTED") if not helpers.check_vecsize(v, self.m): raise TypeError('V wrong') off = 0 m, n = self.shape() if out is None: out = np.empty((n, n)) else: self._matbtdb_checkout(out) out.fill(0.) # 'buffmat1' is allocated once, then reused try: self.buffmat1.resize((n, n), refcheck=False) except AttributeError: self.buffmat1 = np.empty((n, n)) for chd in self.child: sz = chd.shape(0) chd.mat_btdb(v[off:off + sz], self.buffmat1) out += self.buffmat1 off += sz return out
def get_marg(self, j, vvec=None): """ Returns (mu, rho), mu marginal mean, rho marginal variance at potential j (Gaussian marginal, not tilted marginal). If 'vvec' is given, L^-1 B[j,:] is written there. In this case, the marginal is always computed from scratch. Otherwise, if 'keep_margs'==True, we use 'marg_XXX'. If (mu, rho) are computed from scratch and 'keep_margs'==True, the corr. entries of 'marg_XXX' are refreshed. """ bfact = self.bfact m, n = bfact.shape() if not (isinstance(j, numbers.Integral) and j >= 0 and j < m): raise ValueError('J wrong') if vvec is None: if self.keep_margs: return (self.marg_means[j], self.marg_vars[j]) vvec = np.empty(n) else: if not helpers.check_vecsize(vvec, n): raise TypeError('VVEC wrong') try: self.us_bvec.resize(n, refcheck=False) except AttributeError: self.us_bvec = np.empty(n) bfact.T().getcol(j, self.us_bvec) vvec[:] = sla.solve_triangular(self.lfact, self.us_bvec, lower=True, trans='N') mu = np.inner(vvec, self.cvec) rho = np.inner(vvec, vvec) if self.keep_margs: # Refresh entries self.marg_means[j] = mu self.marg_vars[j] = rho return (mu, rho)
def mat_btdb(self,v,out=None): """ Returns matrix B^T (diag v) B. If 'out' is given, the result is written there directly. 'out' must have exactly the right size and must be C contiguous, otherwise an exception is thrown. """ m, n = self.shape() if not helpers.check_vecsize(v,m): raise TypeError('V wrong') if out is None: out = np.empty((n,n)) else: self._matbtdb_checkout(out) bt = self.T() tv1 = np.zeros(n) tv2 = np.empty(m) for i in xrange(n): tv1[i] = 1. self.mvm(tv1,tv2) tv1[i] = 0. tv2 *= v bt.mvm(tv2,out[i]) return out
def mat_btdb(self, v, out=None): """ Returns matrix B^T (diag v) B. If 'out' is given, the result is written there directly. 'out' must have exactly the right size and must be C contiguous, otherwise an exception is thrown. """ m, n = self.shape() if not helpers.check_vecsize(v, m): raise TypeError('V wrong') if out is None: out = np.empty((n, n)) else: self._matbtdb_checkout(out) bt = self.T() tv1 = np.zeros(n) tv2 = np.empty(m) for i in xrange(n): tv1[i] = 1. self.mvm(tv1, tv2) tv1[i] = 0. tv2 *= v bt.mvm(tv2, out[i]) return out
def seldamp_reset(self, numk, subind=None, subexcl=False): """ Initializes or resets the selective damping (SD) representation. SD ensures that cavity marginals are well-defined after each EP update. The SD representation tracks max_k pi_{k,i} for each variable, by storing the 'numk' largest pi values for each i. The larger 'numk', the less often maxima have to be recomputed. If 'subind' is given, max_k runs only over this index (if 'subexcl'==False) or over its complement (if 'subexcl'==True). """ bf = self.bfact m, n = bf.shape() if not isinstance(numk, numbers.Integral) or numk < 2: raise TypeError('NUMK must be integer > 1') if not (subind is None or (helpers.check_vecsize(subind) and subind.dtype == np.int32)): raise TypeError( 'SUBIND must be numpy.ndarray with dtype numpy.int32') (self.sd_numvalid, self.sd_topind, self.sd_topval) \ = epx.fact_compmaxpi(n,m,bf.rowind,bf.colind,bf.bvals,self.ep_pi, self.ep_beta,numk,subind,subexcl) self.sd_subind = subind self.sd_subexcl = subexcl self.sd_numk = numk
def update_single(self, j, delpi, delbeta, vvec=None): """ Change of EP parameters: ep_pi[j] += delpi; ep_beta[j] += delbeta The representation is updated accordingly. In particular, the Cholesky factor 'lfact' is updated ('delpi'>0) or downdated ('delpi'<0). If 'keep_margs'==True, the marginal moments are updated as well. In 'vvec', the vector L^-1 B[j,:] can be passed. If not, it is recomputed here. NOTE: 'post_cov' (if given) is not updated! """ bfact = self.bfact m, n = bfact.shape() if not (isinstance(j, numbers.Integral) and j >= 0 and j < m and isinstance(delpi, numbers.Real) and isinstance(delbeta, numbers.Real)): raise ValueError('J, DELPI or DELBETA wrong') if not (vvec is None or helpers.check_vecsize(vvec, n)): raise TypeError('VVEC wrong') # Scratch variables. We keep them as members, to avoid having to # allocate them in every call try: self.cup_c.resize(n, refcheck=False) self.cup_s.resize(n, refcheck=False) self.cup_wk.resize(n, refcheck=False) self.cup_z.resize((1, n), refcheck=False) self.us_bvec.resize(n, refcheck=False) if self.keep_margs: self.us_wvec.resize(m, refcheck=False) self.us_w2vec.resize(m, refcheck=False) except AttributeError: self.cup_c = np.empty(n) self.cup_s = np.empty(n) self.cup_wk = np.empty(n) self.cup_z = np.empty((1, n), order='F') self.us_bvec = np.empty(n) if self.keep_margs: self.us_wvec = np.empty(m) self.us_w2vec = np.empty(m) bvec = self.us_bvec if self.keep_margs: wvec = self.us_wvec w2vec = self.us_w2vec if delpi > 0.: # Cholesky update tscal = np.sqrt(delpi) bfact.T().getcol(j, bvec) if self.keep_margs: if vvec is None: # Need 'vvec' below, so compute it here vvec = sla.solve_triangular(self.lfact, bvec, lower=True, trans='N') mu = np.inner(vvec, self.cvec) rho = np.inner(vvec, vvec) bvec *= tscal yscal = np.empty(1) yscal[0] = delbeta / tscal self.cup_z[0] = self.cvec stat = epx.choluprk1(self.lfact, 'L', bvec, self.cup_c, self.cup_s, self.cup_wk, self.cup_z, yscal) if stat != 0: raise sla.LinAlgError( "Numerical error in 'choluprk1' (external)") self.cvec[:] = self.cup_z.ravel() else: # Cholesky downdate tscal = np.sqrt(-delpi) if vvec is None: bfact.T().getcol(j, bvec) vvec = sla.solve_triangular(self.lfact, bvec, lower=True, trans='N') if self.keep_margs: mu = np.inner(vvec, self.cvec) rho = np.inner(vvec, vvec) yscal = np.empty(1) yscal[0] = -delbeta / tscal self.cup_z[0] = self.cvec bvec[:] = vvec bvec *= tscal stat = epx.choldnrk1(self.lfact, 'L', bvec, self.cup_c, self.cup_s, self.cup_wk, self.cup_z, yscal) if stat != 0: raise sla.LinAlgError( "Numerical error in 'choldnrk1' (external)") self.cvec[:] = self.cup_z.ravel() self.ep_pi[j] += delpi self.ep_beta[j] += delbeta if self.keep_margs: # Update marginal moments assert vvec is not None bfact.mvm( sla.solve_triangular(self.lfact, vvec, lower=True, trans='T'), wvec) tscal = 1. / (delpi * rho + 1.) w2vec[:] = wvec w2vec *= ((delbeta - delpi * mu) * tscal) self.marg_means += w2vec wvec *= wvec wvec *= (delpi * tscal) self.marg_vars -= wvec