def _do_forward_pass(self, framelogprob): # Based on hmmlearn's _BaseHMM safe_startmat = self.startprob_ + np.finfo(float).eps safe_transmat = self.transmat_ + np.finfo(float).eps n_samples, n_components = framelogprob.shape fwdlattice = np.zeros((n_samples, n_components)) _hmmc._forward(n_samples, n_components, np.log(safe_startmat), np.log(safe_transmat), framelogprob, fwdlattice) return logsumexp(fwdlattice[-1]), fwdlattice
def _do_score_samples(self, data, lengths=None): # adapted hmmlearn # TODO: Support lengths arguement framelogprob = self._compute_log_likelihood(data) logprob, fwdlattice = self._do_forward_pass(framelogprob) bwdlattice = self._do_backward_pass(framelogprob) gamma = fwdlattice + bwdlattice # gamma is guaranteed to be correctly normalized by logprob at # all frames, unless we do approximate inference using pruning. # So, we will normalize each frame explicitly in case we # pruned too aggressively. posteriors = np.exp(gamma.T - logsumexp(gamma, axis=1)).T posteriors += np.finfo(np.float64).eps posteriors /= np.sum(posteriors, axis=1).reshape((-1, 1)) return logprob, posteriors
def _decode_map(self, data): # adapted hmmlearn framelogprob = self._compute_log_likelihood(data) logprob, fwdlattice = self._do_forward_pass(framelogprob) bwdlattice = self._do_backward_pass(framelogprob) gamma = fwdlattice + bwdlattice # gamma is guaranteed to be correctly normalized by logprob at # all frames, unless we do approximate inference using pruning. # So, we will normalize each frame explicitly in case we # pruned too aggressively. posteriors = np.exp(gamma.T - logsumexp(gamma, axis=1)).T posteriors += np.finfo(np.float64).eps posteriors /= np.sum(posteriors, axis=1).reshape((-1, 1)) state_sequence = np.argmax(posteriors, axis=1) map_logprob = np.max(posteriors, axis=1).sum() return map_logprob, state_sequence
def _accumulate_sufficient_statistics(self, stats, X, framelogprob, posteriors, fwdlattice, bwdlattice): """Updates sufficient statistics from a given sample. Parameters ---------- stats : dict Sufficient statistics as returned by :meth:`~base._BaseHMM._initialize_sufficient_statistics`. X : array, shape (n_samples, n_features) Sample sequence. framelogprob : array, shape (n_samples, n_components) Log-probabilities of each sample under each of the model states. posteriors : array, shape (n_samples, n_components) Posterior probabilities of each sample being generated by each of the model states. fwdlattice, bwdlattice : array, shape (n_samples, n_components) Log-forward and log-backward probabilities. """ # Based on hmmlearn's _BaseHMM safe_transmat = self.transmat_ + np.finfo(float).eps stats['nobs'] += 1 if 's' in self.params: stats['start'] += posteriors[0] if 't' in self.params: n_samples, n_components = framelogprob.shape # when the sample is of length 1, it contains no transitions # so there is no reason to update our trans. matrix estimate if n_samples <= 1: return lneta = np.zeros((n_samples - 1, n_components, n_components)) _hmmc._compute_lneta(n_samples, n_components, fwdlattice, np.log(safe_transmat), bwdlattice, framelogprob, lneta) stats['trans'] += np.exp(logsumexp(lneta, axis=0)) # stats['trans'] = np.round(stats['trans']) # if np.sum(stats['trans']) != X.shape[0]-1: # warnings.warn("transmat counts != n_samples", RuntimeWarning) # import pdb; pdb.set_trace() stats['trans'][np.where(stats['trans'] < 0.01)] = 0.0