def calcELBO_LinearTerms(SS=None, StartStateCount=None, TransStateCount=None, rho=None, omega=None, Ebeta=None, startTheta=None, transTheta=None, startAlpha=0, alpha=0, kappa=None, gamma=None, afterGlobalStep=0, todict=0, **kwargs): """ Calculate ELBO objective terms that are linear in suff stats. Returns ------- L : scalar float L is sum of any term in ELBO that is const/linear wrt suff stats. """ Ltop = L_top(rho=rho, omega=omega, alpha=alpha, gamma=gamma, kappa=kappa, startAlpha=startAlpha) LdiffcDir = -c_Dir(transTheta) - c_Dir(startTheta) if afterGlobalStep: if todict: return dict(Lalloc=Ltop + LdiffcDir, Lslack=0) return Ltop + LdiffcDir K = rho.size if Ebeta is None: Ebeta = rho2beta(rho, returnSize='K+1') if SS is not None: StartStateCount = SS.StartStateCount TransStateCount = SS.TransStateCount # Augment suff stats to be sure have 0 in final column, # which represents inactive states. if StartStateCount.size == K: StartStateCount = np.hstack([StartStateCount, 0]) if TransStateCount.shape[-1] == K: TransStateCount = np.hstack([TransStateCount, np.zeros((K, 1))]) LstartSlack = np.inner(StartStateCount + startAlpha * Ebeta - startTheta, digamma(startTheta) - digamma(startTheta.sum())) alphaEbetaPlusKappa = alpha * np.tile(Ebeta, (K, 1)) alphaEbetaPlusKappa[:, :K] += kappa * np.eye(K) digammaSum = digamma(np.sum(transTheta, axis=1)) LtransSlack = np.sum((TransStateCount + alphaEbetaPlusKappa - transTheta) * (digamma(transTheta) - digammaSum[:, np.newaxis])) if todict: return dict(Lalloc=Ltop + LdiffcDir, Lslack=LstartSlack + LtransSlack) return Ltop + LdiffcDir + LstartSlack + LtransSlack
def L_alloc_no_slack(self): ''' Compute allocation term of objective function, without slack term Returns ------- L : scalar float ''' prior_cDir = L_top(nDoc=self.theta.shape[0], alpha=self.alpha, gamma=self.gamma, rho=self.rho, omega=self.omega) post_cDir = c_Dir(self.theta, self.thetaRem) return prior_cDir - post_cDir