From f329dc2b60b18ab83dbf875a67ef8cce856d27a2 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 25 May 2010 19:50:35 +0000 Subject: [PATCH] Document hmm_train executable entirely, and change some outputs from printf to fastlib standards where necessary --- fastlib/trunk/mlpack/hmm/train.cc | 217 +++++++++++++----------------- 1 file changed, 94 insertions(+), 123 deletions(-) diff --git a/fastlib/trunk/mlpack/hmm/train.cc b/fastlib/trunk/mlpack/hmm/train.cc index 960b07f051..994a7080be 100644 --- a/fastlib/trunk/mlpack/hmm/train.cc +++ b/fastlib/trunk/mlpack/hmm/train.cc @@ -11,12 +11,13 @@ * See the usage() function for complete option list */ -#include "fastlib/fastlib.h" +#include #include "support.h" #include "discreteHMM.h" #include "gaussianHMM.h" #include "mixgaussHMM.h" #include "mixtureDST.h" +#include "hmm_documentation.h" using namespace hmm_support; @@ -25,67 +26,67 @@ success_t train_viterbi(); void usage(); const fx_entry_doc hmm_train_main_entries[] = { + {"input_file", FX_REQUIRED, FX_STR, NULL, + "Input file containing data sequences to train on.\n"}, + {"guess_file", FX_PARAM, FX_STR, NULL, + "File containing guess of HMM model profile (.hmm)\n"}, + {"output_file", FX_PARAM, FX_STR, NULL, + "Output file containing trained HMM profile (default output..hmm)\n"}, {"type", FX_REQUIRED, FX_STR, NULL, - " HMM type : discrete | gaussian | mixture.\n"}, + "HMM type: discrete | gaussian | mixture\n"}, {"algorithm", FX_PARAM, FX_STR, NULL, - " Training algoritm: baumwelch | viterbi.\n"}, - {"seqfile", FX_REQUIRED, FX_STR, NULL, - " Output file for the data sequences.\n"}, - {"guess", FX_PARAM, FX_STR, NULL, - " File containing guessing HMM model profile.\n"}, - {"numstate", FX_PARAM, FX_INT, NULL, - " If no guessing profile specified, at least provide the number of states.\n"}, - {"profile", FX_REQUIRED, FX_STR, NULL, - " Output file containing trained HMM profile.\n"}, - {"maxiter", FX_PARAM, FX_INT, NULL, - " Maximum number of iterations, default = 500.\n"}, + "Training algorithm: baumwelch | viterbi (default baumwelch)\n"}, + {"num_states", FX_PARAM, FX_INT, NULL, + "If no guess profile is specified, at least provide the number of states\n"}, + {"max_iter", FX_PARAM, FX_INT, NULL, + "Maximum number of iterations (default 500)\n"}, {"tolerance", FX_PARAM, FX_DOUBLE, NULL, - " Error tolerance on log-likelihood as a stopping criteria.\n"}, + "Error tolerance on log-likelihood as a stopping criteria (default 0.001)\n"}, FX_ENTRY_DOC_DONE }; -const fx_submodule_doc hmm_train_main_submodules[] = { +const fx_submodule_doc hmm_train_submod_entries[] = { + {"formats", &hmm_format_doc, + "Documentation for file formats used by this program and other MLPACK HMM tools\n"}, FX_SUBMODULE_DOC_DONE }; const fx_module_doc hmm_train_main_doc = { - hmm_train_main_entries, hmm_train_main_submodules, - "This is a program training HMM models from data sequences. \n" + hmm_train_main_entries, hmm_train_submod_entries, + "The hmm_train utility is for training HMMs from data sequences. Given an\n" + "input file of data sequences, and optionally a file containing a guess of\n" + "the HMM profile (or a parameter specifying the number of states), the program\n" + "will use the specified training algorithm (Viterbi or Baum-Welch, default\n" + "Baum-Welch) to train the HMM until the log-likelihood error reaches the given\n" + "value (default 0.001).\n" + "\n" + "It is important to note that if the guess file is not specified, the number\n" + "of states must be specified. Additionally, a guess file must be specified\n" + "if the HMM type is 'mixture'.\n" + "\n" + "See the documentation in the 'formats' submodule (--help=formats) for more\n" + "information on the file formats that this program uses.\n" }; -void usage() { - printf("\nUsage:\n" - " train --type=={discrete|gaussian|mixture} OPTION\n" - "[OPTIONS]\n" - " --algorithm={baumwelch|viterbi} : algorithm used for training, default Baum-Welch\n" - " --seqfile=file : file contains input sequences\n" - " --guess=file : file contains guess HMM profile\n" - " --numstate=NUM : if no guess profile is specified, at least specify the number of state\n" - " --profile=file : output file for estimated HMM profile\n" - " --maxiter=NUM : maximum number of iteration, default=500\n" - " --tolerance=NUM : error tolerance on log-likelihood, default=1e-3\n" - ); -} - int main(int argc, char* argv[]) { fx_init(argc, argv, &hmm_train_main_doc); success_t s = SUCCESS_PASS; - if (fx_param_exists(NULL,"type")) { + if (fx_param_exists(NULL, "type")) { const char* algorithm = fx_param_str(NULL, "algorithm", "baumwelch"); - if (strcmp(algorithm,"baumwelch")==0) + if (strcmp(algorithm, "baumwelch") == 0) s = train_baumwelch(); - else if (strcmp(algorithm,"viterbi")==0) + else if (strcmp(algorithm, "viterbi") == 0) s = train_viterbi(); else { - printf("Unrecognized algorithm: must be baumwelch or viterbi !!!\n"); + FATAL("Unrecognized training algorithm: must be 'baumwelch' or 'viterbi'.\n"); s = SUCCESS_FAIL; } } else { - printf("Unrecognized type: must be: discrete | gaussian | mixture !!!\n"); + FATAL("Unrecognized HMM type; must be 'discrete', 'gaussian', or 'mixture'.\n"); s = SUCCESS_FAIL; } - if (!PASSED(s)) usage(); + fx_done(NULL); } @@ -101,10 +102,8 @@ success_t train_baumwelch() { return train_baumwelch_gaussian(); else if (strcmp(type, "mixture")==0) return train_baumwelch_mixture(); - else { - printf("Unrecognized type: must be: discrete | gaussian | mixture !!!\n"); - return SUCCESS_FAIL; - } + + return SUCCESS_FAIL; } success_t train_viterbi_discrete(); @@ -119,40 +118,34 @@ success_t train_viterbi() { return train_viterbi_gaussian(); else if (strcmp(type, "mixture")==0) return train_viterbi_mixture(); - else { - printf("Unrecognized type: must be: discrete | gaussian | mixture !!!\n"); - return SUCCESS_FAIL; - } + + return SUCCESS_FAIL; } success_t train_baumwelch_mixture() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } - MixtureofGaussianHMM hmm; ArrayList seqs; - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.mix.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.mix.hmm"); load_matrix_list(seqin, &seqs); - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load parameters from file %s\n", guess); + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading guess parameters from file %s...", guess); hmm.InitFromFile(guess); } else { hmm.Init(); - printf("Automatic initialization not supported !!!"); + FATAL("Automatic initialization not supported for mixture training."); return SUCCESS_FAIL; } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); + NOTIFY("Training using Baum-Welch algorithm..."); hmm.TrainBaumWelch(seqs, maxiter, tol); hmm.SaveProfile(proout); @@ -161,36 +154,30 @@ success_t train_baumwelch_mixture() { } success_t train_baumwelch_gaussian() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } GaussianHMM hmm; ArrayList seqs; - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.gauss.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.gauss.hmm"); load_matrix_list(seqin, &seqs); - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load parameters from file %s\n", guess); + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading guess parameters from file %s...", guess); hmm.InitFromFile(guess); } else { // otherwise initialized using information from the data - int numstate = fx_param_int_req(NULL, "numstate"); - printf("Generate HMM parameters: NUMSTATE = %d\n", numstate); + int numstate = fx_param_int_req(NULL, "num_states"); + NOTIFY("Generating HMM parameters: %d states...", numstate); hmm.InitFromData(seqs, numstate); - printf("Done.\n"); } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); - printf("Training ...\n"); + NOTIFY("Training using Baum-Welch algorithm..."); hmm.TrainBaumWelch(seqs, maxiter, tol); - printf("Done.\n"); hmm.SaveProfile(proout); @@ -198,33 +185,29 @@ success_t train_baumwelch_gaussian() { } success_t train_baumwelch_discrete() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } - - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.dis.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.dis.hmm"); ArrayList seqs; load_vector_list(seqin, &seqs); DiscreteHMM hmm; - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load HMM parameters from file %s\n", guess); + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading HMM parameters from file %s...", guess); hmm.InitFromFile(guess); } else { // otherwise randomly initialized using information from the data - int numstate = fx_param_int_req(NULL, "numstate"); - printf("Randomly generate parameters: NUMSTATE = %d\n", numstate); + int numstate = fx_param_int_req(NULL, "num_states"); + NOTIFY("Randomly generating parameters: %d states...", numstate); hmm.InitFromData(seqs, numstate); } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); + NOTIFY("Training using Baum-Welch algorithm..."); hmm.TrainBaumWelch(seqs, maxiter, tol); hmm.SaveProfile(proout); @@ -233,33 +216,29 @@ success_t train_baumwelch_discrete() { } success_t train_viterbi_mixture() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } - MixtureofGaussianHMM hmm; ArrayList seqs; - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.mix.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.mix.hmm"); load_matrix_list(seqin, &seqs); - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load parameters from file %s\n", guess); + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading parameters from guess file %s...", guess); hmm.InitFromFile(guess); } else { hmm.Init(); - printf("Automatic initialization not supported !!!"); + FATAL("Automatic initialization not supported for mixture training."); return SUCCESS_FAIL; } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); + NOTIFY("Training using Viterbi algorithm..."); hmm.TrainViterbi(seqs, maxiter, tol); hmm.SaveProfile(proout); @@ -268,33 +247,29 @@ success_t train_viterbi_mixture() { } success_t train_viterbi_gaussian() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } - GaussianHMM hmm; ArrayList seqs; - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.gauss.viterbi.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.gauss.hmm"); load_matrix_list(seqin, &seqs); - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load parameters from file %s\n", guess); + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading parameters from file %s...", guess); hmm.InitFromFile(guess); } else { // otherwise initialized using information from the data - int numstate = fx_param_int_req(NULL, "numstate"); - printf("Generate parameters: NUMSTATE = %d\n", numstate); + int numstate = fx_param_int_req(NULL, "num_states"); + NOTIFY("Generating parameters with %d states\n", numstate); hmm.InitFromData(seqs, numstate); } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); + NOTIFY("Training using Viterbi algorithm..."); hmm.TrainViterbi(seqs, maxiter, tol); hmm.SaveProfile(proout); @@ -303,34 +278,30 @@ success_t train_viterbi_gaussian() { } success_t train_viterbi_discrete() { - if (!fx_param_exists(NULL, "seqfile")) { - printf("--seqfile must be defined.\n"); - return SUCCESS_FAIL; - } - DiscreteHMM hmm; ArrayList seqs; - const char* seqin = fx_param_str_req(NULL, "seqfile"); - const char* proout = fx_param_str(NULL, "profile", "pro.dis.viterbi.out"); + const char* seqin = fx_param_str_req(NULL, "input_file"); + const char* proout = fx_param_str(NULL, "output_file", "output.dis.hmm"); load_vector_list(seqin, &seqs); - if (fx_param_exists(NULL, "guess")) { // guessed parameters in a file + if (fx_param_exists(NULL, "guess_file")) { // guessed parameters in a file ArrayList matlst; - const char* guess = fx_param_str_req(NULL, "guess"); - printf("Load parameters from file %s\n", guess); + const char* guess = fx_param_str_req(NULL, "guess_file"); + NOTIFY("Loading guess parameters from file %s...", guess); hmm.InitFromFile(guess); } else { // otherwise randomly initialized using information from the data - int numstate = fx_param_int_req(NULL, "numstate"); - printf("Generate parameters with NUMSTATE = %d\n", numstate); + int numstate = fx_param_int_req(NULL, "num_states"); + NOTIFY("Generate parameters with %d states\n", numstate); hmm.InitFromData(seqs, numstate); } - int maxiter = fx_param_int(NULL, "maxiter", 500); + int maxiter = fx_param_int(NULL, "max_iter", 500); double tol = fx_param_double(NULL, "tolerance", 1e-3); + NOTIFY("Training using Viterbi algorithm..."); hmm.TrainViterbi(seqs, maxiter, tol); hmm.SaveProfile(proout);