def KL_Wishart(nu_h, W_h, nu, W):
    '''
    :param nu_h/ nu: float
    :param W_h/ W: arr(D, D)
    :return val: float
    '''
    from numpy import newaxis
    data_dim = len(W[0])
    val = 0
    if W.ndim == 2:
        invW = inv(W)
        invW_wh = dot(invW, W_h)
        val += -0.5 * nu * logdet(invW_wh[newaxis, :, :])
        val += 0.5 * nu_h * (trace(invW_wh) - data_dim)
        for d in range(1, data_dim + 1):
            val += gammaln((nu + 1 - d) / 2.0) - gammaln((nu_h + 1 - d) / 2.0)
            val += (nu_h - nu) * digamma((nu_h + 1.0 - d) / 2.0) / 2.0
    else:
        invW = inv(W.transpose(2, 0, 1)).transpose(1, 2, 0)
        invW_Wh = einsum('dek,efk->kdf', invW, W_h)
        val += -0.5 * nu * logdet(invW_Wh)
        val += 0.5 * nu_h * (trace(invW_Wh) - data_dim)
        nuh_nu = nu_h - nu
        for d in range(1, data_dim + 1):
            lngam_nuh_d_2 = gammaln((nu_h + 1.0 - d) / 2.0)
            lngam_nu_d_2 = gammaln(nu + 1.0 - d / 2.0)
            dig_nuh_d_2 = digamma((nu_h + 1.0 - d) / 2.0)
            val += lngam_nu_d_2 - lngam_nuh_d_2
            val += nuh_nu * dig_nuh_d_2
    return val
Beispiel #2
0
 def calc_inv(self, src):
     if src.ndim == 2:
         dst = inv(src)
     elif src.ndim == 3:
         dst = inv(src.transpose(2, 0, 1)).transpose(1, 2, 0)
     else:
         logger.error('ndim %d is not supported' % src.ndim)
         dst = None
     return dst
Beispiel #3
0
 def _calc_inv(self, src):
     if src.ndim == 1:
         dst = 1.0 / src
     elif src.ndim == 2:
         dst = inv(src)
     elif src.ndim == 3:
         dst = inv(src.transpose(2, 0, 1)).transpose(1, 2, 0)
     elif src.ndim == 4:
         dst = inv(src.transpose(2, 3, 0, 1)).transpose(2, 3, 0, 1)
     else:
         self._log_error_not_supported()
         dst = None
     return dst
def KL_Gauss(mu_h, sig_h, mu, sig):
    '''
    :param mu_h: arr(data_dim)
    :param sig_h: arr(data_dim, data_dim)
    :param mu: arr(data_dim)
    :param sig: arr(data_dim, data_dim)
    :return val: float
    (mu_h - mu)T * sig^{-1} * (mu_h - mu)
    + Tr(inv_sig * sig_h) - data_dim + log(|sig|) - log(|sig_h|)
    '''
    data_dim = len(mu_h)
    inv_sig = inv(sig)
    mu_h_mu = mu_h - mu
    val = 0.5 * (einsum('d,de,e->', mu_h_mu, inv_sig, mu_h_mu) + trace(
        dot(inv_sig, sig_h)) - data_dim + logdet(sig) - logdet(sig_h))
    return val
