def find_r(r_initial, dane, pstwa, p, threshold=1e-3): r = r_initial.copy() r_not_found = True counter = 0 delta = np.zeros(shape=r.shape) stop = np.zeros(r.shape, dtype=bool) while r_not_found: derivative = calculate_derivative(pstwa, dane, copy.deepcopy(r), p) #print(derivative) if np.any(np.isnan(derivative)): print("Derivative is nan, stop this madness") print("That's the r, p and derivative:") print(r) print(p) print(derivative) break if np.all((abs(derivative) < threshold) + stop): r_not_found = False break stop[abs(derivative) < threshold] = True r, delta, stop = update_r(copy.deepcopy(r), derivative, delta, stop) counter += 1 #if counter % 10 == 0: # print("%i iterations" % counter) # print(derivative) # print(r) if counter == 2000: # jesli idzie tak dlugo to pewnie i tak cos jest nie tak. # to niech juz beda te estymacje ktore sa. break #print("r estimated:") #print(r) #print("***") return r
def _initialize_sufficient_statistics(self): """Initializes sufficient statistics required for M-step. The method is *pure*, meaning that it doesn't change the state of the instance. For extensibility computed statistics are stored in a dictionary. Returns ------- nobs : int Number of samples in the data. start : array, shape (n_components, ) An array where the i-th element corresponds to the posterior probability of the first sample being generated by the i-th state. trans : array, shape (n_components, n_components) An array where the (i, j)-th element corresponds to the posterior probability of transitioning between the i-th to j-th states. """ stats = { 'nobs': 0, 'start': np.zeros(self.n_components), 'trans': np.zeros((self.n_components, self.n_components)) } return stats
def _do_forward_pass(self, framelogprob): n_samples, n_components = framelogprob.shape fwdlattice = np.zeros((n_samples, n_components)) _hmmc._forward(n_samples, n_components, log_mask_zero(self.startprob_), log_mask_zero(self.transmat_), framelogprob, fwdlattice) with np.errstate(under="ignore"): return logsumexp(fwdlattice[-1]), fwdlattice
def _do_backward_pass(self, framelogprob): n_samples, n_components = framelogprob.shape bwdlattice = np.zeros((n_samples, n_components)) _hmmc._backward(n_samples, n_components, log_mask_zero(self.startprob_), log_mask_zero(self.transmat_), framelogprob, bwdlattice) return bwdlattice
def calculate_derivative(posteriors, data, r, p): def _digamma(array): return digamma(array.astype("float64")).astype("float128") n_comp, n_var = r.shape n_obs, _ = data.shape derivative = np.zeros(r.shape) for state in range(n_comp): r_j, p_j = r[state], p[state] posteriors_j = posteriors[:, state][:, np.newaxis] in_brackets = _digamma(data + r_j) - _digamma(r_j) + np.log(p_j) derivative[state] = np.sum(posteriors_j * in_brackets, axis=0) #print("derivative:") #print(derivative) return derivative # it's the same, just different implementation n_comp, n_var = r.shape n_obs, _ = data.shape desired_shape = (n_comp, n_obs, n_var) data_repeated = np.concatenate([data] * n_comp).reshape(desired_shape) r_repeated = np.repeat([r], n_obs, axis=1).reshape(desired_shape) digamma_of_sum = _digamma(data_repeated + r_repeated) digamma_of_r = _digamma(r_repeated) log_p = np.log(p) log_p_repeated = np.repeat([log_p], n_obs, axis=1).reshape(desired_shape) sum_ = digamma_of_sum - digamma_of_r + log_p_repeated posteriors_repeated = np.repeat(posteriors.T, n_var).reshape(desired_shape) product = posteriors_repeated * sum_ derivative = np.sum(product, axis=1) return derivative # another implementation r_conc = np.concatenate([r] * n_obs, axis=0) r_conc = r_conc.reshape(n_obs, n_comp, n_var) X_repeat = np.repeat(data, n_comp, axis=0) X_repeat = X_repeat.reshape(n_obs, n_comp, n_var) suma = X_repeat + r_conc suma = suma.reshape(n_obs, n_comp, n_var) pstwa_repeat = np.repeat(posteriors, n_var) pstwa_repeat = pstwa_repeat.reshape(n_obs, n_comp, n_var) a = np.sum(pstwa_repeat * _digamma(suma), axis=0) a = a.reshape(n_comp, n_var) b = np.sum(pstwa_repeat * _digamma(r_conc), axis=0) b = b.reshape(n_comp, n_var) p_conc = np.concatenate([p] * n_obs, axis=0) p_conc = p_conc.reshape(n_obs, n_comp, n_var) c = np.sum(pstwa_repeat * np.log(p_conc), axis=0) c = c.reshape(n_comp, n_var) derivative = a - b + c return derivative
def score_samples(self, X, lengths=None): """Compute the log probability under the model and compute posteriors. Parameters ---------- X : array-like, shape (n_samples, n_features) Feature matrix of individual samples. lengths : array-like of integers, shape (n_sequences, ), optional Lengths of the individual sequences in ``X``. The sum of these should be ``n_samples``. Returns ------- logprob : float Log likelihood of ``X``. posteriors : array, shape (n_samples, n_components) State-membership probabilities for each sample in ``X``. See Also -------- score : Compute the log probability under the model. decode : Find most likely state sequence corresponding to ``X``. """ check_is_fitted(self, "startprob_") self._check() X = check_array(X) n_samples = X.shape[0] logprob = 0 posteriors = np.zeros((n_samples, self.n_components)) for i, j in iter_from_X_lengths(X, lengths): framelogprob = self._compute_log_likelihood(X[i:j]) logprobij, fwdlattice = self._do_forward_pass(framelogprob) logprob += logprobij bwdlattice = self._do_backward_pass(framelogprob) posteriors[i:j] = self._compute_posteriors(fwdlattice, bwdlattice) return logprob, posteriors