// file: $isip/class/stats/MixtureModel/mm_07.cc // version: $Id: mm_07.cc 7556 2001-12-26 22:32:53Z alphonso $ // // isip include files // #include "MixtureModel.h" // method: add // // arguments: // StatisticalModelBase& ptr: (input) pointer // // return: a bool8 value indicating status // // add models to models_d // bool8 MixtureModel::add(StatisticalModelBase& ptr_a) { // declare statistical model // StatisticalModel m; // assign input pointer to StatisticalModel // m.assign(ptr_a); // set the mode of the model // m.setMode(mode_d); // add StatisticalModel to list // models_d.insert(&m); // exit gracefully // return true; } // method: setModels // // arguments: // SingleLinkedList& ptr: (input) pointer // // return: a bool8 value indicating status // // replace models_d with the input // bool8 MixtureModel::setModels(SingleLinkedList& ptr_a) { // assign the models // models_d.assign(ptr_a); // set each model to be in the compute mode that we are in // for (bool8 more_models = models_d.gotoFirst(); more_models; more_models = models_d.gotoNext()) { models_d.getCurr()->setMode(mode_d); } // exit gracefully // is_valid_d = false; return true; } // method: setWeights // // arguments: // const VectorFloat& arg: (input) vector of weights // // return: a bool8 value indicating status // // this method sets the weight for each mixture // bool8 MixtureModel::setWeights(const VectorFloat& arg_a) { // set the weight // weights_d.assign(arg_a); // exit gracefully // is_valid_d = false; return true; } // method: setMode // // arguments: // MODE arg: (input) mode to set // // return: a bool8 value indicating status // // this method sets the computation mode // bool8 MixtureModel::setMode(MODE arg_a) { // set computation mode of all the models in list // for (bool8 more_models = models_d.gotoFirst(); more_models; more_models = models_d.gotoNext()) { models_d.getCurr()->setMode(arg_a); } // change the weights if necessary // if ((mode_d == PRECOMPUTE) && (is_valid_d)) { weights_d.exp(); } // force reinitialization // is_valid_d = false; mode_d = arg_a; // exit gracefully // return true; } // method: init // // arguments: none // // return: a bool8 value indicating status // // this method precomputes the necessary data for fast computation // bool8 MixtureModel::init() { // if we are not in the precompute mode, we don't need to do anything. // if (mode_d != PRECOMPUTE) { is_valid_d = true; return true; } // if the data are valid, we also don't need to do anything. // else if (is_valid_d) { return true; } // check the arguments // int32 len = weights_d.length(); if (len <= 0) { is_valid_d = false; return false; } // init all the models in list // for (bool8 more_models = models_d.gotoFirst(); more_models; more_models = models_d.gotoNext()) { models_d.getCurr()->init(); } // convert to natural log scaling // weights_d.log(); // exit gracefully // return (is_valid_d = true); } // method: getWeights // // arguments: // VectorFloat& weights: (output) output weight vector // // return: a bool8 value indicating status // // this method gives the weights of the Mixture model // bool8 MixtureModel::getWeights(VectorFloat& weights_a) const { // if the weights have not been initialized, return them // if ((mode_d == NONE) || ((mode_d == PRECOMPUTE) && (!is_valid_d))) { return weights_a.assign(weights_d); } // else: convert // else { return weights_a.exp(weights_d); } } // method: isNormalized // // arguments: // float32 norm: (input) the value that the weights should sum to // // return: true if the weights sum up to 'norm', false otherwise // // this method determines if the weights are normalized to a certain 'norm' // value // bool8 MixtureModel::isNormalized(float32 norm_a) const { if ((mode_d == NONE) || ((mode_d == PRECOMPUTE) && (!is_valid_d))) { // loop over the weights and sum // float32 sum = weights_d.sum(); // are we normalized? // return (Integral::almostEqual(sum, norm_a)); } // else we are in PRECOMPUTE mode and the weights have been initialized // else { // loop over the weights and sum // float32 sum = 0; int32 length = weights_d.length(); for (int32 i = 0; i < length; i++) { sum += Integral::exp(weights_d(i)); } // are we normalized? // return (Integral::almostEqual(sum, norm_a)); } } // method: initializeWeights // // arguments: none // // return: bool8 value indicating status // // this method initialize the weight vector // bool8 MixtureModel::initializeWeights() { // set the weight vector to be the same dimension as the number of models // if (weights_d.length() != models_d.length()) { weights_d.setLength(models_d.length()); } // mode: NONE // if ((mode_d == NONE) || (!is_valid_d)) { // compute the weight for each mixture // float32 weight = 1.0 / (float32)weights_d.length(); // initialize the weight vector // for (int i=0; i < weights_d.length(); i++) { weights_d(i) = weight; } } // mode: PRECOMPUTE // else { // compute the weight for each mixture // float32 weight = -log(weights_d.length()); // initialize the weight vector // for (int i=0; i < weights_d.length(); i++) { weights_d(i) = weight; } } // exit gracefully // return true; } // method: normalizeWeights // // arguments: // float32 norm: (input) the value that the weights should sum to // // return: bool8 value indicating status // // this method renormalizes the weight vector so that the weights sum // to the input 'norm' value. // bool8 MixtureModel::normalizeWeights(float32 norm_a) { // mode: NONE // if ((mode_d == NONE) || (!is_valid_d)) { // loop over the weights and sum // float32 sum = weights_d.sum(); // divide each weight by the sum and multiply each by norm_a to // renormalize to norm_a // weights_d.mult(norm_a / sum); } // mode: PRECOMPUTE // else { // pull the weights back to a linear scale // weights_d.exp(); // loop over the weights and sum // float32 sum = weights_d.sum(); // divide each weight by the sum and multiply each by norm_a // to renormalize to norm_a // weights_d.mult(norm_a / sum); // now make the weights log again // weights_d.log(); } // exit gracefully // return true; }