def expected_log_likelihood(self, xy=None, stats=None): # TODO test values, test for the affine case assert isinstance(xy, (tuple, np.ndarray)) ^ isinstance(stats, tuple) D = self.D_out E_Sigmainv, E_Sigmainv_A, E_AT_Sigmainv_A, E_logdetSigmainv = \ mniw_expectedstats( *self._natural_to_standard(self.mf_natural_hypparam)) if self.affine: E_Sigmainv_A, E_Sigmainv_b = \ E_Sigmainv_A[:,:-1], E_Sigmainv_A[:,-1] E_AT_Sigmainv_A, E_AT_Sigmainv_b, E_bT_Sigmainv_b = \ E_AT_Sigmainv_A[:-1,:-1], E_AT_Sigmainv_A[:-1,-1], \ E_AT_Sigmainv_A[-1,-1] if xy is not None: x, y = (xy[:,:-D], xy[:,-D:]) if isinstance(xy, np.ndarray) \ else xy parammat = -1./2 * blockarray([ [E_AT_Sigmainv_A, -E_Sigmainv_A.T], [-E_Sigmainv_A, E_Sigmainv]]) contract = 'ni,ni->n' if x.ndim == 2 else 'i,i->' if isinstance(xy, np.ndarray): out = np.einsum('ni,ni->n', xy.dot(parammat), xy) else: out = np.einsum(contract,x.dot(parammat[:-D,:-D]),x) out += np.einsum(contract,y.dot(parammat[-D:,-D:]),y) out += 2*np.einsum(contract,x.dot(parammat[:-D,-D:]),y) out += -D/2*np.log(2*np.pi) + 1./2*E_logdetSigmainv if self.affine: out += y.dot(E_Sigmainv_b) out -= x.dot(E_AT_Sigmainv_b) out -= 1./2 * E_bT_Sigmainv_b else: if self.affine: Ey, Ex = stats[:2] yyT, yxT, xxT, n = stats[-4:] contract = 'ij,nij->n' if yyT.ndim == 3 else 'ij,ij->' out = -1./2 * np.einsum(contract, E_AT_Sigmainv_A, xxT) out += np.einsum(contract, E_Sigmainv_A, yxT) out += -1./2 * np.einsum(contract, E_Sigmainv, yyT) out += -D/2*np.log(2*np.pi) + n/2.*E_logdetSigmainv if self.affine: out += Ey.dot(E_Sigmainv_b) out -= Ex.dot(E_AT_Sigmainv_b) out -= 1./2 * E_bT_Sigmainv_b return out
def expected_log_likelihood(self, xy=None, stats=None): # TODO test values, test for the affine case assert isinstance(xy, (tuple, np.ndarray)) ^ isinstance(stats, tuple) D = self.D_out E_Sigmainv, E_Sigmainv_A, E_AT_Sigmainv_A, E_logdetSigmainv = \ mniw_expectedstats( *self._natural_to_standard(self.mf_natural_hypparam)) if self.affine: E_Sigmainv_A, E_Sigmainv_b = \ E_Sigmainv_A[:,:-1], E_Sigmainv_A[:,-1] E_AT_Sigmainv_A, E_AT_Sigmainv_b, E_bT_Sigmainv_b = \ E_AT_Sigmainv_A[:-1,:-1], E_AT_Sigmainv_A[:-1,-1], \ E_AT_Sigmainv_A[-1,-1] if xy is not None: x, y = (xy[:,:-D], xy[:,-D:]) if isinstance(xy, np.ndarray) \ else xy parammat = -1. / 2 * blockarray([[ E_AT_Sigmainv_A, -E_Sigmainv_A.T ], [-E_Sigmainv_A, E_Sigmainv]]) contract = 'ni,ni->n' if x.ndim == 2 else 'i,i->' if isinstance(xy, np.ndarray): out = np.einsum('ni,ni->n', xy.dot(parammat), xy) else: out = np.einsum(contract, x.dot(parammat[:-D, :-D]), x) out += np.einsum(contract, y.dot(parammat[-D:, -D:]), y) out += 2 * np.einsum(contract, x.dot(parammat[:-D, -D:]), y) out += -D / 2 * np.log(2 * np.pi) + 1. / 2 * E_logdetSigmainv if self.affine: out += y.dot(E_Sigmainv_b) out -= x.dot(E_AT_Sigmainv_b) out -= 1. / 2 * E_bT_Sigmainv_b else: if self.affine: Ey, Ex = stats[:2] yyT, yxT, xxT, n = stats[-4:] contract = 'ij,nij->n' if yyT.ndim == 3 else 'ij,ij->' out = -1. / 2 * np.einsum(contract, E_AT_Sigmainv_A, xxT) out += np.einsum(contract, E_Sigmainv_A, yxT) out += -1. / 2 * np.einsum(contract, E_Sigmainv, yyT) out += -D / 2 * np.log(2 * np.pi) + n / 2. * E_logdetSigmainv if self.affine: out += Ey.dot(E_Sigmainv_b) out -= Ex.dot(E_AT_Sigmainv_b) out -= 1. / 2 * E_bT_Sigmainv_b return out
def get_vlb(self): E_Sigmainv, E_Sigmainv_A, E_AT_Sigmainv_A, E_logdetSigmainv = \ mniw_expectedstats(*self._natural_to_standard(self.mf_natural_hypparam)) A, B, C, d = self.natural_hypparam - self.mf_natural_hypparam bilinear_term = -1./2 * np.trace(A.dot(E_Sigmainv)) \ + np.trace(B.T.dot(E_Sigmainv_A)) \ - 1./2 * np.trace(C.dot(E_AT_Sigmainv_A)) \ + 1./2 * d * E_logdetSigmainv # log normalizer term Z = mniw_log_partitionfunction( *self._natural_to_standard(self.natural_hypparam)) Z_mf = mniw_log_partitionfunction( *self._natural_to_standard(self.mf_natural_hypparam)) return bilinear_term - (Z - Z_mf)
def get_vlb(self): E_Sigmainv, E_Sigmainv_A, E_AT_Sigmainv_A, E_logdetSigmainv = \ mniw_expectedstats(*self._natural_to_standard(self.mf_natural_hypparam)) A, B, C, d = self.natural_hypparam - self.mf_natural_hypparam bilinear_term = -1./2 * np.trace(A.dot(E_Sigmainv)) \ + np.trace(B.T.dot(E_Sigmainv_A)) \ - 1./2 * np.trace(C.dot(E_AT_Sigmainv_A)) \ + 1./2 * d * E_logdetSigmainv # log normalizer term Z = mniw_log_partitionfunction(*self._natural_to_standard( self.natural_hypparam)) Z_mf = mniw_log_partitionfunction(*self._natural_to_standard( self.mf_natural_hypparam)) return bilinear_term - (Z - Z_mf)
def get_params(distn): return mniw_expectedstats( *distn._natural_to_standard(distn.mf_natural_hypparam))
def meanfield_expectedstats(self): from pybasicbayes.util.stats import mniw_expectedstats return mniw_expectedstats( *self._natural_to_standard(self.mf_natural_hypparam))
def get_paramseq(distns): contract = partial(np.tensordot, self.expected_states, axes=1) std_param = lambda d: d._natural_to_standard(d.mf_natural_hypparam) params = [mniw_expectedstats(*std_param(d)) for d in distns] return map(contract, zip(*params))