def lml_derivative_over_cov(self, dQS): from numpy_sugar.linalg import cho_solve, ddot, dotd self._update() L = self._posterior.L() Q = self._posterior.cov["QS"][0][0] ttau = self._site.tau teta = self._site.eta diff = teta - ttau * self._posterior.mean v0 = dot(dQS[0][0], dQS[1] * dot(dQS[0][0].T, diff)) v1 = ttau * dot(Q, cho_solve(L, dot(Q.T, diff))) dlml = 0.5 * dot(diff, v0) dlml -= dot(v0, v1) dlml += 0.5 * dot(v1, dot(dQS[0][0], dQS[1] * dot(dQS[0][0].T, v1))) dqs = ddot(dQS[1], dQS[0][0].T, left=True) diag = dotd(dQS[0][0], dqs) dlml -= 0.5 * sum(ttau * diag) tmp = cho_solve(L, dot(ddot(Q.T, ttau, left=False), dQS[0][0])) dlml += 0.5 * sum(ttau * dotd(Q, dot(tmp, dqs))) return dlml
def _joint_update(self): A = self._A() C = self._C() m = self.m() Q = self._Q v = self.v delta = self.delta teta = self._sitelik_eta jtau = self._joint_tau jeta = self._joint_eta Kteta = self._Kdot(teta) BiQt = self._BiQt() uBiQtAK0, uBiQtAK1 = self._uBiQtAK() jtau[:] = -dotd(Q, uBiQtAK0) jtau *= 1 - delta jtau -= delta * dotd(Q, uBiQtAK1) jtau *= v jtau += self._diagK() jtau[:] = 1 / jtau dot(Q, dot(BiQt, -A * Kteta), out=jeta) jeta += Kteta jeta += m jeta -= self._QBiQtAm() jeta *= jtau jtau /= C
def update(self): from numpy_sugar.linalg import ddot, dotd self._flush_cache() s = self._cov["scale"] d = self._cov["delta"] Q = self._cov["QS"][0][0] A = self.A LQt = self.LQt() T = self._site.tau E = self._site.eta AQ = self.AQ() QS = self.QS() LQtA = ddot(LQt, A) D = self.QSQtATQLQtA() self.tau[:] = s * (1 - d) * dotd(QS, AQ.T) self.tau -= s * (1 - d) * D * (1 - d) self.tau += s * d * A self.tau -= s * d * dotd(self.ATQ(), LQtA) * (1 - d) self.tau **= -1 v = s * (1 - d) * dot(Q, dot(QS.T, E)) + s * d * E + self._mean self.eta[:] = A * v self.eta -= dot(AQ, dot(LQtA, T * v)) * (1 - d) self.eta *= self.tau
def lml_derivatives(self, dm): from numpy_sugar.linalg import dotd if self._cache["grad"] is not None: return self._cache["grad"] self._update() LQt = self._posterior.LQt() ATQ = self._posterior.ATQ() ttau = self._site.tau teta = self._site.eta A = self._posterior.A cov = self._posterior.cov Q = cov["QS"][0][0] s = cov["scale"] d = cov["delta"] QS = self._posterior.QS() e_m = teta - ttau * self._posterior.mean Ae_m = A * e_m TA = ttau * A LtQTAe_m = dot(LQt, Ae_m) tQTAe_m = dot(Q.T, Ae_m) dKAd_m = dot(QS, tQTAe_m) * (1 - d) + d * Ae_m w = TA * dot(Q, LtQTAe_m) * (1 - d) QTAe_m = dot(Q.T, Ae_m) dKAs_m = -s * dot(QS, QTAe_m) + s * Ae_m r = (self._posterior.QSQtATQLQtA() * ttau).sum() dlml_mean = dot(e_m, ldot(A, dm)) - dot( Ae_m, dot(Q, dot(LQt, ldot(TA, dm))) ) * (1 - d) r1 = (TA * dotd(Q, LQt) * TA).sum() dlml_scale = 0.5 * dot(Ae_m, dKAd_m) dlml_scale -= sum(w * dKAd_m) dlml_scale += 0.5 * dot(w, dot(QS, dot(Q.T, w) * (1 - d)) + d * w) dlml_scale -= 0.5 * dotd(ATQ, QS.T).sum() * (1 - d) dlml_scale -= 0.5 * sum(TA) * d dlml_scale += 0.5 * r * (1 - d) * (1 - d) dlml_scale += 0.5 * d * r1 * (1 - d) dlml_delta = 0.5 * dot(Ae_m, dKAs_m) dlml_delta -= sum(w * dKAs_m) dlml_delta += 0.5 * dot(w, -s * dot(QS, dot(Q.T, w)) + s * w) dlml_delta += 0.5 * s * dotd(ATQ, QS.T).sum() dlml_delta -= 0.5 * sum(TA) * s dlml_delta -= 0.5 * s * r * (1 - d) dlml_delta += 0.5 * s * r1 * (1 - d) g = dict(mean=dlml_mean, scale=dlml_scale, delta=dlml_delta) self._cache["grad"] = g return g
def update(self): from numpy_sugar.linalg import ddot, dotd self._flush_cache() Q = self._cov["QS"][0][0] K = dot(self.QS(), Q.T) BiQt = self.LQt() TK = ddot(self._site.tau, K, left=True) BiQtTK = dot(BiQt, TK) self.tau[:] = K.diagonal() self.tau -= dotd(Q, BiQtTK) self.tau[:] = 1 / self.tau if not all(self.tau >= 0.0): raise RuntimeError("'tau' has to be non-negative.") self.eta[:] = dot(K, self._site.eta) self.eta[:] += self._mean self.eta[:] -= dot(Q, dot(BiQtTK, self._site.eta)) self.eta[:] -= dot(Q, dot(BiQt, self._site.tau * self._mean)) self.eta *= self.tau
def _bstar_1effect(beta, alpha, yTBy, yTBX, yTBM, XTBX, XTBM, MTBM): """ Same as :func:`_bstar_set` but for single-effect. """ from numpy_sugar import epsilon from numpy_sugar.linalg import dotd from numpy import sum r = full(MTBM[0].shape[0], yTBy) r -= 2 * add.reduce([dot(i, beta) for i in yTBX]) r -= 2 * add.reduce([i * alpha for i in yTBM]) r += add.reduce([dotd(beta.T, dot(i, beta)) for i in XTBX]) r += add.reduce([dotd(beta.T, i * alpha) for i in XTBM]) r += add.reduce([sum(alpha * i * beta, axis=0) for i in XTBM]) r += add.reduce([alpha * i.ravel() * alpha for i in MTBM]) return clip(r, epsilon.tiny, inf)
def test_dotd(): random = RandomState(958) A = random.randn(10, 2) B = random.randn(2, 10) r = A.dot(B).diagonal() assert_allclose(r, dotd(A, B)) r1 = empty(len(r)) assert_allclose(dotd(A, B, out=r1), r) a = random.randn(2) b = random.randn(2) c = array(0.0) assert_allclose(dotd(a, b), -1.05959423672) dotd(a, b, out=c) assert_allclose(c, -1.05959423672)
def _init_svd(self): from numpy_sugar.linalg import dotd from scipy.linalg import svd if self._Lx is not None: return G = self._G U, S, _ = svd(G, check_finite=False) S *= S self._Sxe = S self._Sx = concatenate((S, [0.0] * (U.shape[0] - S.shape[0]))) self._Lx = U.T self._LxG = self._Lx @ G self._diag_LxGGLx = dotd(self._LxG, self._LxG.T) self._Lxe = U[:, : S.shape[0]].T self._LxGe = self._Lxe @ G self._diag_LxGGLxe = dotd(self._LxGe, self._LxGe.T)
def logdet_gradient(self): """ Implements ∂log|K| = Tr[K⁻¹∂K]. It can be shown that:: ∂log|K| = diag(D)ᵀdiag(L(∂K)Lᵀ) = diag(D)ᵀ(diag(Lₕ∂C₀Lₕᵀ)⊗diag(LₓGGᵀLₓᵀ)), when the derivative is over the parameters of C₀. Similarly, ∂log|K| = diag(D)ᵀdiag(L(∂K)Lᵀ) = diag(D)ᵀ(diag(Lₕ∂C₁Lₕᵀ)⊗diag(I)), over the parameters of C₁. Returns ------- C0 : ndarray Derivative of C₀ over its parameters. C1 : ndarray Derivative of C₁ over its parameters. """ from numpy_sugar.linalg import dotd self._init_svd() dC0 = self._C0.gradient()["Lu"] grad_C0 = zeros_like(self._C0.Lu) for i in range(self._C0.Lu.shape[0]): t = kron(dotd(self.Lh, dC0[..., i] @ self.Lh.T), self._diag_LxGGLxe) grad_C0[i] = (self._De * t).sum() dC1 = self._C1.gradient()["Lu"] grad_C1 = zeros_like(self._C1.Lu) p = self._Sxe.shape[0] np = self._G.shape[0] - p for i in range(self._C1.Lu.shape[0]): t = (dotd(self.Lh, dC1[..., i] @ self.Lh.T) * np).sum() t1 = kron(dotd(self.Lh, dC1[..., i] @ self.Lh.T), eye(p)) t += (self._De * t1).sum() grad_C1[i] = t return {"C0.Lu": grad_C0, "C1.Lu": grad_C1}
def QSQtATQLQtA(self): from numpy_sugar.linalg import ddot, dotd if self._QSQtATQLQtA_cache is not None: return self._QSQtATQLQtA_cache LQt = self.LQt() A = self.A Q = self._cov["QS"][0][0] LQtA = ddot(LQt, A) AQ = self.AQ() QS = self.QS() T = self._site.tau self._QSQtATQLQtA_cache = dotd(QS, dot(dot(ddot(AQ.T, T), Q), LQtA)) return self._QSQtATQLQtA_cache