def likelihood_worker(allX, allCov, otherX, otherCov=None, smooth=None, W=None): if otherCov is not None: V = allCov[np.newaxis] + otherCov[:,np.newaxis] if smooth is not None: H = np.eye(allCov.shape[-1]) * smooth**2 if W is not None: H = np.einsum('mj,jk->mk', W, H) H = np.einsum('lk,mk->ml', W, H) V += H[np.newaxis,np.newaxis] ll = log_multivariate_gaussian(allX[np.newaxis], otherX[:,np.newaxis], V) else: V = allCov if smooth is not None: H = np.eye(allCov.shape[-1]) * smooth**2 if W is not None: H = np.einsum('mj,jk->mk', W, H) H = np.einsum('lk,mk->ml', W, H) V += H[np.newaxis] ll = log_multivariate_gaussian(allX[np.newaxis], otherX[:,np.newaxis], V[np.newaxis]) ll = logsumexp(ll, axis=0) # NOTE: could also max here return ll
def test_log_multivariate_gaussian_methods(): np.random.seed(0) x = np.random.random(3) mu = np.random.random(3) V = positive_definite_matrix(3, M=10) res1 = log_multivariate_gaussian(x, mu, V, method=0) res2 = log_multivariate_gaussian(x, mu, V, method=1) assert_array_almost_equal(res1, res2)
def test_log_multivariate_gaussian_methods(): np.random.seed(0) x = np.random.random(3) mu = np.random.random(3) V = positive_definite_matrix(3, M=10) res1 = log_multivariate_gaussian(x, mu, V, method=0) res2 = log_multivariate_gaussian(x, mu, V, method=1) assert_array_almost_equal(res1, res2)
def test_log_multivariate_gaussian_Vinv(): np.random.seed(0) x = np.random.random((2, 1, 1, 3)) mu = np.random.random((3, 1, 3)) V = positive_definite_matrix(3, M=4) Vinv = np.array([np.linalg.inv(Vi) for Vi in V]) res1 = log_multivariate_gaussian(x, mu, V) res2 = log_multivariate_gaussian(x, mu, V, Vinv=Vinv) assert_array_almost_equal(res1, res2)
def test_log_multivariate_gaussian_Vinv(): np.random.seed(0) x = np.random.random((2, 1, 1, 3)) mu = np.random.random((3, 1, 3)) V = positive_definite_matrix(3, M=4) Vinv = np.array([np.linalg.inv(Vi) for Vi in V]) res1 = log_multivariate_gaussian(x, mu, V) res2 = log_multivariate_gaussian(x, mu, V, Vinv=Vinv) assert_array_almost_equal(res1, res2)
def logprob_a(self, X, Xerr): """ Evaluate the probability for a set of points Parameters ---------- X: array_like Input data. shape = (n_samples, n_features) Xerr: array_like Error on input data. shape = (n_samples, n_features, n_features) Returns ------- p: ndarray Probabilities. shape = (n_samples,) """ X = np.asarray(X) Xerr = np.asarray(Xerr) n_samples, n_features = X.shape # assume full covariances of data assert Xerr.shape == (n_samples, n_features, n_features) X = X[:, np.newaxis, :] Xerr = Xerr[:, np.newaxis, :, :] T = Xerr + self.V return log_multivariate_gaussian(X, self.mu, T)
def logprob_a(self, X, Xerr): """ Evaluate the probability for a set of points Parameters ---------- X: array_like Input data. shape = (n_samples, n_features) Xerr: array_like Error on input data. shape = (n_samples, n_features, n_features) Returns ------- p: ndarray Probabilities. shape = (n_samples,) """ X = np.asarray(X) Xerr = np.asarray(Xerr) n_samples, n_features = X.shape # assume full covariances of data assert Xerr.shape == (n_samples, n_features, n_features) X = X[:, np.newaxis, :] Xerr = Xerr[:, np.newaxis, :, :] T = Xerr + self.V return log_multivariate_gaussian(X, self.mu, T)
def test_log_multivariate_gaussian(): np.random.seed(0) x = np.random.random((2, 1, 1, 3)) mu = np.random.random((3, 1, 3)) V = positive_definite_matrix(3, M=4) res1 = log_multivariate_gaussian(x, mu, V) assert res1.shape == (2, 3, 4) res2 = np.zeros_like(res1) for i in range(2): for j in range(3): for k in range(4): res2[i, j, k] = log_multivariate_gaussian(x[i, 0, 0], mu[j, 0], V[k]) assert_array_almost_equal(res1, res2)
def test_log_multivariate_gaussian(): np.random.seed(0) x = np.random.random((2, 1, 1, 3)) mu = np.random.random((3, 1, 3)) V = positive_definite_matrix(3, M=4) res1 = log_multivariate_gaussian(x, mu, V) assert res1.shape == (2, 3, 4) res2 = np.zeros_like(res1) for i in range(2): for j in range(3): for k in range(4): res2[i, j, k] = log_multivariate_gaussian(x[i, 0, 0], mu[j, 0], V[k]) assert_array_almost_equal(res1, res2)
def _EMstep(self, X, Xerr): """ Perform the E-step (eq 16 of Bovy et al) """ n_samples, n_features = X.shape X = X[:, np.newaxis, :] Xerr = Xerr[:, np.newaxis, :, :] w_m = X - self.mu T = Xerr + self.V #------------------------------------------------------------ # compute inverse of each covariance matrix T Tshape = T.shape T = T.reshape([n_samples * self.n_components, n_features, n_features]) Tinv = np.array([linalg.inv(T[i]) for i in range(T.shape[0])]).reshape(Tshape) T = T.reshape(Tshape) #------------------------------------------------------------ # evaluate each mixture at each point N = np.exp(log_multivariate_gaussian(X, self.mu, T, Vinv=Tinv)) #------------------------------------------------------------ # E-step: # compute q_ij, b_ij, and B_ij q = (N * self.alpha) / np.dot(N, self.alpha)[:, None] tmp = np.sum(Tinv * w_m[:, :, np.newaxis, :], -1) b = self.mu + np.sum(self.V * tmp[:, :, np.newaxis, :], -1) tmp = np.sum(Tinv[:, :, :, :, np.newaxis] * self.V[:, np.newaxis, :, :], -2) B = self.V - np.sum(self.V[:, :, :, np.newaxis] * tmp[:, :, np.newaxis, :, :], -2) #------------------------------------------------------------ # M-step: # compute alpha, m, V qj = q.sum(0) self.alpha = qj / n_samples self.mu = np.sum(q[:, :, np.newaxis] * b, 0) / qj[:, np.newaxis] m_b = self.mu - b tmp = m_b[:, :, np.newaxis, :] * m_b[:, :, :, np.newaxis] tmp += B tmp *= q[:, :, np.newaxis, np.newaxis] self.V = tmp.sum(0) / qj[:, np.newaxis, np.newaxis]
def _EMstep(self, X, Xerr): """ Perform the E-step (eq 16 of Bovy et al) """ n_samples, n_features = X.shape X = X[:, np.newaxis, :] Xerr = Xerr[:, np.newaxis, :, :] w_m = X - self.mu T = Xerr + self.V #------------------------------------------------------------ # compute inverse of each covariance matrix T Tshape = T.shape T = T.reshape([n_samples * self.n_components, n_features, n_features]) Tinv = np.array([linalg.inv(T[i]) for i in range(T.shape[0])]).reshape(Tshape) T = T.reshape(Tshape) #------------------------------------------------------------ # evaluate each mixture at each point N = np.exp(log_multivariate_gaussian(X, self.mu, T, Vinv=Tinv)) #------------------------------------------------------------ # E-step: # compute q_ij, b_ij, and B_ij q = (N * self.alpha) / np.dot(N, self.alpha)[:, None] tmp = np.sum(Tinv * w_m[:, :, np.newaxis, :], -1) b = self.mu + np.sum(self.V * tmp[:, :, np.newaxis, :], -1) tmp = np.sum( Tinv[:, :, :, :, np.newaxis] * self.V[:, np.newaxis, :, :], -2) B = self.V - np.sum( self.V[:, :, :, np.newaxis] * tmp[:, :, np.newaxis, :, :], -2) #------------------------------------------------------------ # M-step: # compute alpha, m, V qj = q.sum(0) self.alpha = qj / n_samples self.mu = np.sum(q[:, :, np.newaxis] * b, 0) / qj[:, np.newaxis] m_b = self.mu - b tmp = m_b[:, :, np.newaxis, :] * m_b[:, :, :, np.newaxis] tmp += B tmp *= q[:, :, np.newaxis, np.newaxis] self.V = tmp.sum(0) / qj[:, np.newaxis, np.newaxis]
def likelihood_worker(y, ivar, M, mu, Lambda, make_aA=False): """ Internal function used to construct linear algebra objects used to compute the marginal log-likelihood. Parameters ---------- M : array_like Design matrix. ivar : array_like Inverse-variance matrix. y : array_like Data (in this case, radial velocities). mu : array_like Prior mean for linear parameters. Lambda : array_like Prior variance matrix for linear parameters. Returns ------- B : `numpy.ndarray` C + M Λ M^T - Variance of data gaussian. b : `numpy.ndarray` M µ - Optimal values of linear parameters. chi2 : float Chi-squared value. Notes ----- The linear parameter vector returned here (``b``) may have a negative velocity semi-amplitude. I don't think there is anything we can do about this if we want to preserve the simple linear algebra below and it means that optimizing over the marginal likelihood below won't work -- in the argument of periastron, there will be two peaks of similar height, and so the highest marginal likelihood period might be shifted from the truth. """ Λ = Lambda Λinv = np.linalg.inv(Λ) µ = mu Cinv = np.diag(ivar) C = np.diag(1 / ivar) b = M @ µ B = C + M @ Λ @ M.T # Old implementation: # old_marg_ll = multivariate_normal.logpdf(y, b, B) # if make_aAinv: # Ainv = Λinv + M.T @ Cinv @ M # # Note: this is unstable! if cond num is high, could do: # # p, *_ = np.linalg.lstsq(A, y) # a = np.linalg.solve(Ainv, Λinv @ mu + M.T @ Cinv @ y) # return marg_ll, b, B, a, Ainv # else: # return marg_ll, b, B # New implementation: Ainv = Λinv + M.T @ Cinv @ M A = np.linalg.inv(Ainv) Binv = Cinv - Cinv @ M @ A @ M.T @ Cinv marg_ll = log_multivariate_gaussian(y, b, B, Vinv=Binv) if make_aA: # Note: this is unstable! if cond num is high, could do: # p, *_ = np.linalg.lstsq(A, y) a = np.linalg.solve(Ainv, Λinv @ mu + M.T @ Cinv @ y) return marg_ll, b, B, a, A else: return marg_ll, b, B