Beispiel #5
0
 def update(self, Y, z, r):
     '''
     lamb.update(Y, z, r)
     Y: array(data_dim, data_len)
     r.post.expt: <R>
     z.post.expt2: <ZZ>
     '''
     # --- prec (inv(cov))
     rzz = einsum('ddk,ljt->ljdk', r.post.expt, z.expt2)
     prec = self.prior.prec + rzz
     # --- cov
     cov = inv(prec.transpose(2, 3, 1, 0)).transpose(2, 3, 0, 1)
     # --- mean
     yz = einsum('dt,lt->ld', Y, z.mu)
     ryz = einsum('ddk,ld->ldk', r.post.expt, yz)
     pm_ryz = self.prior.expt_prec_mu + ryz
     mean = einsum('ljdk,jdk->ldk', cov, pm_ryz)
     self.post.set_params(mu=mean, cov=cov, prec=prec)
 def sample_mu(self, data_len=1, R=None):
     '''
     mu: (data_len, data_dim, n_states)
     '''
     if R is None:
         R = self.sample_R()[0]
     mu = zeros((data_len, self.data_dim, self.n_states))
     for k in range(self.n_states):
         # cov = inv(self.beta[k] * R[:, :, k])
         cov = inv(R[:, :, k])
         try:
             mu[:, :, k] = mvnrnd(self.mu[:, k], cov, size=data_len)
         except RuntimeWarning as e:
             logger.warn('%s %d. not sampled' % (e, mu.shape[0]))
             mu[:, :, k] = self.mu[newaxis, :, k]
         except Exception as e:
             logger.error('%s %d. not sampled.' % (e, mu.shape[0]))
             mu[:, :, k] = self.mu[newaxis, :, k]
     return mu
Beispiel #7
0
    def update(self, theta, Y):
        '''
        z.update(Y)
        lamb.mu: <lamb> array(aug_dim, data_dim)
        lamb.post.expt2: <lamblambT> array(aug_dim, aug_dim, data_dim)
        r.post.expt: <R> array(data_dim)
        lamb.post.mu: <lamb> array(aug_dim, data_dim)

        '''
        # -- prec
        rll = einsum('ddk,ljdk->lj', theta.r.post.expt, theta.lamb.post.expt2)
        self.prec = rll + self.prior.prec[:, :, 0]
        # --- cov
        self.cov = inv(self.prec)
        # --- mean
        lr = einsum('ldk,ddk->ld', theta.lamb.post.mu, theta.r.post.expt)
        lry = einsum('ld,dt->lt', lr, Y)
        lry_muz = lry + self.prior.expt_prec_mu[:, 0, newaxis]
        self.mu = einsum('lj,jt->lt', self.cov, lry_muz)
        self.expt2 = self.calc_expt2()
Beispiel #8
0
 def Z(cls, fa_dim):
     '''
     DefaultPriors().Z(fa_dim)
     @argvs
     fa_dim: dimention of factor analysis
     @output
     z_mean: np.array(aug_dim)
     z_cov: np.array(aug_dim, aug_dim)
     z_prc: np.array(aug_dim, aug_dim)
     '''
     aug_dim = fa_dim + 1
     # --- Z
     fa_dim = int(aug_dim - 1)
     eps = 1e-8
     # eps = get_eps()
     # eps = get_eps() * 1e+10
     z_mean = append(zeros(fa_dim), [1])
     z_cov = eye(aug_dim)
     z_cov[-1, -1] = eps
     z_prc = inv(z_cov)
     return z_mean, z_cov, z_prc
Beispiel #9
0
    def samples(self, data_len, by_posterior=True):
        '''
        y, z, [lamb, prec, cov] = fa.samples(data_len, by_posterior=True)

        Returns
        y: np.array(data_dim, data_len).
        z: np.array(aug_dim, data_len).
        lamb: np.array(aug_dim, data_dim, n_states).
        prec: np.array(data_dim, data_dim, n_states).
        cov: np.array(data_dim, data_dim, n_states).
        * aug_dim = fa_dim + 1
        * n_states = 1
        '''
        z = self.z.samples(data_len, by_posterior)
        # lamb, prec = self.theta.samples(1, by_posterior)
        lamb, prec = self.theta.expectations(1, by_posterior)
        y = zeros((self.data_dim, data_len))
        mu = einsum('ld,lt->dt', lamb[:, :, 0], z)
        cov = inv(prec[:, :, 0])
        for t in range(data_len):
            y[:, t] = mvnrnd(mu[:, t], cov)
        cov = cov[:, :, newaxis]
        return y, z, [lamb, prec, cov]
 def _inv(self, src):
     dst = inv(src.transpose(2, 0, 1)).transpose(1, 2, 0)
     return dst