static void Apply(HMMType& hmm, void* /* extraInfo */) { // Load observations. const string inputFile = CLI::GetParam<string>("input_file"); mat dataSeq; data::Load(inputFile, dataSeq, true); // See if transposing the data could make it the right dimensionality. if ((dataSeq.n_cols == 1) && (hmm.Emission()[0].Dimensionality() == 1)) { Log::Info << "Data sequence appears to be transposed; correcting." << endl; dataSeq = dataSeq.t(); } // Verify correct dimensionality. if (dataSeq.n_rows != hmm.Emission()[0].Dimensionality()) Log::Fatal << "Observation dimensionality (" << dataSeq.n_rows << ") " << "does not match HMM Gaussian dimensionality (" << hmm.Emission()[0].Dimensionality() << ")!" << endl; arma::Col<size_t> sequence; hmm.Predict(dataSeq, sequence); // Save output. const string outputFile = CLI::GetParam<string>("output_file"); data::Save(outputFile, sequence, true); }
static void Apply(HMMType& hmm, vector<mat>* trainSeqPtr) { const bool batch = CLI::HasParam("batch"); const double tolerance = CLI::GetParam<double>("tolerance"); // Do we need to replace the tolerance? if (CLI::HasParam("tolerance")) hmm.Tolerance() = tolerance; const string labelsFile = CLI::GetParam<string>("labels_file"); // Verify that the dimensionality of our observations is the same as the // dimensionality of our HMM's emissions. vector<mat>& trainSeq = *trainSeqPtr; for (size_t i = 0; i < trainSeq.size(); ++i) if (trainSeq[i].n_rows != hmm.Emission()[0].Dimensionality()) Log::Fatal << "Dimensionality of training sequence " << i << " (" << trainSeq[i].n_rows << ") is not equal to the dimensionality of " << "the HMM (" << hmm.Emission()[0].Dimensionality() << ")!" << endl; vector<arma::Row<size_t>> labelSeq; // May be empty. if (labelsFile != "") { // Do we have multiple label files to load? char lineBuf[1024]; if (batch) { fstream f(labelsFile); if (!f.is_open()) Log::Fatal << "Could not open '" << labelsFile << "' for reading." << endl; // Now read each line in. f.getline(lineBuf, 1024, '\n'); while (!f.eof()) { Log::Info << "Adding training sequence labels from '" << lineBuf << "'." << endl; // Now read the matrix. Mat<size_t> label; data::Load(lineBuf, label, true); // Fatal on failure. // Ensure that matrix only has one row. if (label.n_cols == 1) label = trans(label); if (label.n_rows > 1) Log::Fatal << "Invalid labels; must be one-dimensional." << endl; // Check all of the labels. for (size_t i = 0; i < label.n_cols; ++i) { if (label[i] >= hmm.Transition().n_cols) { Log::Fatal << "HMM has " << hmm.Transition().n_cols << " hidden " << "states, but label on line " << i << " of '" << lineBuf << "' is " << label[i] << " (should be between 0 and " << (hmm.Transition().n_cols - 1) << ")!" << endl; } } labelSeq.push_back(label.row(0)); f.getline(lineBuf, 1024, '\n'); } f.close(); } else { Mat<size_t> label; data::Load(labelsFile, label, true); // Ensure that matrix only has one row. if (label.n_cols == 1) label = trans(label); if (label.n_rows > 1) Log::Fatal << "Invalid labels; must be one-dimensional." << endl; // Verify the same number of observations as the data. if (label.n_elem != trainSeq[labelSeq.size()].n_cols) Log::Fatal << "Label sequence " << labelSeq.size() << " does not have" << " the same number of points as observation sequence " << labelSeq.size() << "!" << endl; // Check all of the labels. for (size_t i = 0; i < label.n_cols; ++i) { if (label[i] >= hmm.Transition().n_cols) { Log::Fatal << "HMM has " << hmm.Transition().n_cols << " hidden " << "states, but label on line " << i << " of '" << labelsFile << "' is " << label[i] << " (should be between 0 and " << (hmm.Transition().n_cols - 1) << ")!" << endl; } } labelSeq.push_back(label.row(0)); } // Now perform the training with labels. hmm.Train(trainSeq, labelSeq); } else { // Perform unsupervised training. hmm.Train(trainSeq); } // Save the model. if (CLI::HasParam("output_model_file")) { const string modelFile = CLI::GetParam<string>("output_model_file"); SaveHMM(hmm, modelFile); } }