def loglikelihood(data, model): lpr = log_multivariate_normal_density_diag(data['lmfcc'], model['means'], model['covars']) log_st_prob = np.log(model['startprob']) log_transmat = np.log(model['transmat']) alpha_matrix = forward(lpr, log_st_prob, log_transmat) return lpr, logsumexp(alpha_matrix[-1])
def forward_algorithm(): wordHMMs = {} isolated = get_isolated(prondict) plot_p_color_mesh(example['logalpha'], 'example alpha matrix') # verify implementation wordHMMs['o'] = concatHMMs(phoneHMMsAll, isolated['o']) log_st_prob = np.log(wordHMMs['o']['startprob']) log_transmat = np.log(wordHMMs['o']['transmat']) alpha_matrix = forward(example['obsloglik'], log_st_prob, log_transmat) plot_p_color_mesh(alpha_matrix, "hmms all output example alpha matrix") # 44 data labels keys_list = [x for x in isolated.keys()] scores_models_all = np.zeros((len(data), len(isolated))) scores_models_onespkr = np.zeros_like(scores_models_all) for j in range(len(keys_list)): key = keys_list[j] hmms = concatHMMs(phoneHMMsAll, isolated[key]) log_st_prob = np.log(hmms['startprob']) log_transmat = np.log(hmms['transmat']) for i in range(len(data)): lpr_test = log_multivariate_normal_density_diag( data[i]['lmfcc'], hmms['means'], hmms['covars']) alpha = forward(lpr_test, log_st_prob, log_transmat) scores_models_all[i, j] = logsumexp(alpha[len(alpha) - 1]) hmms = concatHMMs(phoneHMMsOne, isolated[key]) log_st_prob = np.log(hmms['startprob']) log_transmat = np.log(hmms['transmat']) for i in range(len(data)): lpr_test = log_multivariate_normal_density_diag( data[i]['lmfcc'], hmms['means'], hmms['covars']) alpha = forward(lpr_test, log_st_prob, log_transmat) scores_models_onespkr[i, j] = logsumexp(alpha[len(alpha) - 1]) predict_all = np.argmax(scores_models_all, axis=1) predict_one = np.argmax(scores_models_onespkr, axis=1) label_all = [keys_list[x] for x in predict_all] label_one = [keys_list[x] for x in predict_one] true_label = [data[x]['digit'] for x in range(len(data))] print(true_label) print(label_all) print(label_one)
def get_loglik(feature, hmm): trans_mat = hmm['transmat'][:-1, :-1] pi_vec = hmm['startprob'][:-1] means = hmm['means'] covars = hmm['covars'] obsloglik = log_multivariate_normal_density_diag(feature, means, covars) log_alpha = forward(obsloglik, np.log(pi_vec), np.log(trans_mat)) ret = logsumexp(log_alpha[-1]) return ret
def statePosteriors(log_alpha, log_beta): """State posterior (gamma) probabilities in log domain. Args: log_alpha: NxM array of log forward (alpha) probabilities log_beta: NxM array of log backward (beta) probabilities where N is the number of frames, and M the number of states Output: log_gamma: NxM array of gamma probabilities for each of the M states in the model """ log_gamma = log_alpha + log_beta - lab2_tools.logsumexp(log_alpha[-1,:]) return log_gamma
def backward(log_emlik, log_startprob, log_transmat): """Backward (beta) probabilities in log domain. Args: log_emlik: NxM array of emission log likelihoods, N frames, M states log_startprob: log probability to start in state i log_transmat: transition log probability from state i to j Output: backward_prob: NxM array of backward log probabilities for each of the M states in the model """ log_beta = np.zeros(log_emlik.shape) # since beta_N = 1 => log_beta_N = 0 for n in reversed(range(log_emlik.shape[0] - 1)): # time dimension for i in range(log_emlik.shape[1]): # loop over states log_beta[n, i] = logsumexp(log_transmat[i,:] + log_emlik[n + 1, :] + log_beta[n + 1,:]) return log_beta
def forward(log_emlik, log_startprob, log_transmat): """Forward (alpha) probabilities in log domain. Args: log_emlik: NxM array of emission log likelihoods, N frames, M states log_startprob: log probability to start in state i log_transmat: log transition probability from state i to j Output: forward_prob: NxM array of forward log probabilities for each of the M states in the model """ # follow the appendix in the question pdf log_alpha = np.zeros(log_emlik.shape) log_alpha[0][:] = log_startprob.T + log_emlik[0] for n in range(1,len(log_alpha)): # time dimension for i in range(log_alpha.shape[1]): # loop over states log_alpha[n, i] = logsumexp(log_alpha[n - 1] + log_transmat[:,i]) + log_emlik[n,i] return log_alpha
def retrain(feature, model, num_iters=20, threshold=1): # extract params means = model['means'] covars = model['covars'] transmat = model['transmat'][:-1, :-1] startprob = model['startprob'][:-1] log_pi = np.log(startprob) log_trans = np.log(transmat) # calculate the emission obsloglik = log_multivariate_normal_density_diag(feature, means, covars) # EM algorithm loglik_old = -np.inf for iter_ in range(num_iters): # E-step log_alpha = forward(obsloglik, log_pi, log_trans) log_beta = backward(obsloglik, log_pi, log_trans) log_gamma = statePosteriors(log_alpha, log_beta) # M-step means, covars = updateMeanAndVar(feature, log_gamma) # update obsloglik = log_multivariate_normal_density_diag( feature, means, covars) loglik = logsumexp(log_alpha[-1]) print("Iter {}: The log likelihood in EM:".format(iter_), loglik) # check if terminate EM if (loglik - loglik_old) < threshold or np.isnan(loglik): print("Terminating the EM") break else: loglik_old = loglik
def backward(log_emlik, log_startprob, log_transmat): """Backward (beta) probabilities in log domain. Args: log_emlik: NxM array of emission log likelihoods, N frames, M states log_startprob: log probability to start in state i log_transmat: transition log probability from state i to j Output: backward_prob: NxM array of backward log probabilities for each of the M states in the model """ N, M = log_emlik.shape # Create zeroed beta return matrix. log_beta = np.zeros((N, M)) #For all other n, populate beta with regular formula result. #Start at N-2 &, in increments of -1, finish at 0. for n in range(N - 2, -1, -1): for j in range(M): log_beta[n][j] = lab2_tools.logsumexp(log_beta[n + 1, :] + log_emlik[n + 1, :] + log_transmat[j, :-1]) return log_beta
def forward(log_emlik, log_startprob, log_transmat): """Forward (alpha) probabilities in log domain. Args: log_emlik: NxM array of emission log likelihoods, N frames, M states log_startprob: log probability to start in state i log_transmat: log transition probability from state i to j Output: forward_prob: NxM array of forward log probabilities for each of the M states in the model """ N, M = log_emlik.shape # Create alpha return matrix, populate with n=0 formula result. forward_prob = np.zeros((N, M)) forward_prob[0, :] = log_startprob[:-1] + log_emlik[0, :] for n in range(1, N): for j in range(M): forward_prob[n, j] = lab2_tools.logsumexp(forward_prob[n-1, :] + log_transmat[:-1, j]) + log_emlik[n, j] return forward_prob
for d in isolated.keys(): wordHMMs[d] = concatHMMs(phoneHMMs, isolated[d]) # get the observation sequence feature = data[10]['lmfcc'] # First part # calculate the emissions digit = '4' means = wordHMMs[digit]['means'] covars = wordHMMs[digit]['covars'] obsloglik = log_multivariate_normal_density_diag(feature, means, covars) # calculate the log likelihood trans_mat = wordHMMs[digit]['transmat'][:-1, :-1] pi_vec = wordHMMs[digit]['startprob'][:-1] # log space log_pi = np.log(pi_vec) log_trans = np.log(trans_mat) log_alpha = forward(obsloglik, log_pi, log_trans) log_seq_likelihood = logsumexp(log_alpha[-1]) print("The log likelihood of the digit {}:".format(digit), log_seq_likelihood) # ========================================================================= for d in wordHMMs.keys(): print("========================================================") print("Retrain HMM of digit '{}' with data[10]['lmfcc']".format(d)) retrain(feature, wordHMMs[d]) print("========================================================")
axs[0].set_title("Computed \"o\" forward probability, from one speaker") axs[0].pcolormesh(forward_probability.T) axs[1].set_title("Computed \"o\" forward probability, from multiple speakers") axs[1].pcolormesh(forward_probability_all.T) plt.show() scores = np.zeros((44, 11)) for i in range(len(data)): data_sample = data[i]['lmfcc'] j = 0 for key, HMM in wordHMMs.items(): log_lik = lab2_tools.log_multivariate_normal_density_diag(data_sample, HMM["means"], HMM["covars"]) forward_probability2 = forward(log_lik, np.log(HMM["startprob"]), np.log(HMM["transmat"])) scores[i, j] = lab2_tools.logsumexp(forward_probability2[-1]) j += 1 scores_all = np.zeros((44, 11)) for i in range(len(data)): data_sample = data[i]['lmfcc'] j = 0 for key, HMM in wordHMMs_all.items(): log_lik = lab2_tools.log_multivariate_normal_density_diag(data_sample, HMM["means"], HMM["covars"]) forward_probability2 = forward(log_lik, np.log(HMM["startprob"]), np.log(HMM["transmat"])) scores_all[i, j] = lab2_tools.logsumexp(forward_probability2[-1]) j += 1 # plotting forward functions, comparing all speakers to one: fig, axs = plt.subplots(2)
example = np.load('data/lab2_example.npz')['example'].item() phoneHMMs = np.load('data/lab2_models_onespkr.npz')['phoneHMMs'].item() # Build hmm wordHMMs = {} wordHMMs['o'] = concatHMMs(phoneHMMs, isolated['o']) trans_mat = wordHMMs['o']['transmat'][:-1, :-1] pi_vec = wordHMMs['o']['startprob'][:-1] log_startprob = np.log(pi_vec) log_transmat = np.log(trans_mat) log_emlik = example['obsloglik'] # ===================================================== log_beta = backward(log_emlik, log_startprob, log_transmat) log_alpha = forward(log_emlik, log_startprob, log_transmat) # caculate the log gamma log_gamma = statePosteriors(log_alpha, log_beta) # print(np.allclose(example['loggamma'], log_gamma)) # check if sum to one in linear / sum to zero in log domain ntime_steps = log_gamma.shape[0] zeros = np.zeros((ntime_steps)) # print(np.allclose(logsumexp(log_gamma, axis=1), zeros)) # ==================================================================== # See notes, just do the normalization to get the state posterior of GMM logZ = logsumexp(log_emlik, axis=1) # the normalization factor in log space log_gamma_gmm = log_emlik - logZ[:, np.newaxis]
from lab2_proto import backward from lab2_tools import logsumexp if __name__ == "__main__": # load data data = np.load('data/lab2_data.npz')['data'] example = np.load('data/lab2_example.npz')['example'].item() phoneHMMs = np.load('data/lab2_models_onespkr.npz')['phoneHMMs'].item() # Build hmm wordHMMs = {} wordHMMs['o'] = concatHMMs(phoneHMMs, isolated['o']) trans_mat = wordHMMs['o']['transmat'][:-1, :-1] pi_vec = wordHMMs['o']['startprob'][:-1] log_startprob = np.log(pi_vec) log_transmat = np.log(trans_mat) log_emlik = example['obsloglik'] # ===================================================== log_beta = backward(log_emlik, log_startprob, log_transmat) # check the result of log_beta print("Is beta close?:", np.allclose(log_beta, example['logbeta'])) # calculate the log prob # seq_likelihood = sum_{i}(\alpha_0(i) * \beta_0(i)) log_alpha_0 = log_startprob.T + log_emlik[0] log_beta_0 = log_beta[0, :] log_seq_like = logsumexp(log_alpha_0 + log_beta_0) print(log_seq_like) print(example['loglik'])