00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00038 #include "fastlib/fastlib.h"
00039 #include "support.h"
00040 #include "gaussianHMM.h"
00041
00042 using namespace hmm_support;
00043
00044 void GaussianHMM::setModel(const Matrix& transmission, const ArrayList<Vector>& list_mean_vec,const ArrayList<Matrix>& list_covariance_mat) {
00045 DEBUG_ASSERT(transmission.n_rows() == transmission.n_cols());
00046 DEBUG_ASSERT(transmission.n_rows() == list_mean_vec.size());
00047 DEBUG_ASSERT(transmission.n_rows() == list_covariance_mat.size());
00048 for (int i = 1; i < list_mean_vec.size(); i++) {
00049 DEBUG_ASSERT(list_mean_vec[0].length() == list_covariance_mat[i].n_rows());
00050 DEBUG_ASSERT(list_mean_vec[0].length() == list_covariance_mat[i].n_cols());
00051 DEBUG_ASSERT(list_mean_vec[0].length() == list_mean_vec[i].length());
00052 }
00053 transmission_.Destruct();
00054 list_mean_vec_.Renew();
00055 list_covariance_mat_.Renew();
00056 transmission_.Copy(transmission);
00057 list_mean_vec_.InitCopy(list_mean_vec);
00058 list_covariance_mat_.InitCopy(list_covariance_mat);
00059 CalculateInverse();
00060 }
00061
00062 void GaussianHMM::Init(const Matrix& transmission, const ArrayList<Vector>& list_mean_vec,const ArrayList<Matrix>& list_covariance_mat) {
00063 transmission_.Copy(transmission);
00064 list_mean_vec_.InitCopy(list_mean_vec);
00065 list_covariance_mat_.InitCopy(list_covariance_mat);
00066 DEBUG_ASSERT(transmission.n_rows() == transmission.n_cols());
00067 DEBUG_ASSERT(transmission.n_rows() == list_mean_vec.size());
00068 DEBUG_ASSERT(transmission.n_rows() == list_covariance_mat.size());
00069 for (int i = 1; i < list_mean_vec.size(); i++) {
00070 DEBUG_ASSERT(list_mean_vec[0].length() == list_covariance_mat[i].n_rows());
00071 DEBUG_ASSERT(list_mean_vec[0].length() == list_covariance_mat[i].n_cols());
00072 DEBUG_ASSERT(list_mean_vec[0].length() == list_mean_vec[i].length());
00073 }
00074 CalculateInverse();
00075 }
00076
00077 void GaussianHMM::InitFromFile(const char* profile) {
00078 if (!PASSED(GaussianHMM::LoadProfile(profile, &transmission_, &list_mean_vec_, &list_covariance_mat_)))
00079 FATAL("Couldn't open '%s' for reading.", profile);
00080 list_inverse_cov_mat_.InitCopy(list_covariance_mat_);
00081 gauss_const_vec_.Init(list_covariance_mat_.size());
00082 CalculateInverse();
00083 }
00084
00085 void GaussianHMM::InitFromData(const ArrayList<Matrix>& list_data_seq, int numstate) {
00086 GaussianHMM::InitGaussParameter(numstate, list_data_seq, &transmission_, &list_mean_vec_, &list_covariance_mat_);
00087 list_inverse_cov_mat_.InitCopy(list_covariance_mat_);
00088 gauss_const_vec_.Init(list_covariance_mat_.size());
00089 CalculateInverse();
00090 }
00091
00092 void GaussianHMM::InitFromData(const Matrix& data_seq, const Vector& state_seq) {
00093 GaussianHMM::EstimateInit(data_seq, state_seq, &transmission_,
00094 &list_mean_vec_, &list_covariance_mat_);
00095 CalculateInverse();
00096 }
00097
00098 void GaussianHMM::LoadProfile(const char* profile) {
00099 transmission_.Destruct();
00100 list_mean_vec_.Renew();
00101 list_covariance_mat_.Renew();
00102 list_inverse_cov_mat_.Renew();
00103 gauss_const_vec_.Destruct();
00104 InitFromFile(profile);
00105 }
00106
00107 void GaussianHMM::SaveProfile(const char* profile) const {
00108 GaussianHMM::SaveProfile(profile, transmission_, list_mean_vec_, list_covariance_mat_);
00109 }
00110
00111 void GaussianHMM::CalculateInverse() {
00112 int M = transmission_.n_rows();
00113 int N = list_mean_vec_[0].length();
00114 for (int i = 0; i < M; i++) {
00115 la::InverseOverwrite(list_covariance_mat_[i], &list_inverse_cov_mat_[i]);
00116 gauss_const_vec_[i] = pow(2.0*math::PI, -N/2.0) * pow(la::Determinant(list_covariance_mat_[i]), -0.5);
00117 }
00118 }
00119
00120 void GaussianHMM::GenerateSequence(int L, Matrix* data_seq, Vector* state_seq) const {
00121 GaussianHMM::GenerateInit(L, transmission_, list_mean_vec_, list_covariance_mat_, data_seq, state_seq);
00122 }
00123
00124 void GaussianHMM::EstimateModel(const Matrix& data_seq, const Vector& state_seq) {
00125 transmission_.Destruct();
00126 list_mean_vec_.Renew();
00127 list_covariance_mat_.Renew();
00128 GaussianHMM::EstimateInit(data_seq, state_seq, &transmission_,
00129 &list_mean_vec_, &list_covariance_mat_);
00130 CalculateInverse();
00131 }
00132
00133 void GaussianHMM::EstimateModel(int numstate, const Matrix& data_seq, const Vector& state_seq) {
00134 transmission_.Destruct();
00135 list_mean_vec_.Renew();
00136 list_covariance_mat_.Renew();
00137 GaussianHMM::EstimateInit(numstate, data_seq, state_seq, &transmission_,
00138 &list_mean_vec_, &list_covariance_mat_);
00139 CalculateInverse();
00140 }
00141
00142 void GaussianHMM::DecodeOverwrite(const Matrix& data_seq, Matrix* state_prob_mat,
00143 Matrix* forward_prob_mat, Matrix* backward_prob_mat, Vector* scale_vec) const {
00144 int M = transmission_.n_rows();
00145 int L = data_seq.n_cols();
00146 Matrix emission_prob_mat(M, L);
00147 GaussianHMM::CalculateEmissionProb(data_seq, list_mean_vec_, list_inverse_cov_mat_,
00148 gauss_const_vec_, &emission_prob_mat);
00149 GaussianHMM::Decode(transmission_, emission_prob_mat, state_prob_mat, forward_prob_mat,
00150 backward_prob_mat, scale_vec);
00151 }
00152
00153 void GaussianHMM::DecodeInit(const Matrix& data_seq, Matrix* state_prob_mat,
00154 Matrix* forward_prob_mat, Matrix* backward_prob_mat, Vector* scale_vec) const {
00155 int M = transmission_.n_rows();
00156 int L = data_seq.n_cols();
00157 state_prob_mat->Init(M, L);
00158 forward_prob_mat->Init(M, L);
00159 backward_prob_mat->Init(M, L);
00160 scale_vec->Init(L);
00161 Matrix emission_prob_mat(M, L);
00162 GaussianHMM::CalculateEmissionProb(data_seq, list_mean_vec_, list_inverse_cov_mat_,
00163 gauss_const_vec_, &emission_prob_mat);
00164 GaussianHMM::Decode(transmission_, emission_prob_mat, state_prob_mat, forward_prob_mat,
00165 backward_prob_mat, scale_vec);
00166 }
00167
00168 double GaussianHMM::ComputeLogLikelihood(const Matrix& data_seq) const {
00169 int L = data_seq.n_cols();
00170 int M = transmission_.n_rows();
00171 Matrix fs(M, L), emis_prob(M, L);
00172 Vector sc;
00173 sc.Init(L);
00174 GaussianHMM::CalculateEmissionProb(data_seq, list_mean_vec_, list_inverse_cov_mat_, gauss_const_vec_, &emis_prob);
00175 GaussianHMM::ForwardProcedure(L, transmission_, emis_prob, &sc, &fs);
00176 double loglik = 0;
00177 for (int t = 0; t < L; t++)
00178 loglik += log(sc[t]);
00179 return loglik;
00180 }
00181
00182 void GaussianHMM::ComputeLogLikelihood(const ArrayList<Matrix>& list_data_seq, ArrayList<double>* list_likelihood) const {
00183 int L = 0;
00184 for (int i = 0; i < list_data_seq.size(); i++)
00185 if (list_data_seq[i].n_cols() > L) L = list_data_seq[i].n_cols();
00186 int M = transmission_.n_rows();
00187 Matrix fs(M, L), emis_prob(M, L);
00188 Vector sc;
00189 sc.Init(L);
00190 list_likelihood->Init();
00191 for (int i = 0; i < list_data_seq.size(); i++) {
00192 int L = list_data_seq[i].n_cols();
00193 GaussianHMM::CalculateEmissionProb(list_data_seq[i], list_mean_vec_, list_inverse_cov_mat_, gauss_const_vec_, &emis_prob);
00194 GaussianHMM::ForwardProcedure(L, transmission_, emis_prob, &sc, &fs);
00195 double loglik = 0;
00196 for (int t = 0; t < L; t++)
00197 loglik += log(sc[t]);
00198 list_likelihood->PushBackCopy(loglik);
00199 }
00200 }
00201
00202 void GaussianHMM::ComputeViterbiStateSequence(const Matrix& data_seq, Vector* state_seq) const {
00203 int M = transmission_.n_rows();
00204 int L = data_seq.n_cols();
00205 Matrix emis_prob(M, L);
00206 GaussianHMM::CalculateEmissionProb(data_seq, list_mean_vec_, list_inverse_cov_mat_, gauss_const_vec_, &emis_prob);
00207 GaussianHMM::ViterbiInit(transmission_, emis_prob, state_seq);
00208 }
00209
00210 void GaussianHMM::TrainBaumWelch(const ArrayList<Matrix>& list_data_seq, int max_iteration, double tolerance) {
00211 GaussianHMM::Train(list_data_seq, &transmission_, &list_mean_vec_, &list_covariance_mat_, max_iteration, tolerance);
00212 CalculateInverse();
00213 }
00214
00215 void GaussianHMM::TrainViterbi(const ArrayList<Matrix>& list_data_seq, int max_iteration, double tolerance) {
00216 GaussianHMM::TrainViterbi(list_data_seq, &transmission_, &list_mean_vec_, &list_covariance_mat_, max_iteration, tolerance);
00217 CalculateInverse();
00218 }
00219
00220 success_t GaussianHMM::LoadProfile(const char* profile, Matrix* trans, ArrayList<Vector>* means, ArrayList<Matrix>* covs) {
00221 ArrayList<Matrix> matlst;
00222 if (!PASSED(load_matrix_list(profile, &matlst)))
00223 return SUCCESS_FAIL;
00224
00225 DEBUG_ASSERT(matlst.size() > 0);
00226 trans->Copy(matlst[0]);
00227 means->Init();
00228 covs->Init();
00229 int M = trans->n_rows();
00230 DEBUG_ASSERT(matlst.size() == 2*M+1);
00231 int N = matlst[1].n_rows();
00232 for (int i = 1; i < 2*M+1; i+=2) {
00233 DEBUG_ASSERT(matlst[i].n_rows()==N && matlst[i].n_cols()==1);
00234 DEBUG_ASSERT(matlst[i+1].n_rows()==N && matlst[i+1].n_cols()==N);
00235 Vector m;
00236 matlst[i].MakeColumnVector(0, &m);
00237 means->PushBackCopy(m);
00238 covs->PushBackCopy(matlst[i+1]);
00239 }
00240 return SUCCESS_PASS;
00241 }
00242
00243 success_t GaussianHMM::SaveProfile(const char* profile, const Matrix& trans, const ArrayList<Vector>& means, const ArrayList<Matrix>& covs) {
00244 TextWriter w_pro;
00245 if (!PASSED(w_pro.Open(profile))) {
00246 NONFATAL("Couldn't open '%s' for writing.", profile);
00247 return SUCCESS_FAIL;
00248 }
00249 int M = trans.n_rows();
00250 DEBUG_ASSERT(means.size() == M && covs.size() == M);
00251 int N = means[0].length();
00252 print_matrix(w_pro, trans, "% transmission", "%f,");
00253 for (int i = 0; i < M; i++) {
00254 DEBUG_ASSERT(means[i].length() == N);
00255 DEBUG_ASSERT(covs[i].n_rows()==N && covs[i].n_cols()==N);
00256 char s[100];
00257 sprintf(s, "%% mean - state %d", i);
00258 print_vector(w_pro, means[i], s, "%f,");
00259 sprintf(s, "%% covariance - state%d", i);
00260 print_matrix(w_pro, covs[i], s, "%f,");
00261 }
00262 return SUCCESS_PASS;
00263 }
00264
00265 void GaussianHMM::GenerateInit(int L, const Matrix& trans, const ArrayList<Vector>& means, const ArrayList<Matrix>& covs, Matrix* seq, Vector* states){
00266 DEBUG_ASSERT_MSG((trans.n_rows()==trans.n_cols() && trans.n_rows()==means.size() && trans.n_rows()==covs.size()), "hmm_generateG_init: matrices sizes do not match");
00267 Matrix trsum;
00268 Matrix& seq_ = *seq;
00269 Vector& states_ = *states;
00270 int M, N;
00271 int cur_state;
00272
00273 M = trans.n_rows();
00274 N = means[0].length();
00275
00276 trsum.Copy(trans);
00277
00278 for (int i = 0; i < M; i++)
00279 for (int j = 1; j < M; j++)
00280 trsum.set(i, j, trsum.get(i, j) + trsum.get(i, j-1));
00281
00282 seq_.Init(N, L);
00283 states_.Init(L);
00284
00285 cur_state = 0;
00286
00287 for (int i = 0; i < L; i++) {
00288 int j;
00289
00290
00291 double r = RAND_UNIFORM_01();
00292 for (j = 0; j < M; j++)
00293 if (r <= trsum.get(cur_state, j)) break;
00294 cur_state = j;
00295
00296
00297 Vector e;
00298 RAND_NORMAL_INIT(means[cur_state], covs[cur_state], &e);
00299 for (j = 0; j < N; j++)
00300 seq_.ref(j, i) = e[j];
00301 states_[i] = cur_state;
00302 }
00303 }
00304
00305 void GaussianHMM::EstimateInit(const Matrix& seq, const Vector& states, Matrix* trans, ArrayList<Vector>* means, ArrayList<Matrix>* covs) {
00306 DEBUG_ASSERT_MSG((seq.n_cols()==states.length()), "hmm_estimateG_init: sequence and states length must be the same");
00307 int M = 0;
00308 for (int i = 0; i < seq.n_cols(); i++)
00309 if (states[i] > M) M = (int) states[i];
00310 M++;
00311 GaussianHMM::EstimateInit(M, seq, states, trans, means, covs);
00312 }
00313
00314 void GaussianHMM::EstimateInit(int numStates, const Matrix& seq, const Vector& states, Matrix* trans, ArrayList<Vector>* means, ArrayList<Matrix>* covs) {
00315 DEBUG_ASSERT_MSG((seq.n_cols()==states.length()), "hmm_estimateD_init: sequence and states length must be the same");
00316
00317 int N = seq.n_rows();
00318 int M = numStates;
00319 int L = seq.n_cols();
00320
00321 Matrix &trans_ = *trans;
00322 ArrayList<Vector>& mean_ = *means;
00323 ArrayList<Matrix>& cov_ = *covs;
00324 Vector stateSum;
00325
00326 trans_.Init(M, M);
00327 mean_.Init();
00328 cov_.Init();
00329 stateSum.Init(M);
00330
00331 trans_.SetZero();
00332 for (int i = 0; i < M; i++) {
00333 Vector m;
00334 m.Init(N); m.SetZero();
00335 mean_.PushBackCopy(m);
00336
00337 Matrix c;
00338 c.Init(N, N); c.SetZero();
00339 cov_.PushBackCopy(c);
00340 }
00341
00342 stateSum.SetZero();
00343 for (int i = 0; i < L-1; i++) {
00344 int state = (int) states[i];
00345 int next_state = (int) states[i+1];
00346 stateSum[state]++;
00347 trans_.ref(state, next_state)++;
00348 }
00349 for (int i = 0; i < M; i++) {
00350 if (stateSum[i] == 0) stateSum[i] = -INFINITY;
00351 for (int j = 0; j < M; j++)
00352 trans_.ref(i, j) /= stateSum[i];
00353 }
00354
00355 stateSum.SetZero();
00356 for (int i = 0; i < L; i++) {
00357 int state = (int) states[i];
00358 Vector e;
00359 seq.MakeColumnVector(i, &e);
00360
00361 stateSum[state]++;
00362 la::AddTo(e, &mean_[state]);
00363 }
00364
00365 for (int i = 0; i < M; i++)
00366 if (stateSum[i] != 0)
00367 la::Scale(1.0/stateSum[i], &mean_[i]);
00368
00369 for (int i = 0; i < L; i++) {
00370 int state = (int) states[i];
00371 Vector e;
00372 seq.MakeColumnVector(i, &e);
00373 Vector d;
00374 la::SubInit(e, mean_[state], &d);
00375 Matrix D;
00376 D.AliasColVector(d);
00377 la::MulExpert(1.0, false, D, true, D, 1.0, &cov_[state]);
00378 }
00379
00380 for (int i = 0; i < M; i++)
00381 if (stateSum[i] != 0)
00382 la::Scale(1.0/stateSum[i], &cov_[i]);
00383 }
00384
00385 void GaussianHMM::ForwardProcedure(int L, const Matrix& trans, const Matrix& emis_prob, Vector *scales, Matrix* fs) {
00386 int M = trans.n_rows();
00387
00388 Matrix& fs_ = *fs;
00389 Vector& s_ = *scales;
00390
00391 fs_.SetZero();
00392 s_.SetZero();
00393
00394
00395 for (int i = 0; i < M; i++) {
00396 fs_.ref(i, 0) = trans.get(0, i) * emis_prob.get(i, 0);
00397 s_[0] += fs_.get(i, 0);
00398 }
00399 for (int i = 0; i < M; i++)
00400 fs_.ref(i, 0) /= s_[0];
00401
00402
00403 for (int t = 1; t < L; t++) {
00404 for (int j = 0; j < M; j++) {
00405 for (int i = 0; i < M; i++)
00406 fs_.ref(j, t) += fs_.get(i, t-1)*trans.get(i, j);
00407 fs_.ref(j, t) *= emis_prob.get(j, t);
00408 s_[t] += fs_.get(j, t);
00409 }
00410 for (int j = 0; j < M; j++)
00411 fs_.ref(j, t) /= s_[t];
00412 }
00413 }
00414
00415 void GaussianHMM::BackwardProcedure(int L, const Matrix& trans, const Matrix& emis_prob, const Vector& scales, Matrix* bs) {
00416 int M = trans.n_rows();
00417
00418 Matrix& bs_ = *bs;
00419 bs_.SetZero();
00420 for (int i = 0; i < M; i++)
00421 bs_.ref(i, L-1) = 1.0;
00422
00423 for (int t = L-2; t >= 0; t--) {
00424 for (int i = 0; i < M; i++) {
00425 for (int j = 0; j < M; j++)
00426 bs_.ref(i, t) += trans.get(i, j) * bs_.ref(j, t+1) * emis_prob.get(j, t+1);
00427 bs_.ref(i, t) /= scales[t+1];
00428 }
00429 }
00430 }
00431
00432 double GaussianHMM::Decode(int L, const Matrix& trans, const Matrix& emis_prob, Matrix* pstates, Matrix* fs, Matrix* bs, Vector* scales) {
00433 int M = trans.n_rows();
00434
00435 DEBUG_ASSERT_MSG((L==pstates->n_cols() && L==fs->n_cols() && L == bs->n_cols() &&
00436 M==trans.n_cols() && M==emis_prob.n_rows()),"hmm_decodeG: sizes do not match");
00437
00438 Matrix& ps_ = *pstates;
00439 Vector& s_ = *scales;
00440
00441 GaussianHMM::ForwardProcedure(L, trans, emis_prob, &s_, fs);
00442 GaussianHMM::BackwardProcedure(L, trans, emis_prob, s_, bs);
00443
00444 for (int i = 0; i < M; i++)
00445 for (int t = 0; t < L; t++)
00446 ps_.ref(i, t) = fs->get(i,t) * bs->get(i,t);
00447
00448 double logpseq = 0;
00449 for (int t = 0; t < L; t++)
00450 logpseq += log(s_[t]);
00451
00452 return logpseq;
00453 }
00454
00455 double GaussianHMM::Decode(const Matrix& trans, const Matrix& emis_prob, Matrix* pstates, Matrix* fs, Matrix* bs, Vector* scales) {
00456 int L = emis_prob.n_cols();
00457 return GaussianHMM::Decode(L, trans, emis_prob, pstates, fs, bs, scales);
00458 }
00459
00460 double GaussianHMM::ViterbiInit(const Matrix& trans, const Matrix& emis_prob, Vector* states) {
00461 int L = emis_prob.n_cols();
00462 return GaussianHMM::ViterbiInit(L, trans, emis_prob, states);
00463 }
00464
00465 double GaussianHMM::ViterbiInit(int L, const Matrix& trans, const Matrix& emis_prob, Vector* states) {
00466 int M = trans.n_rows();
00467 DEBUG_ASSERT_MSG((M==trans.n_cols() && M==emis_prob.n_rows()),"hmm_viterbiG: sizes do not match");
00468
00469 Vector& s_ = *states;
00470 s_.Init(L);
00471
00472 Vector v, vOld;
00473 v.Init(M);
00474 v.SetAll(-INFINITY);
00475 v[0] = 0;
00476 vOld.Copy(v);
00477
00478 Matrix w;
00479 w.Init(M, L);
00480
00481 Matrix logtrans;
00482 logtrans.Init(M, M);
00483
00484 for (int i = 0; i < M; i++)
00485 for (int j = 0; j < M; j++) logtrans.ref(i, j) = log(trans.get(i, j));
00486
00487
00488 for (int t = 0; t < L; t++) {
00489 for (int j = 0; j < M; j++) {
00490 double bestVal = -INFINITY;
00491 double bestPtr = -1;
00492 for (int i = 0; i < M; i++) {
00493 double val = vOld[i] + logtrans.get(i, j);
00494 if (val > bestVal) {
00495 bestVal = val;
00496 bestPtr = i;
00497 }
00498 }
00499 v[j] = bestVal + log(emis_prob.get(j, t));
00500 w.ref(j, t) = bestPtr;
00501 }
00502 vOld.CopyValues(v);
00503 }
00504
00505 double bestVal = -INFINITY;
00506 double bestPtr = -1;
00507 for (int i = 0; i < M; i++)
00508 if (v[i] > bestVal) {
00509 bestVal = v[i];
00510 bestPtr = i;
00511 }
00512
00513 s_[L-1] = bestPtr;
00514 for (int t = L-2; t >= 0; t--) {
00515 s_[t] = w.get((int)s_[t+1], t+1);
00516 }
00517
00518 return bestVal;
00519 }
00520
00521 void GaussianHMM::CalculateEmissionProb(const Matrix& seq, const ArrayList<Vector>& means, const ArrayList<Matrix>& inv_covs, const Vector& det, Matrix* emis_prob) {
00522 int L = seq.n_cols();
00523 int M = means.size();
00524 for (int t = 0; t < L; t++) {
00525 Vector e;
00526 seq.MakeColumnVector(t, &e);
00527 for (int i = 0; i < M; i++)
00528 emis_prob->ref(i, t) = NORMAL_DENSITY(e, means[i], inv_covs[i], det[i]);
00529 }
00530 }
00531
00532 void GaussianHMM::InitGaussParameter(int M, const ArrayList<Matrix>& seqs, Matrix* guessTR, ArrayList<Vector>* guessME, ArrayList<Matrix>* guessCO) {
00533 int N = seqs[0].n_rows();
00534 Matrix& gTR = *guessTR;
00535 ArrayList<Vector>& gME = *guessME;
00536 ArrayList<Matrix>& gCO = *guessCO;
00537 ArrayList<int> labels;
00538 Vector sumState;
00539
00540 kmeans(seqs, M, &labels, &gME, 1000, 1e-5);
00541
00542
00543
00544
00545 gTR.Init(M, M); gTR.SetZero();
00546 sumState.Init(M); sumState.SetZero();
00547 gCO.Init();
00548 for (int i = 0; i < M; i++) {
00549 Matrix m;
00550 m.Init(N, N); m.SetZero();
00551 gCO.PushBackCopy(m);
00552 }
00553
00554
00555 int t = 0;
00556 for (int p=0; p < seqs.size(); p++) {
00557 for (int q=0; q < seqs[p].n_cols(); q++,t++) {
00558 if (q == seqs[p].n_cols() -1) continue;
00559 int i = labels[t];
00560 int j = labels[t+1];
00561
00562 gTR.ref(i, j)++;
00563 sumState[i]++;
00564
00565 Vector data_j_Vec, sub_Vec;
00566 Matrix tmp_cov;
00567
00568 seqs[p].MakeColumnVector(q, &data_j_Vec);
00569 la::SubInit(gME[i], data_j_Vec, &sub_Vec);
00570 tmp_cov.AliasColVector(sub_Vec);
00571
00572 la::MulExpert(1, false, tmp_cov, true, tmp_cov, 1, &gCO[i]);
00573 }
00574 }
00575
00576
00577 for (int i = 0; i < M; i++)
00578 if (sumState[i] == 0) {
00579 for (int j = 0; j < M; j++) gTR.ref(i, j) = 0;
00580 gTR.ref(i, i) = 1;
00581 gME[i].SetZero();
00582 gCO[i].SetZero();
00583 for (int j = 0; j < N; j++) gCO[i].ref(j, j) = 1;
00584 }
00585 else {
00586 for (int j = 0; j < M; j++) gTR.ref(i, j) /= sumState[i];
00587 la::Scale(1.0/sumState[i], &gCO[i]);
00588 for (int j = 0; j < N; j++) gCO[i].ref(j, j) += 1e-3;
00589 }
00590
00591 }
00592
00593 void GaussianHMM::TrainViterbi(const ArrayList<Matrix>& seqs, Matrix* guessTR, ArrayList<Vector>* guessME, ArrayList<Matrix>* guessCO, int max_iter, double tol) {
00594 Matrix &gTR = *guessTR;
00595 ArrayList<Vector>& gME = *guessME;
00596 ArrayList<Matrix>& gCO = *guessCO;
00597 int L = -1;
00598 int M = gTR.n_rows();
00599 int N = gME[0].length();
00600 DEBUG_ASSERT_MSG((M==gTR.n_cols() && M==gME.size() && M == gCO.size()),"hmm_trainD: sizes do not match");
00601
00602 for (int i = 0; i < seqs.size(); i++)
00603 if (seqs[i].n_cols() > L) L = seqs[i].n_cols();
00604
00605 Matrix TR;
00606 ArrayList<Vector> ME;
00607 ArrayList<Matrix> CO;
00608 ArrayList<Matrix> INV_CO;
00609 Vector DET;
00610 TR.Init(M, M);
00611 ME.InitCopy(gME);
00612 CO.InitCopy(gCO);
00613 INV_CO.InitCopy(CO);
00614 DET.Init(M);
00615
00616 Matrix emis_prob;
00617 Vector sumState;
00618
00619 emis_prob.Init(M, L);
00620 sumState.Init(M);
00621
00622 double loglik = 0, oldlog;
00623 for (int iter = 0; iter < max_iter; iter++) {
00624 oldlog = loglik;
00625 loglik = 0;
00626
00627
00628 TR.SetZero();
00629 for (int i = 0; i < M; i++) {
00630 ME[i].SetZero();
00631 CO[i].SetZero();
00632 la::InverseOverwrite(gCO[i], &INV_CO[i]);
00633 DET[i] = pow(2.0*math::PI, -N/2.0) * pow(la::Determinant(gCO[i]), -0.5);
00634 }
00635 sumState.SetZero();
00636
00637
00638 for (int idx = 0; idx < seqs.size(); idx++) {
00639 L = seqs[idx].n_cols();
00640 Vector states;
00641 GaussianHMM::CalculateEmissionProb(seqs[idx], gME, INV_CO, DET, &emis_prob);
00642 loglik += GaussianHMM::ViterbiInit(L, gTR, emis_prob, &states);
00643
00644
00645 for (int t = 0; t < L-1; t++) {
00646 int i = (int) states[t];
00647 int j = (int) states[t+1];
00648 TR.ref(i, j) ++;
00649 }
00650
00651 for (int t = 0; t < L; t++) {
00652 Vector e;
00653 seqs[idx].MakeColumnVector(t, &e);
00654 int i = (int) states[t];
00655 sumState[i] ++;
00656 la::AddTo(e, &ME[i]);
00657
00658 Vector d;
00659 la::SubInit(e, gME[i], &d);
00660 Matrix D;
00661 D.AliasColVector(d);
00662 la::MulExpert(1, false, D, true, D, 1.0, &CO[i]);
00663 }
00664
00665 }
00666
00667
00668 for (int i = 0; i < M; i++) {
00669 double s = 0;
00670 for (int j = 0; j < M; j++) s += TR.get(i, j);
00671 if (s == 0) {
00672 for (int j = 0; j < M; j++) gTR.ref(i, j) = 0;
00673 gTR.ref(i, i) = 1;
00674 }
00675 else {
00676 for (int j = 0; j < M; j++) gTR.ref(i, j) = TR.get(i, j) / s;
00677 }
00678
00679 if (sumState[i] != 0) {
00680 la::ScaleOverwrite(1.0/sumState[i], ME[i], &gME[i]);
00681 la::ScaleOverwrite(1.0/sumState[i], CO[i], &gCO[i]);
00682 }
00683 }
00684
00685
00686 printf("Iter = %d Loglik = %8.4f\n", iter, loglik);
00687 if (fabs(oldlog - loglik) < tol) {
00688 printf("\nConverged after %d iterations\n", iter);
00689 break;
00690 }
00691 oldlog = loglik;
00692 }
00693 }
00694
00695
00696 void GaussianHMM::Train(const ArrayList<Matrix>& seqs, Matrix* guessTR, ArrayList<Vector>* guessME, ArrayList<Matrix>* guessCO, int max_iter, double tol) {
00697 Matrix &gTR = *guessTR;
00698 ArrayList<Vector>& gME = *guessME;
00699 ArrayList<Matrix>& gCO = *guessCO;
00700 int L = -1;
00701 int M = gTR.n_rows();
00702 int N = gME[0].length();
00703 DEBUG_ASSERT_MSG((M==gTR.n_cols() && M==gME.size() && M == gCO.size()),"hmm_trainD: sizes do not match");
00704
00705 for (int i = 0; i < seqs.size(); i++)
00706 if (seqs[i].n_cols() > L) L = seqs[i].n_cols();
00707
00708 Matrix TR;
00709 ArrayList<Vector> ME;
00710 ArrayList<Matrix> CO;
00711 ArrayList<Matrix> INV_CO;
00712 Vector DET;
00713 TR.Init(M, M);
00714 ME.InitCopy(gME);
00715 CO.InitCopy(gCO);
00716 INV_CO.InitCopy(CO);
00717 DET.Init(M);
00718
00719 Matrix ps, fs, bs, emis_prob;
00720 Vector s;
00721 Vector sumState;
00722
00723 ps.Init(M, L);
00724 fs.Init(M, L);
00725 bs.Init(M, L);
00726 s.Init(L);
00727 emis_prob.Init(M, L);
00728 sumState.Init(M);
00729
00730 double loglik = 0, oldlog;
00731 for (int iter = 0; iter < max_iter; iter++) {
00732 oldlog = loglik;
00733 loglik = 0;
00734
00735
00736 TR.SetZero();
00737 for (int i = 0; i < M; i++) {
00738 ME[i].SetZero();
00739 CO[i].SetZero();
00740 la::InverseOverwrite(gCO[i], &INV_CO[i]);
00741 DET[i] = pow(2.0*math::PI, -N/2.0) * pow(la::Determinant(gCO[i]), -0.5);
00742 }
00743 sumState.SetZero();
00744
00745
00746 for (int idx = 0; idx < seqs.size(); idx++) {
00747
00748 L = seqs[idx].n_cols();
00749 for (int t = 0; t < L; t++) {
00750 Vector e;
00751 seqs[idx].MakeColumnVector(t, &e);
00752 for (int i = 0; i < M; i++)
00753 emis_prob.ref(i, t) = NORMAL_DENSITY(e, gME[i], INV_CO[i], DET[i]);
00754 }
00755
00756 loglik += GaussianHMM::Decode(L, gTR, emis_prob, &ps, &fs, &bs, &s);
00757
00758
00759 for (int t = 0; t < L-1; t++) {
00760 for (int i = 0; i < M; i++)
00761 for (int j = 0; j < M; j++)
00762 TR.ref(i, j) += fs.get(i, t) * gTR.get(i, j) * emis_prob.get(j, t+1) * bs.get(j, t+1) / s[t+1];
00763 }
00764
00765 for (int t = 0; t < L; t++) {
00766 Vector e;
00767 seqs[idx].MakeColumnVector(t, &e);
00768 for (int i = 0; i < M; i++) {
00769 sumState[i] += ps.get(i, t);
00770 la::AddExpert(ps.get(i, t), e, &ME[i]);
00771
00772 Matrix D;
00773 D.AliasColVector(e);
00774 la::MulExpert(ps.get(i, t), false, D, true, D, 1.0, &CO[i]);
00775 }
00776 }
00777
00778 }
00779
00780
00781 for (int i = 0; i < M; i++) {
00782 double s = 0;
00783 for (int j = 0; j < M; j++) s += TR.get(i, j);
00784 if (s == 0) {
00785 for (int j = 0; j < M; j++) gTR.ref(i, j) = 0;
00786 gTR.ref(i, i) = 1;
00787 }
00788 else {
00789 for (int j = 0; j < M; j++) gTR.ref(i, j) = TR.get(i, j) / s;
00790 }
00791
00792 if (sumState[i] != 0) {
00793 la::ScaleOverwrite(1.0/sumState[i], ME[i], &gME[i]);
00794 Matrix D;
00795 D.AliasColVector(gME[i]);
00796 la::MulExpert(-1.0, false, D, true, D, 1.0/sumState[i], &CO[i]);
00797 gCO[i].CopyValues(CO[i]);
00798 }
00799 }
00800
00801
00802 printf("Iter = %d Loglik = %8.4f\n", iter, loglik);
00803 if (fabs(oldlog - loglik) < tol) {
00804 printf("\nConverged after %d iterations\n", iter);
00805 break;
00806 }
00807 oldlog = loglik;
00808 }
00809 }