def estimate(self, Y=None, use_sample=False): ''' return estim_y: (data_dim, data_len), waveform sequence estim_s: (data_len), state sequence which contains 0 to n_states - 1 vb: float value, valiational bound ''' estim_s = self.qs.estimate(Y, self.theta) estim_y = zeros((self.data_dim, len(estim_s))) if use_sample: for k in range(self.n_states): idx = estim_s == k data_len = estim_y[:, idx].shape[-1] mu, R = self.theta.qmur.post.sample() estim_y[:, idx] = mvnrand( mu[:, k], inv(R[:, :, k]), size=data_len).T else: for k in range(self.n_states): idx = estim_s == k data_len = estim_y[:, idx].shape[-1] m = self.theta.qmur.post.mu[:, k] c = inv(self.theta.qmur.post.expt_prec[:, :, k]) estim_y[:, idx] = mvnrand(m, c, size=data_len).T vb = self.calc_vb() return estim_y, estim_s, vb
def samples(self, data_len, by_posterior=True): ''' Y, S, mu, R, pi, A = hmm.sample(data_len) @argvs data_len: data length use_uniform_s: use uniform S if True, use sampled S if False @return Y: sampled observations, np.array(data_dim, data_len) S: sampled states, np.array(n_states, data_len) Z: sampled categories, np.array(n_cat, data_len) prms: [mu, R, pi, A, psi] mu: sampled mu: np.array(data_dim, n_states) R: sampled R: np.array(data_dim, data_dim, n_states) pi: sampled pi: np.array(n_states) A: sampled A: np.array(n_states, n_states) ''' # mu, R, pi, A = self.theta.samples(1, by_posterior) mu, R, pi, A = self.theta.expectations(by_posterior) S = self.qs.samples(data_len, pi, A) Y = zeros((self.data_dim, data_len)) for t in range(data_len): k = S[t] cov = inv(R[:, :, k]) Y[:, t] = mvnrand(mu[:, k], cov) return Y, S, [mu, R, pi, A]
def update(self, Y, theta): ''' @argvs Y: array(data_dim, data_len) 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) ''' # -- prc rll = einsum('ddk,ljdk->ljk', theta.r.post.expt, theta.lamb.post.expt2) z_prc = self.prior.prec + rll # --- cov self.z_cov = inv(z_prc.transpose(2, 0, 1)).transpose(1, 2, 0) # --- mu ylr = einsum('dt,ldk,ddk->lkt', Y, theta.lamb.post.mu, theta.r.post.expt) ylr_zmu = ylr + self.prior.expt_prec_mu[:, :, newaxis] self.z_mu = einsum('ljk,jkt->lkt', self.z_cov, ylr_zmu) # --- update s z_mpm = einsum('lkt,lkt->kt', self.z_mu, ylr_zmu) z_cov_lndet = logdet(self.z_cov.transpose(2, 0, 1)) self.s.update(Y, theta, self.prior, z_mpm, z_cov_lndet) # --- expectations self.set_expt(self.s.expt, self.z_mu, self.z_cov)
def samples(self, data_len, **args): ''' gmm.samples(data_len, use_uniform_s=False) get sampled data from the model @argv data_len: sample data length, int return_uniform_s: return uniform S or sampled S, boo, default, False by_posterior: sample from post or prior, bool, default True @return Y: sampled observation, np.array(data_dim, data_len) S: sampled hidden variables, np.array(data_len) mu: sampled mu, np.array(data_dim, n_states) R: sampled R, np.array(data_dim, data_dim, n_states) pi: sampled pi, np.array(n_states) ''' by_posterior = args.get('by_posterior', True) # mu, R, pi = self.theta.samples(by_posterior) mu, R, pi = self.theta.expectations(by_posterior) S = self.qs.samples(data_len, pi) Y = zeros((self.data_dim, data_len)) cov = inv(R.transpose(2, 0, 1)).transpose(1, 2, 0) for t in range(data_len): k = S[t] Y[:, t] = mvnrand(mu[:, k], cov[:, :, k]) return Y, S, [mu, R, pi]
def samples(self, data_len, by_posterior=True): lamb, r, pi = self.theta.samples(by_posterior=by_posterior) z, s = self.zs.samples(data_len, pi, by_posterior) y = ones((self.data_dim, data_len)) * nan inv_r = inv(r.transpose(2, 0, 1)).transpose(1, 2, 0) for t in range(data_len): k = s[t] mu = einsum('ld,l->d', lamb[:, :, k], z[:, k, t]) cov = inv_r[:, :, k] y[:, t] = mvnrnd(mu, cov) return y, z, s, [lamb, r, inv_r, pi]
def update(self, r, sum_szz, sum_ysz): ''' r.post.diag_expt: (data_dim, n_states) szz: array(aug_dim, aug_dim, n_states, data_len) YSS sum_ysz: array(data_dim, aug_dim, n_states) sum(Y<ZS>) ''' # --- precision r_szz = einsum('ddk,ijk->ijdk', r.post.expt, sum_szz) prc = self.prior.prec + r_szz # --- covariance cov = inv(prc.transpose((2, 3, 0, 1))).transpose((2, 3, 0, 1)) # --- mu rysz = einsum('ddk,dlk->ldk', r.post.expt, sum_ysz) pm_rysz = self.prior.expt_prec_mu + rysz mu = einsum('ijdk,jdk->idk', cov, pm_rysz) self.post.set_params(mu=mu, cov=cov, prc=prc)
def _plotter_core(y, s, prms, vbs, prm_type_str, sup_title, figno): from ml_utils.plot_models import PlotModels mu, r, pi = prms n_cols = 3 pm = PlotModels(3, n_cols, figno) # --- mu pm.plot_2d_array((0, 0), mu, title=r'$\mu$ %s' % prm_type_str) # --- Pi pm.multi_bar((0, 1), atleast_2d(pi), title=r'$\pi$ %s' % prm_type_str) # --- A # --- No A # --- Obs (data_dim v amplitude) pm.plot_2d_array((1, 0), y, title='Y') # --- mu and obs (Scatter) cov = inv(r.transpose(2, 0, 1)).transpose(1, 2, 0) pm.plot_2d_mu_cov((1, 1), mu, cov, src=y, cat=s) # --- Variational bound pm.plot_vb((1, 2), vbs, cspan=1) # --- Y (sequence) pm.plot_seq((2, 0), y, cat=s, title='Y', cspan=n_cols) # --- pm.sup_title(sup_title) pm.tight_layout()