-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhmmmix_mu_lambda_MLE_nopdf_loop.m
146 lines (124 loc) · 5.94 KB
/
hmmmix_mu_lambda_MLE_nopdf_loop.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
function [mu_KP, lambda_KP] = hmmmix_mu_lambda_MLE_nopdf_loop(hM_KTG, hC_GP, Y_PT, mu_KP, lambda_KP, alpha_K, nu_KP, m_K, gamma_K, eta_K, S_K, forbidGoingBack, verbose, whichLogLikelihoodToUse)
[K,T,G] = size(hM_KTG);
P = size(hC_GP,2);
% As mentioned in my thesis, we are using a lower bound on the original
% lower bound. Nothing guarantees that the updates here will be
% beneficial in terms of maximizing the first (tightest) lower bound,
% so I added the option here of rejecting updates when the values for
% the loglikelihood of the observations is going down.
if nargin < 12
% The default value is 'true', but it's a costly thing to do.
forbidGoingBack = true;
end
if nargin < 13
verbose = false;
end
if nargin < 14
whichLogLikelihoodToUse = 'original'; % 'original' or 'second'
% Determines if we'll use
% sum(sum(log(sum(rho_KTP .* YgivenZ_KTP,1))))
% or
% sum(sum(sum(rho_KTP .* log(YgivenZ_KTP))))
% as loglikelihood value that we want to monitor.
% With 'original' we use the first one.
end
debug = false;
% I had this alpha_KK in the main code for the FL data, but now I'm
% hitting this function 'hmmmix_compute_rho_KTP_nopdf_MatlabC' that I
% won't be rewriting to allow alpha_KK to be square. I also realized
% that I was picking alpha_KK = [20,1,1; 1,10,1; 1,1,20]; anyways, and
% I can reproduce that value with alpha_K = [20,10,20]. So there it is.
% This function 'hmmmix_mu_lambda_MLE_nopdf_loop' now takes alpha_KK
% also because I'm downgrading it.
if all([K,K] == size(alpha_K))
alpha_K = diag(alpha_K);
% Make sure someone hasn't had the bad (incompatible) idea of
% normalizing alpha already. Those alpha matrices are always
% renormalized on the spot by some function.
assert(min(alpha_K(:)) >= 1)
end
assert(length(alpha_K) == K);
rho_KTP = hmmmix_compute_rho_KTP_nopdf_MatlabC(hM_KTG, hC_GP, alpha_K);
% Backup the original quantities so that, if 'forbidGoingBack' is true
% and the loglikelihood went down, we can revert to them.
if forbidGoingBack || debug
original_mu_KP = mu_KP;
original_lambda_KP = lambda_KP;
YgivenZ_KTP = hmmmix_YgivenZ_KTP(Y_PT, nu_KP, mu_KP, lambda_KP);
switch whichLogLikelihoodToUse
case 'original'
original_loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(sum(log(sum(rho_KTP .* YgivenZ_KTP,1))));
case 'second'
original_loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(rho_KTP(:) .* log(YgivenZ_KTP(:)));
end
end
previous_u_KTP = zeros(K,T,P);
paramsDone = false;
safetyCounter = 1;
% not used
if debug
loglikHistory = [original_loglik];
end
while ~paramsDone
u_KTP = hmmmix_compute_u_KTP(rho_KTP, Y_PT, mu_KP, lambda_KP, nu_KP);
[mu_KP, lambda_KP] = hmmmix_mu_lambda_MLE(rho_KTP, Y_PT, u_KTP, m_K, nu_KP, gamma_K, eta_K, S_K);
if (max(abs(previous_u_KTP(:) - u_KTP(:))) < 0.01) || safetyCounter > 50
paramsDone = true;
%fprintf('optimizing lambda and mu took %d iterations\n', safetyCounter);
end
safetyCounter = safetyCounter + 1;
previous_u_KTP = u_KTP;
% Computing the loglikelihood is expensive, so don't do it unless you
% want to track the values.
if debug
YgivenZ_KTP = hmmmix_YgivenZ_KTP(Y_PT, nu_KP, mu_KP, lambda_KP);
switch whichLogLikelihoodToUse
case 'original'
loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(sum(log(sum(rho_KTP .* YgivenZ_KTP,1))));
case 'second'
loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(rho_KTP(:) .* log(YgivenZ_KTP(:)));
end
loglikHistory = [loglikHistory, loglik];
end
% This would be ok if we weren't looking for a fixed point, I
% think, but now I'm not sure it's reasonable to expect that every
% time we set u or mu,lambda we should expect an increase in
% loglik.
%if previous_loglik > loglik
% mu_KP = previous_mu_KP;
% lambda_KP = previous_lambda_KP;
% loglik = previous_loglik;
% paramsDone = true;
%end
end
if debug
loglikHistory
end
% Computing the loglikelihood is expensive, so don't do it unless you
% have to.
if debug || forbidGoingBack
YgivenZ_KTP = hmmmix_YgivenZ_KTP(Y_PT, nu_KP, mu_KP, lambda_KP);
switch whichLogLikelihoodToUse
case 'original'
loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(sum(log(sum(rho_KTP .* YgivenZ_KTP,1))));
case 'second'
loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K, eta_K, S_K, gamma_K) + sum(rho_KTP(:) .* log(YgivenZ_KTP(:)));
end
%loglik = hmmmix_loglik_theta_parameters(mu_KP, lambda_KP, m_K,
%eta_K, S_K, gamma_K) + sum(rho_KTP(:) .* YgivenZ_KTP(:));
end
% if this check fails, we want to revert to the original parameters
if forbidGoingBack
if loglik < original_loglik
mu_KP = original_mu_KP;
lambda_KP = original_lambda_KP;
if verbose
fprintf('F : The loglikelihood of the parameters went from %f to %f so we forget about this round.\n', original_loglik, loglik);
end
else
if verbose
fprintf('S : The loglikelihood of the parameters went from %f to %f so we keep the suggestions.\n', original_loglik, loglik);
end
end
end
end