TrainTools.cpp

Go to the documentation of this file.
00001 /*
00002 This file is part of LIA_RAL which is a set of software based on ALIZE
00003 toolkit for speaker recognition. ALIZE toolkit is required to use LIA_RAL.
00004 
00005 LIA_RAL project is a development project was initiated by the computer
00006 science laboratory of Avignon / France (Laboratoire Informatique d'Avignon -
00007 LIA) [http://lia.univ-avignon.fr <http://lia.univ-avignon.fr/>]. Then it
00008 was supported by two national projects of the French Research Ministry:
00009         - TECHNOLANGUE program [http://www.technolangue.net]
00010         - MISTRAL program [http://mistral.univ-avignon.fr]
00011 
00012 LIA_RAL is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as
00014 published by the Free Software Foundation, either version 3 of
00015 the License, or any later version.
00016 
00017 LIA_RAL is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021 
00022 You should have received a copy of the GNU Lesser General Public
00023 License along with LIA_RAL.
00024 If not, see [http://www.gnu.org/licenses/].
00025 
00026 The LIA team as well as the LIA_RAL project team wants to highlight the
00027 limits of voice authentication in a forensic context.
00028 The "Person Authentification by Voice: A Need of Caution" paper
00029 proposes a good overview of this point (cf. "Person
00030 Authentification by Voice: A Need of Caution", Bonastre J.F.,
00031 Bimbot F., Boe L.J., Campbell J.P., Douglas D.A., Magrin-
00032 chagnolleau I., Eurospeech 2003, Genova].
00033 The conclusion of the paper of the paper is proposed bellow:
00034 [Currently, it is not possible to completely determine whether the
00035 similarity between two recordings is due to the speaker or to other
00036 factors, especially when: (a) the speaker does not cooperate, (b) there
00037 is no control over recording equipment, (c) recording conditions are not
00038 known, (d) one does not know whether the voice was disguised and, to a
00039 lesser extent, (e) the linguistic content of the message is not
00040 controlled. Caution and judgment must be exercised when applying speaker
00041 recognition techniques, whether human or automatic, to account for these
00042 uncontrolled factors. Under more constrained or calibrated situations,
00043 or as an aid for investigative purposes, judicious application of these
00044 techniques may be suitable, provided they are not considered as infallible.
00045 At the present time, there is no scientific process that enables one to
00046 uniquely characterize a persones voice or to identify with absolute
00047 certainty an individual from his or her voice.]
00048 
00049 Copyright (C) 2004-2010
00050 Laboratoire d'informatique d'Avignon [http://lia.univ-avignon.fr]
00051 LIA_RAL admin [alize@univ-avignon.fr]
00052 Jean-Francois Bonastre [jean-francois.bonastre@univ-avignon.fr]
00053 */
00054 
00055 #if !defined(ALIZE_TrainTools_cpp)
00056 #define ALIZE_TrainTools_cpp
00057 
00058 #include <iostream>
00059 #include <fstream>  // pour outFile
00060 #include <cstdio>   // pour printf()
00061 #include <cassert> // pour le debug pratique
00062 #include <cmath>
00063 #include <liatools.h>
00064 #include <DoubleSquareMatrix.h>
00065 
00066 // Small stuff (command line, small functions
00067 TrainCfg::TrainCfg(Config &config){
00068  _initVarianceFlooring  = config.getParam("initVarianceFlooring").toDouble();    // variance control parameters - relative to global data variance 
00069  _initVarianceCeiling   = config.getParam("initVarianceCeiling").toDouble();     // (1.0 is 100 % of the global vriance, 0.2 is 20% of the global variance
00070  _finalVarianceFlooring = config.getParam("finalVarianceFlooring").toDouble();   // Each parameter varies from initial value to final value 
00071  _finalVarianceCeiling  = config.getParam("finalVarianceCeiling").toDouble();    
00072  _nbTrainIt = config.getParam("nbTrainIt").toLong();                             // number of  it 
00073  _baggedFrameProbability= config.getParam("baggedFrameProbability").toDouble();  // Defines the percentage of frames used for one IT
00074  if (config.existsParam("baggedFrameProbabilityInit")) _baggedFrameProbabilityInit =config.getParam("baggedFrameProbabilityInit").toDouble();  // TODO : SUPRESS (deprecated)
00075  else _baggedFrameProbabilityInit=0;// Defines the percentage of frames BY COMPONENT used for the init from scratch
00076  if (config.existsParam("normalizeModel")) _normalizeModel=config.getParam("normalizeModel").toBool();// normalize the world (at each iteration) or not (default)
00077  else _normalizeModel=false;
00078  if (_normalizeModel){
00079    _normalizeModelNbIt=1;
00080    if (config.existsParam("normalizeModelMeanOnly")) 
00081      _normalizeModelMeanOnly=config.getParam("normalizeModelMeanOnly").toBool(); 
00082    else _normalizeModelMeanOnly=false;
00083    if (_normalizeModelMeanOnly) 
00084      _normalizeModelNbIt=config.getParam("normalizeModelNbIt").toLong();
00085  }
00086 
00087  _componentReduction=false;
00088  if (config.existsParam("componentReduction")) _componentReduction=config.getParam("componentReduction").toBool();
00089   _targetDistribCount=0;
00090  if (_componentReduction){
00091    _targetDistribCount=config.getParam("targetMixtureDistribCount").toLong();
00092  }
00093 }
00094 void TrainCfg::showConfig(ostream & st=cout){
00095   st << "Training parameters "<<endl;
00096   st <<"nb training iterations:"<<_nbTrainIt<<endl;
00097   st <<"init variance floor:"<<_initVarianceFlooring<<" final floor:"<<_finalVarianceFlooring<<endl;
00098   st <<"init variance ceil:"<<_initVarianceCeiling<<" final ceil:"<<_finalVarianceCeiling<<endl;
00099   if (_normalizeModel){
00100     st <<"normaliseModel on";
00101     if (_normalizeModelMeanOnly){
00102       st <<" Mean Only mode, nbIt:"<<_normalizeModelNbIt<<endl;
00103     }
00104     else st<<endl;
00105   }
00106   else st <<"normalise model off"<<endl;
00107   if (_componentReduction)
00108     st <<"Component number reduction, final["<<_targetDistribCount<<"]"<<endl;
00109 }
00110 MAPCfg::MAPCfg(Config &config){
00111   // MAP Algorithm 
00112   _mean=false;_var=false;_weight=false;
00113   if (config.existsParam("meanAdapt")) _mean=config.getParam("meanAdapt").toBool();
00114   if (config.existsParam("varAdapt")) _var=config.getParam("varAdapt").toBool();
00115   if (config.existsParam("weightAdapt")) _weight=config.getParam("weightAdapt").toBool();
00116   if (!_var && !_mean && !_weight) cerr <<"MAP, no adaptation selected !"<<endl;
00117   _method=config.getParam("MAPAlgo");
00118   if ((_method=="MAPConst")||(_method=="MAPConst2")){
00119     if (_mean)_r[0]=config.getParam("MAPAlphaMean").toDouble();//0.75 a priori probability of the initModel                     
00120     if (_var)_r[1]=config.getParam("MAPAlphaVar").toDouble();
00121     if (_weight)_r[2]=config.getParam("MAPAlphaWeight").toDouble();
00122   }                     
00123   else 
00124     if ((_method=="MAPOccDep")||(_method=="MAPModelBased")|| (_method=="MLLR")){
00125       if (_mean) _r[0]= config.getParam("MAPRegFactorMean").toDouble();// r factor, r=14                        
00126       if (_var)  _r[1]= config.getParam("MAPRegFactorVar").toDouble();// r factor, r=14
00127       if (_weight)_r[2]= config.getParam("MAPRegFactorWeight").toDouble();// r factor, r=14 
00128     } else cerr <<"mapAlgo["<<_method<<"] unknown"<<endl; 
00129   _normalizeModel=false;
00130   if (config.existsParam("normalizeModel")) _normalizeModel=config.getParam("normalizeModel").toBool();// normalize the world (at each iteration) or not (default)
00131   if (_normalizeModel){
00132     _normalizeModelNbIt=1;
00133     if (config.existsParam("normalizeModelMeanOnly")) 
00134       _normalizeModelMeanOnly=config.getParam("normalizeModelMeanOnly").toBool(); 
00135     else _normalizeModelMeanOnly=false;
00136     if (_normalizeModelMeanOnly) 
00137       _normalizeModelNbIt=config.getParam("normalizeModelNbIt").toLong();
00138   }
00139   else _normalizeModel=false;   
00140   _nbTrainIt = 1;
00141   if (config.existsParam("nbTrainIt"))  _nbTrainIt=config.getParam("nbTrainIt").toLong();                      // number of  it 
00142   _nbEmIt = 1;
00143   if (config.existsParam("nbEmIt"))  _nbEmIt=config.getParam("nbEmIt").toLong();                      // number of EM/ML  it for modelbased map
00144   if (config.existsParam("baggedFrameProbability")) 
00145       _baggedFrameProbability= config.getParam("baggedFrameProbability").toDouble();
00146       else  _baggedFrameProbability=1.0;// Defines the percentage of frames used for one IT
00147 }
00148 void MAPCfg::showConfig(ostream & st=cout){
00149   st << "MAP Algo "<<_method<<endl;
00150   if (_mean) st<<"Mean adaption, param["<<_r[0]<<"]"<<endl;
00151   if (_var) st<<"Variance adaption, param["<<_r[1]<<"]"<<endl;
00152   if (_weight) st<<"Weight adaptation, param["<<_r[2]<<"]"<<endl;
00153   st <<"Nb training iterations["<<_nbTrainIt<<"]"<<endl;
00154   if (_normalizeModel){
00155     st <<"NormaliseModel on";
00156     if (_normalizeModelMeanOnly){
00157       st <<" Mean Only mode, nbIt["<<_normalizeModelNbIt<<"]"<<endl;
00158     }
00159     else st<<endl;
00160   }
00161   else st <<"Normalise model off"<<endl;
00162 }
00163 
00164 // Mixture and ditrib tools
00165 
00166 void copyMixture(DistribGD &s,DistribGD &d){
00167   unsigned long vectSize=s.getVectSize();
00168   if (vectSize!=d.getVectSize()) throw Exception("vectSize != for copyMixture" , __FILE__, __LINE__);
00169   for (unsigned long c=0;c<vectSize;c++){
00170     d.setMean(s.getMean(c),c);
00171     d.setCov(s.getCov(c),c);
00172   }
00173   d.computeAll();
00174 }
00175 unsigned long selectComponent(bool selectCompA[],XList & distribL, MixtureGD &inputM){
00176   unsigned long nbInputDistrib=inputM.getDistribCount();  
00177   for (unsigned long idx=0;idx<nbInputDistrib;idx++) selectCompA[idx]=true;
00178   for (unsigned long idx=0;idx<nbInputDistrib;idx++) selectCompA[idx]=true;
00179   unsigned long nbOutputDistrib=nbInputDistrib;
00180   for (unsigned long idxS=0;idxS<distribL.getLineCount();idxS++){
00181     selectCompA[distribL.getLine(idxS).getElement(0).toLong()]=false;
00182     nbOutputDistrib--;
00183   } 
00184   return nbOutputDistrib;
00185 }
00186 unsigned long selectComponent(bool selectCompA[],double wFactor,MixtureGD &inputM){
00187   unsigned long nbInputDistrib=inputM.getDistribCount(); 
00188   for (unsigned long idx=0;idx<nbInputDistrib;idx++) selectCompA[idx]=true;
00189   unsigned long nbOutputDistrib=nbInputDistrib;
00190   for (unsigned long idx=0;idx<nbInputDistrib;idx++)
00191     if ((selectCompA[idx])&&(inputM.weight(idx)<wFactor)){
00192       selectCompA[idx]=false;
00193       nbOutputDistrib--;
00194     } 
00195   return nbOutputDistrib;
00196 }
00197 unsigned long selectComponent(bool selectCompA[],unsigned long nbTop,MixtureGD &inputM){
00198   unsigned long nbInputDistrib=inputM.getDistribCount(); 
00199   for (unsigned long idx=0;idx<nbInputDistrib;idx++) selectCompA[idx]=false;
00200   TabWeight tabW(inputM);
00201   for (unsigned long i=0; i<nbTop;i++){
00202     selectCompA[tabW.getDistrib(i)]=true;
00203   }
00204   return nbTop;
00205 }
00206 double reduceModel(bool selectCompA[],MixtureGD &inputM,MixtureGD &outputM){
00207   unsigned long nbInputDistrib=inputM.getDistribCount(); 
00208   unsigned long outputIdx=0;
00209   double totW=0;
00210   for (unsigned idx=0;idx<nbInputDistrib;idx++){
00211     if (selectCompA[idx]){
00212       DistribGD &s=inputM.getDistrib(idx);
00213       DistribGD &d=outputM.getDistrib(outputIdx);
00214       copyMixture(s,d);
00215       outputM.weight(outputIdx)=inputM.weight(idx);
00216       totW+=outputM.weight(outputIdx);
00217       outputIdx++;
00218     }
00219   }
00220   return totW;
00221 }
00222 
00223 void normalizeWeights(MixtureGD &outputM){
00224   double totW=0;
00225   for (unsigned long idx=0;idx<outputM.getDistribCount();idx++)
00226     totW+=outputM.weight(idx);
00227   for (unsigned long idx=0;idx<outputM.getDistribCount();idx++)
00228     outputM.weight(idx)/=totW;
00229 }
00230 
00231 // TRAINING AND ADAPTING FUNCTIONS
00232 //*******************************
00233 
00234 // fuseModels. this function builds a GMM using two statistic estimations, represented by two models and the number of frames
00235 // the life of this function should be very short, as a +operator on the stat accumulator will replace it
00236 void fuseModels(const MixtureGD & model1,unsigned long nbFrameM1,const MixtureGD & model2,unsigned long nbFrameM2,MixtureGD &result){
00237   unsigned long vectSize=model1.getVectSize();  
00238   if (vectSize!=model2.getVectSize()) throw Exception("Feature vector size should be the same" , __FILE__, __LINE__);
00239   unsigned long nbDistrib=model1.getDistribCount();
00240   if (nbDistrib!=model2.getDistribCount()) throw Exception("Number of components should be the same" , __FILE__, __LINE__);
00241   for (unsigned long idx=0;idx<nbDistrib;idx++){
00242     DistribGD & d1=model1.getDistrib(idx);
00243     DistribGD & d2=model2.getDistrib(idx);
00244     DistribGD & dr=result.getDistrib(idx);
00245     double totOcc1=nbFrameM1*model1.weight(idx);
00246     double totOcc2=nbFrameM2*model2.weight(idx);
00247     for (unsigned long c=0;c<vectSize;c++){
00248       dr.setMean(((d1.getMean(c)*totOcc1)+(d2.getMean(c)*totOcc2))/(totOcc1+totOcc2),c);
00249       dr.setCov(((d1.getCov(c)*totOcc1)+(d2.getCov(c)*totOcc2))/(totOcc1+totOcc2),c);// TO BE CHANGED !!!!!!!
00250     }
00251     dr.computeAll();
00252     result.weight(idx)=((model1.weight(idx)*nbFrameM1)+(model2.weight(idx)*nbFrameM2))/(nbFrameM1+nbFrameM2);
00253   }
00254 }
00255 
00256 // gaussian/mixture fusion using less likelihood loss criterion
00257 void gaussianFusion(const DistribGD &g1,double w1,const DistribGD & g2,double w2, DistribGD &res,double &w)
00258 {
00259  unsigned long vectSize = g1.getVectSize();
00260  double a1=w1/(w1+w2);
00261  double a2=1.0-a1;
00262  for (unsigned long k=0;k<vectSize;k++)
00263  {
00264   double d=g1.getMean(k)-g2.getMean(k);
00265   res.setCov(a1*g1.getCov(k)+a2*g2.getCov(k)+a1*a2*d*d,k);
00266   res.setMean((a1*g1.getMean(k))+(a2*g2.getMean(k)),k);
00267  }
00268  res.computeAll();
00269  w=w1+w2;
00270 }
00271 void mixtureFusion(const MixtureGD &mixt,DistribGD &res,double &wres){
00272   unsigned long distribCount = mixt.getDistribCount();
00273   
00274   DistribGD& tmp=mixt.getDistrib(0);
00275   double wtmp=mixt.weight(0);
00276   // used only for monocomponent mixture
00277   res=tmp; 
00278   wres=wtmp;
00279   for (unsigned long i=1;i<distribCount;i++){
00280    gaussianFusion(mixt.getDistrib(i),mixt.weight(i),res,wtmp,res,wres);
00281    wtmp=wres;
00282   }     
00283 }
00284 // normalizeMixture() normmalizes  the mixture to fit
00285 // the data distriobution
00286 // Usually used with a mean=0, cov=1 distribution
00287 void normalizeMixture(MixtureGD &mixt,const DoubleVector &meanSignal,const DoubleVector &covSignal,bool zeroOne,
00288                       unsigned long nbIt, bool meanOnly,Config &config){
00289   unsigned long vectSize = mixt.getVectSize();
00290   unsigned long distribCount = mixt.getDistribCount();
00291   double wtmp;
00292   MixtureServer ms(config);
00293   DistribGD &tmp=ms.createDistribGD();
00294   for (unsigned long it=0;it<nbIt;it++){ // NbIt used only for mean only option
00295     mixtureFusion(mixt,tmp,wtmp); // Compute in tmp the mono gaussian ML corresponding to the initial mixture
00296     for (unsigned long c=0;c<distribCount;c++){ // normalize the components
00297       DistribGD &d=mixt.getDistrib(c);
00298       for (unsigned long i=0;i<vectSize;i++){
00299                 double newMean=d.getMean(i)-tmp.getMean(i);
00300                 newMean/=sqrt(tmp.getCov(i));
00301                 if (!zeroOne) {// the target is not N(m=0,std=1){
00302                         newMean*=covSignal[i];
00303                         newMean+=meanSignal[i];
00304                 }
00305                 d.setMean(newMean,i);
00306                 if (!meanOnly){
00307                         double newCov=d.getCov(i)/tmp.getCov(i);
00308                         if (zeroOne==false) newCov*=covSignal[i]; // the target is not N(m=0,std=1)
00309                         d.setCov(newCov,i);
00310                 }
00311       }
00312       d.computeAll();
00313     }
00314   }
00315 }
00316 void normalizeMixture(MixtureGD &mixt,const DoubleVector &meanSignal,const DoubleVector &covSignal,bool zeroOne,TrainCfg &trainCfg,Config & config){
00317   normalizeMixture(mixt,meanSignal,covSignal,zeroOne,trainCfg.getNormalizeModelNbIt(),trainCfg.getNormalizeModelMeanOnly(),config);
00318 }
00319 void normalizeMixture(MixtureGD &mixt,const DoubleVector &meanSignal,const DoubleVector covSignal,bool zeroOne,Config &config){
00320   TrainCfg trainCfg(config);
00321   normalizeMixture(mixt,meanSignal,covSignal,zeroOne,trainCfg,config);
00322 }
00323 
00324 // for compatibility reasons only, same function but the target is always D(mean=0,std=1)
00325 void normalizeMixture(MixtureGD &mixt,TrainCfg &trainCfg,Config &config){
00326   DoubleVector fake1,fake2;
00327   normalizeMixture(mixt,fake1,fake2,true,trainCfg,config);
00328 }
00329 void normalizeMixture(MixtureGD &mixt,Config &config){
00330   TrainCfg trainCfg(config);
00331   DoubleVector fake1,fake2;
00332   normalizeMixture(mixt,fake1,fake2,true,trainCfg,config);
00333 }
00334 void normalizeMixture(MixtureGD &mixt,MAPCfg &mapCfg,Config &config){
00335   DoubleVector fake1,fake2;
00336   normalizeMixture(mixt,fake1,fake2,true,mapCfg.getNormalizeModelNbIt(),mapCfg.getNormalizeModelMeanOnly(),config);
00337 }
00338 double likelihoodLoss(const DistribGD &g1,double w1,const DistribGD & g2,double w2)
00339 {
00340   unsigned long vectSize = g1.getVectSize();
00341   double a1=w1/(w1+w2);
00342   double a2=1.0-a1;
00343   double d1=1.0;
00344   double d2=1.0;
00345   for (unsigned long k=0;k<vectSize;k++){
00346     double d=g1.getMean(k)-g2.getMean(k);
00347     double var=a1*g1.getCov(k)+a2*g2.getCov(k)+a1*a2*d*d;
00348     d1*=var/g1.getCov(k);
00349     d2*=var/g2.getCov(k);       
00350   }
00351   return (0.5*(w1*log(d1)+w2*log(d2)));
00352 }
00353 
00354 // Bayesian Adaptation functions (MAP)
00355 //Direct Mean Only interpolation: constant apriori for each component
00356 void computeMAPConst(const MixtureGD& initModel, MixtureGD &client, MAPCfg &cfg)
00357 {
00358   unsigned long vectSize = initModel.getVectSize();
00359   unsigned long distribCount = initModel.getDistribCount();
00360   String Id = "tmp";
00361   Config config;
00362   MixtureServer ms(config);
00363   MixtureGD & tmp=ms.duplicateMixture(initModel,DUPL_DISTRIB);
00364   if (cfg.getMeanAdapt()){
00365     double alpha=cfg.getMeanAlpha();
00366     for ( unsigned long indC=0; indC < distribCount; indC++) {
00367       DistribGD& t = tmp.getDistrib(indC);            // A  priori data for a component (from initModel model)
00368       DistribGD& c  = client.getDistrib(indC);        // Estimate statistics for the component
00369       for (unsigned long coef=0;coef<vectSize;coef++){
00370         double res=(alpha*t.getMean(coef)) +((1-alpha)*c.getMean(coef));
00371         t.setMean(res, coef);
00372       }
00373     }
00374   }
00375   if (cfg.getVarAdapt()){
00376     //    double alpha=cfg.varAlpha();
00377     // TODO
00378   } 
00379   if (cfg.getWeightAdapt()){
00380     //double alpha=cfg.weightAlpha();
00381     // TODO
00382   } 
00383   client=tmp;       
00384 }
00385 /************************************************************
00386 * Calcul MAP avec une constante
00387 * 
00388 * Origine : Corinne Fredouille
00389 ************************************************************/
00390 void computeMAPConst2(const MixtureGD& initModel, MixtureGD &client,MAPCfg &cfg )
00391 {
00392   unsigned long vectSize = initModel.getVectSize();
00393   unsigned long distribCount = initModel.getDistribCount();
00394   String Id = "tmp";
00395   Config config;
00396   MixtureServer ms(config);
00397   MixtureGD & tmp=ms.duplicateMixture(initModel,DUPL_DISTRIB);
00398   //MixtureGD tmp(Id,vectSize,distribCount);
00399   //tmp=initModel;
00400   if (cfg.getMeanAdapt()){
00401     double alpha=cfg.getMeanAlpha();
00402     for ( unsigned long indC=0; indC < distribCount; indC++) {
00403       DistribGD& t = tmp.getDistrib(indC); // A  priori data for a component (from initModel model)
00404       DistribGD& c  = client.getDistrib(indC);  // Estimate statistics for the component
00405       for (unsigned long coef=0;coef<vectSize;coef++){
00406         double res=((alpha*tmp.weight(indC)*t.getMean(coef)) +
00407                     ((1-alpha)*client.weight(indC)*c.getMean(coef)))/(tmp.weight(indC)*alpha+client.weight(indC)*(1-alpha));
00408         t.setMean(res, coef);
00409       }
00410     } 
00411   }
00412   if (cfg.getVarAdapt()){
00413     //    double alpha=cfg.varAlpha();
00414     // TODO
00415   }   
00416   if (cfg.getWeightAdapt()){
00417     //double alpha=cfg.weightAlpha();
00418     // TODO
00419   }
00420   client=tmp;       
00421 }
00422 
00423 void copyMean(MixtureGD & mixtS, MixtureGD & mixtD){
00424   for ( unsigned long indC=0; indC <mixtS.getDistribCount(); indC++) {
00425     DistribGD& s = mixtS.getDistrib(indC);                 
00426     DistribGD& d = mixtD.getDistrib(indC);             
00427     for (unsigned long coef=0;coef<mixtS.getVectSize();coef++)
00428       d.setMean(s.getMean(coef), coef);;
00429     }
00430   mixtD.computeAll(); 
00431 }
00432 void copyVar(MixtureGD & mixtS, MixtureGD & mixtD){
00433   for ( unsigned long indC=0; indC <mixtS.getDistribCount(); indC++) {
00434     DistribGD& s = mixtS.getDistrib(indC);                 
00435     DistribGD& d = mixtD.getDistrib(indC);             
00436     for (unsigned long coef=0;coef<mixtS.getVectSize();coef++)
00437       d.setCov(s.getCov(coef), coef);;
00438     }
00439   mixtD.computeAll(); 
00440 }
00441 void copyWeight(MixtureGD & mixtS, MixtureGD & mixtD){
00442   for ( unsigned long indC=0; indC <mixtS.getDistribCount(); indC++) 
00443     mixtD.weight(indC)=mixtS.weight(indC);
00444 }
00445 
00446 // Classical LIMSI or MIT mean only MAP adaptation
00447 void computeMAPOccDep(const MixtureGD& initModel, MixtureGD &client, MAPCfg &cfg,double frameCount)
00448 {
00449   unsigned long vectSize = initModel.getVectSize();
00450   unsigned long distribCount = initModel.getDistribCount();
00451   if (verbose) cfg.showConfig();
00452   // TODO : suppress the need of a temporary mixture server
00453   Config config;
00454   MixtureServer ms(config);
00455   MixtureGD & tmp=ms.duplicateMixture(initModel,DUPL_DISTRIB);
00456   //
00457   if ((cfg.getMeanAdapt()) || (cfg.getVarAdapt()))
00458     for ( unsigned long indC=0; indC < distribCount; indC++) {
00459       DistribGD& t = tmp.getDistrib(indC);                  // A  priori data for a component (from initModel model)
00460       DistribGD& c = client.getDistrib(indC);               // Estimate statistics for the component
00461       DistribGD& w = initModel.getDistrib(indC);                // The initModel
00462       double alpha= (client.weight(indC)*frameCount);       // occupation for the component
00463       if (cfg.getMeanAdapt()){
00464         double alphaMean=alpha/(alpha+cfg.getMeanReg());                                          // weight for the component
00465         for (unsigned long coef=0;coef<vectSize;coef++){
00466           double res=((1-alphaMean)*w.getMean(coef)) +(alphaMean*c.getMean(coef));
00467           t.setMean(res, coef);
00468         }
00469       }
00470       if (cfg.getVarAdapt()){
00471         double alphaVar=alpha/(alpha+cfg.getVarReg());  
00472         for (unsigned long coef=0;coef<vectSize;coef++){
00473           double res=((1-alphaVar)*w.getCov(coef)) +(alphaVar*c.getCov(coef))
00474             +(((1-alphaVar)*alphaVar)*pow(w.getMean(coef)-c.getMean(coef),2));
00475           t.setCov(res, coef);
00476         }  
00477       }
00478     } 
00479   if (cfg.getWeightAdapt()){
00480     double sumWeight=0.0;
00481     for ( unsigned long indC=0; indC < distribCount; indC++) {
00482       double alpha= (client.weight(indC)*frameCount); 
00483       double alphaWeight=alpha/(alpha+cfg.getWeightReg());      
00484       tmp.weight(indC)=alphaWeight*client.weight(indC)+((1-alphaWeight)*initModel.weight(indC));
00485       sumWeight+=tmp.weight(indC);
00486     }
00487     for ( unsigned long indC=0; indC < distribCount; indC++) tmp.weight(indC)/=sumWeight;
00488   }
00489   tmp.computeAll();
00490   client=tmp;     
00491 }
00492 // Classical LIMSI or MIT mean only MAP adaptation but based on ML estimate of the training data
00493 void computeModelBasedMAPOccDep(const MixtureGD& initModel, MixtureGD &client, MAPCfg &cfg,double frameCount)
00494 {
00495   unsigned long vectSize = initModel.getVectSize();
00496   unsigned long distribCount = initModel.getDistribCount();
00497   if (verbose) {
00498     cout << "modelBased MAP Adaptation"<<endl;
00499     cfg.showConfig();
00500   }
00501   // TODO : suppress the need of a temporary mixture server
00502   Config config;
00503   MixtureServer ms(config);
00504   MixtureGD & tmp=ms.duplicateMixture(initModel,DUPL_DISTRIB);
00505 
00506   //
00507   if ((cfg.getMeanAdapt()) || (cfg.getVarAdapt()))
00508     for ( unsigned long indC=0; indC < distribCount; indC++) {
00509       DistribGD& t = tmp.getDistrib(indC);                  // A  priori data for a component (from initModel model)
00510       DistribGD& c = client.getDistrib(indC);               // Estimate statistics for the component (Full ML in this case)
00511       DistribGD& w = initModel.getDistrib(indC);            // The initModel
00512       double alpha= (client.weight(indC)*frameCount);       // occupation for the component
00513       if (cfg.getMeanAdapt()){
00514         double alphaMean=alpha/(alpha+cfg.getMeanReg());                                          // weight for the component
00515         for (unsigned long coef=0;coef<vectSize;coef++){
00516           double res=((1-alphaMean)*w.getMean(coef)) +(alphaMean*c.getMean(coef));
00517           t.setMean(res, coef);
00518         }
00519       }
00520       if (cfg.getVarAdapt()){
00521         double alphaVar=alpha/(alpha+cfg.getVarReg());  
00522         for (unsigned long coef=0;coef<vectSize;coef++){
00523           double res=((1-alphaVar)*w.getCov(coef)) +(alphaVar*c.getCov(coef))
00524             +(((1-alphaVar)*alphaVar)*pow(w.getMean(coef)-c.getMean(coef),2));
00525           t.setCov(res, coef);
00526         }  
00527       }
00528     } 
00529   if (cfg.getWeightAdapt()){
00530     double sumWeight=0.0;
00531     for ( unsigned long indC=0; indC < distribCount; indC++) {
00532       double alpha= (client.weight(indC)*frameCount); 
00533       double alphaWeight=alpha/(alpha+cfg.getWeightReg());      
00534       tmp.weight(indC)=alphaWeight*client.weight(indC)+((1-alphaWeight)*initModel.weight(indC));
00535       sumWeight+=tmp.weight(indC);
00536     }
00537     for ( unsigned long indC=0; indC < distribCount; indC++) tmp.weight(indC)/=sumWeight;
00538   }
00539   tmp.computeAll();
00540   client=tmp;     
00541 }
00542 // Main MAP functions
00543 void computeMAP(MixtureServer &ms,const MixtureGD& initModel,MixtureGD &client,unsigned long frameCount,Config &config)
00544 {
00545   MAPCfg cfg(config);                          // Get all the needed parameters in the config
00546   computeMAP(ms,initModel,client,frameCount,cfg);
00547 }
00548 void computeMAP(MixtureServer &ms,const MixtureGD& initModel,MixtureGD &client,unsigned long frameCount,MAPCfg &cfg)
00549 {
00550   if (debug) cfg.showConfig(cout);
00551   if (cfg.getMethod()=="MAPConst")
00552     computeMAPConst(initModel,client,cfg);
00553   else if (cfg.getMethod()=="MAPOccDep")
00554     computeMAPOccDep(initModel,client,cfg,frameCount);
00555   else if (cfg.getMethod()=="MAPConst2")
00556     computeMAPConst2(initModel,client,cfg);
00557   else if (cfg.getMethod()=="MAPModelBased")
00558     computeModelBasedMAPOccDep(initModel,client,cfg,frameCount);
00559  else cerr <<"mapAlgo["<<cfg.getMethod()<<"] unknown, No adaptation will be perform"<<endl; 
00560 }
00561 //-------------------------------------------------------------------------
00562 double setItParameter(double begin, double end, int nbIt, int it){
00563   if (nbIt<2) return begin;
00564   double itVal=((begin-end)/((double)nbIt-1));
00565   return begin-(itVal*it);
00566 }
00567 //-------------------------------------------------------------------------
00568 // varianceControl for GMM models (florring and ceiling)
00569 void varianceControl(MixtureGD& model,double flooring,double ceiling,const DoubleVector &covSignal)
00570 {
00571   unsigned long vectSize     = model.getVectSize();
00572   unsigned long distribCount = model.getDistribCount();
00573   unsigned long cptFlooring  = 0;
00574   unsigned long cptCeiling   = 0;
00575 
00576   for (unsigned long c=0; c<distribCount; c++){
00577     DistribGD& d = model.getDistrib(c); 
00578     for (unsigned long v=0; v<vectSize; v++){
00579       double cov = d.getCov(v); 
00580       if (cov <= (flooring*covSignal[v])) { cov = flooring*covSignal[v]; cptFlooring++; }
00581       if (cov >= (ceiling*covSignal[v]))  { cov = ceiling*covSignal[v];  cptCeiling++; }
00582       d.setCov(cov, v);
00583     } 
00584     d.computeAll();  
00585   }
00586   if (verbose) cout << " total variance flooring = " << cptFlooring
00587                     << " ceiling = " << cptCeiling << endl;
00588   
00589 }
00590  
00591 // **********************************************************************
00592 // Mixture Initialization stuff
00593 //***********************************************************************
00594 // cov and mean initialization
00595 unsigned long computeMeanCov(Config &config,FeatureServer **fsTab,SegCluster ** segTab,unsigned long nbStream,DoubleVector &mean,DoubleVector &cov){
00596   initialize01(fsTab[0]->getVectSize(),mean,cov); // Set the good size to mean and cov
00597   FrameAccGD frameAcc;
00598   for (unsigned long stream=0;stream<nbStream;stream++)
00599     accumulateStatFrame(frameAcc,*fsTab[stream],*segTab[stream],config);
00600   mean=frameAcc.getMeanVect(); 
00601   cov=frameAcc.getCovVect();
00602   unsigned long nbFrame= frameAcc.getCount();
00603   return nbFrame;
00604 }
00605 unsigned long computeMeanCov(Config &config,FeatureServer &fs,SegCluster &seg,DoubleVector &mean,DoubleVector &cov){
00606   initialize01(fs.getVectSize(),mean,cov); // Set the good size to mean and cov
00607   FrameAccGD frameAcc;
00608   accumulateStatFrame(frameAcc,fs,seg,config);
00609   mean=frameAcc.getMeanVect(); 
00610   cov=frameAcc.getCovVect();
00611   unsigned long nbFrame= frameAcc.getCount();
00612   return nbFrame;
00613 }
00614 void initialize01(unsigned long vectSize,DoubleVector &mean,DoubleVector &cov){
00615   for(unsigned long i=0;i<vectSize;i++){
00616     mean.addValue(0);
00617     cov.addValue(1);
00618   }
00619 }
00620 // Mixture initialisation, based on random picking of frames
00621 MixtureGD &mixtureInit(MixtureServer &ms,FeatureServer &fs,MixtureGD &world,
00622                        SegCluster &selectedSegments,const DoubleVector &globalCov, Config& config,TrainCfg & trainCfg)
00623 {
00624   unsigned long vectSize = world.getVectSize(); 
00625   unsigned long minimumLength=3;
00626   unsigned long maximumLength=7;
00627   if (config.existsParam("baggedMinimalLength")) minimumLength=config.getParam("baggedMinimalLength").toLong();
00628   if (config.existsParam("baggedMaximalLength")) maximumLength=config.getParam("baggedMaximalLength").toLong();
00629   if (verbose) cout <<"baggedMinimalLength["<< minimumLength<<"] MaximalLength["<<maximumLength<<"]"<<endl;
00630   unsigned long distribCount = world.getDistribCount(); 
00631   FrameAcc** frameAcc=new FrameAcc* [distribCount];             // Initialise the frame accumulator tab
00632   for (unsigned long indg=0;indg<distribCount;indg++) {         // for the component indg
00633     frameAcc[indg]= new FrameAccGD();                           // Create the accumulators
00634     frameAcc[indg]->reset();                                    // Reset it
00635   } ;
00636   double baggedProba=trainCfg.getBaggedFrameProbabilityInit()/distribCount;
00637   unsigned long nbBaggedIt=1;
00638   if (baggedProba>1){
00639     nbBaggedIt=(unsigned long) baggedProba+1;
00640     baggedProba/=nbBaggedIt;
00641   }
00642   for (unsigned long baggedIt=0;baggedIt<nbBaggedIt;baggedIt++){
00643     for(unsigned long indg=0;indg<distribCount;indg++){
00644       SegServer segServer;                                        // Create a local segment server 
00645       SegCluster & baggedFramesCluster=segServer.createCluster(1,"",""); // Create the cluster for describing the selected frames
00646       srand((indg+1)*(baggedIt+1)); 
00647       baggedSegments(selectedSegments,baggedFramesCluster,
00648                      baggedProba,minimumLength,maximumLength);
00649       accumulateStatFrame(*frameAcc[indg],fs,baggedFramesCluster,config); // Accumulate picked frames for each component
00650     }
00651   }
00652   for (unsigned long indg=0;indg<distribCount;indg++)  {        // For each component
00653     DistribGD& d = world.getDistrib(indg);                      // Get it
00654     DoubleVector mean=frameAcc[indg]->getMeanVect();            // Get the mean
00655     for (unsigned long c=0;c<vectSize;c++){                     // copy it
00656       d.setCov(globalCov[c], c);
00657       d.setMean(mean[c], c);
00658     }
00659     d.computeAll();
00660   }  
00661   world.equalizeWeights();                                      // set weight = 1/distribCount for each distrib 
00662   if (verbose){
00663     cout << "Initialize model"<<endl;
00664     for (unsigned long indg=0;indg<distribCount;indg++) 
00665       cout <<"Nb Frame for mean["<<indg<<"] init =["<<frameAcc[indg]->getCount()<<"]"<<endl;
00666   }
00667   for (unsigned long indg=0;indg<distribCount;indg++)           // Free the memory
00668     delete frameAcc[indg];
00669   delete [] frameAcc;
00670   return world;
00671 }
00672 
00673 
00674 // Mixture initialisation, based on random picking of frames
00675 // Multiple data frames
00676 MixtureGD &mixtureInit(MixtureServer &ms,FeatureServer **fsTab,SegCluster **segTab,double *weightTab,unsigned long nbStream,MixtureGD &world,
00677                        const DoubleVector &globalCov, Config& config,TrainCfg & trainCfg)
00678 {
00679   if (debug|| verbose) cout << "begin of mixtureInit"<<endl;    
00680   unsigned long minimumLength=3;
00681   unsigned long maximumLength=7;
00682   if (config.existsParam("baggedMinimalLength")) minimumLength=config.getParam("baggedMinimalLength").toLong();
00683   if (config.existsParam("baggedMaximalLength")) maximumLength=config.getParam("baggedMaximalLength").toLong();
00684   if (verbose) cout <<"baggedMinimalLength["<< minimumLength<<"] MaximalLength["<<maximumLength<<"]"<<endl;
00685   unsigned long vectSize = world.getVectSize(); 
00686   unsigned long distribCount = world.getDistribCount(); 
00687   FrameAcc** frameAcc=new FrameAcc* [distribCount];             // Initialise the frame accumulator tab
00688   for (unsigned long indg=0;indg<distribCount;indg++) {         // for the component indg
00689     frameAcc[indg]= new FrameAccGD();                           // Create the accumulators
00690     frameAcc[indg]->reset();                                    // Reset it
00691   }
00692   unsigned long nbTotalFrame=0;
00693   for (unsigned long stream=0;stream<nbStream;stream++)
00694     nbTotalFrame+=(unsigned long) ((double)totalFrame(*segTab[stream])*weightTab[stream]);
00695   double nbFrameToSelect=50;
00696   if (config.existsParam("nbFrameToSelect")) nbFrameToSelect=config.getParam("nbFrameToSelect").toLong();
00697   
00698   if (verbose) cout <<"mixtureInit, total frames with stream weighting["<<nbTotalFrame<<"] total frame to select by component["<<nbFrameToSelect<<"]"<<endl;                                                        
00699   // Init the bagged probablity vector : one probability by frame
00700   DoubleVector baggedProbaA(nbStream,nbStream);
00701   ULongVector baggedItA(nbStream,nbStream);
00702   for (unsigned long stream=0;stream<nbStream;stream++){         // For each input stream
00703       baggedProbaA[stream]=(nbFrameToSelect*weightTab[stream])/(double)totalFrame(*segTab[stream]);
00704       baggedItA[stream]=1;
00705       double baggedTmp=baggedProbaA[stream];
00706       while (baggedTmp>1){
00707                 baggedItA[stream]++;
00708                 baggedTmp/=baggedProbaA[stream]/baggedItA[stream];
00709         }
00710       baggedProbaA[stream]=baggedTmp;
00711   }
00712   if (debug || verbose) cout << "bagged proba init ok"<<endl;
00713   /*
00714   for (unsigned long stream=0;stream<nbStream;stream++){         // For each input stream
00715       for (unsigned long baggedIt=0;baggedIt<baggedItA[stream];baggedIt++){
00716                 if (debug || verbose) cout <<"Init Stream["<<stream<<"] Bagged by comp="<<baggedProbaA[stream]<<" It["<<baggedIt<<"]"<<endl;
00717                 // Initialise the array of bagged segment clusters, one by component
00718                 RefVector <SegCluster> baggedA(distribCount); // Will be deleted automatically at the end of each loop it
00719                 SegServer segServer; // Create a local segment server, one for all the bagged clusters
00720                 for (unsigned long indG=0;indG<distribCount;indG++)
00721                   baggedA.addObject(segServer.createCluster(indG,"",""),indG); // Create the cluster for describing the selected frames
00722                 // Compute the bagging - random selection, for all components
00723                 srand(((stream+1)*100)+(baggedIt+1)); // 100 to be sure to not have 2 equal init
00724                 baggedSegments(*segTab[stream],baggedA,baggedProbaA[stream],minimumLength,maximumLength);
00725                 // Accumulate the statistics
00726                 for(unsigned long indG=0;indG<distribCount;indG++){ // For each component
00727                         if (debug || verbose) cout << "AccumulateStat stream["<<stream<<"] component["<<indG<<"]"<<endl;
00728                 accumulateStatFrame(*frameAcc[indG],*fsTab[stream],baggedA[indG],config); // Accumulate picked frames for the component and the input stream
00729                 }
00730       }
00731   }*/
00732   for (unsigned long stream=0;stream<nbStream;stream++){         // For each input stream
00733       for (unsigned long baggedIt=0;baggedIt<baggedItA[stream];baggedIt++){
00734                 if (debug || verbose) cout <<"Init Stream["<<stream<<"] Bagged by comp="<<baggedProbaA[stream]<<" It["<<baggedIt<<"]"<<endl;
00735                 // Initialise the array of bagged segment cluster, who will contain all the segments for all the streams
00736                 SegServer segServer; // Create a local segment server, one for all the bagged clusters
00737             SegCluster & baggedSeg=segServer.createCluster(1,"",""); // Create the cluster for describing the selected frames
00738                 // Compute the bagging - random selection, for all components
00739                 srand(((stream+1)*100)+(baggedIt+1)); // 100 to be sure to not have 2 equal init
00740                 baggedSegments(*segTab[stream],baggedSeg,distribCount,baggedProbaA[stream],minimumLength,maximumLength);
00741                 // Accumulate the statistics
00742                 Seg* seg;                                                     // reset the reader at the begin of the input stream
00743         baggedSeg.rewind();      
00744                 while((seg=baggedSeg.getSeg())!=NULL)                  // For each of the selected segments
00745                 accumulateStatFrame(*frameAcc[seg->labelCode()],*fsTab[stream],seg,config);
00746       }
00747   }
00748   for (unsigned long indg=0;indg<distribCount;indg++)  {        // For each component
00749     DistribGD& d = world.getDistrib(indg);                      // Get it
00750     DoubleVector mean=frameAcc[indg]->getMeanVect();            // Get the mean
00751     for (unsigned long c=0;c<vectSize;c++){                     // copy it
00752       d.setCov(globalCov[c], c);
00753       d.setMean(mean[c], c);
00754     }
00755     d.computeAll();
00756   }  
00757   
00758   world.equalizeWeights();                                      // set weight = 1/distribCount for each distrib 
00759   if (verbose){
00760     cout << "Initialize model"<<endl;
00761     for (unsigned long indg=0;indg<distribCount;indg++) 
00762       cout <<"Nb Frame for mean["<<indg<<"] init =["<<frameAcc[indg]->getCount()<<"]"<<endl;
00763   }
00764   for (unsigned long indg=0;indg<distribCount;indg++)           // Free the memory
00765     delete frameAcc[indg];
00766   delete [] frameAcc;
00767   return world;
00768 }
00769 MixtureGD &mixtureInit(MixtureServer &ms,FeatureServer &fs,MixtureGD &world,
00770                        SegCluster &selectedSegments,const DoubleVector &globalCov, Config& config){
00771   TrainCfg trainCfg(config);
00772   return mixtureInit(ms,fs,world,selectedSegments,globalCov,config,trainCfg);
00773 }
00774 MixtureGD &mixtureInit(MixtureServer &ms,FeatureServer **fsTab, SegCluster **segTab,double *weightTab,unsigned long nbStream,MixtureGD &world,
00775                        const DoubleVector &globalCov, Config& config){
00776   TrainCfg trainCfg(config);
00777   return mixtureInit(ms,fsTab,segTab,weightTab,nbStream,world,globalCov,config,trainCfg);
00778 }
00779 
00780 
00781 
00782 //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
00783 //Compute the MLLR transformation for means of a input Model and store it in an output Model
00784 
00785 // remplacement de toutes les matrices carrées par des Matrices rectangulaires
00786 // Dimension de W (vectsize , vectsize+1)
00787 // Dimension de Z (vectsize, vectsize+1)
00788 // Dimension de G (vectsize +1 , vectsize +1) (en fait on a vectisze Matrices G : une par distribution)
00789 
00790 Matrix <double> computeMLLR (MixtureGD &inM,MixtureGD& outM,unsigned long frameCount, Config &config){
00791         StatServer ss(config);
00792 
00793 
00794 if(verbose)cout<<"MLLR begins"<<endl;
00795         unsigned long distribCount=inM.getDistribCount();               // number of gaussians in the Mixture   
00796         unsigned long vectSize= inM.getVectSize();                              // dimension of the gaussians
00797         Matrix <double> W (vectSize, vectSize+1);                               // MMLR transformation matrix 
00798         Matrix <double> Z(vectSize, vectSize+1);                                // matrix  (one unused colunn)
00799         W.setAllValues(0);
00800         Z.setAllValues(0);
00801         
00802         // Define and initialize the G matrices
00803         DoubleSquareMatrix **G;
00804         G=new DoubleSquareMatrix*[vectSize];
00805         for (unsigned i=0;i<vectSize;i++) {
00806                 G[i]= new DoubleSquareMatrix();
00807                 G[i]->setSize(vectSize+1);
00808                 G[i]->setAllValues(0);
00809                 }
00810         if(verboseLevel>=1 )cout<<"Initialization complete"<<endl<<"Begining the Statistic accumulation"<<endl;
00811 
00812         for (unsigned long j=0; j<distribCount;j++){
00813                 DistribGD & distri = inM.getDistrib(j);
00814                 DistribGD & distriMl = outM.getDistrib(j);
00815                 double occ=outM.weight(j)*frameCount;
00816                 DoubleVector mean(vectSize+1,1);
00817                 DoubleVector &cov=distri.getCovVect();
00818 
00819                 //Initialization of the mean doubleVector (offset and other values)
00820                 mean[0]=1;
00821                 mean.addValue(distri.getMeanVect());
00822 
00823                 // Compute the Z matrix
00824                 for (unsigned long p=0; p<vectSize;p++){
00825                         double occFrame=distriMl.getMean(p)*occ;
00826                         for (unsigned long q=0; q<vectSize+1;q++) 
00827                                 Z(p,q)+=occFrame*mean[q]/cov[p];
00828                 }
00829                 //Compute the G matrix
00830                 for (unsigned long p=0; p<vectSize;p++){
00831                         for (unsigned long q=0; q<vectSize+1; q++){     
00832                                 for (unsigned long r=0; r<vectSize+1; r++) (*G[p])(q,r) += occ*mean[q]*mean[r]/cov[p];
00833                         }
00834                 }
00835         }       
00836         
00837         if(verboseLevel >=1)cout<<"G and Z matrix calculated"<<endl;
00838         
00839         //Compute the W matrix using the G inverse and Z
00840         for (unsigned long l=0; l<vectSize;l++) {
00841                 DoubleSquareMatrix G_inv(vectSize+1);
00842                 (*G[l]).invert(G_inv);
00843                 for (unsigned long c=0; c<vectSize+1;c++) 
00844                         for( unsigned long k=0;k<vectSize+1;k++) 
00845                                 W(l,c) += G_inv(c,k)*Z(l,k);
00846                 
00847         }
00848         if(verboseLevel >= 1)cout<<"W complete"<<endl<<"Computing new means"<<endl;
00849         
00850         //Compute the mean vector of outModel
00851         for (unsigned long j=0; j<distribCount;j++){
00852                 DoubleVector meanOut(vectSize, vectSize);
00853                 DistribGD & distri = inM.getDistrib(j);
00854                 DoubleVector &mean= distri.getMeanVect();
00855                 for (unsigned long i=0;i<vectSize;i++) meanOut[i]=W(i,0);       //initialize the mean vector with the offset
00856                 for (unsigned long i=0;i<vectSize;i++) {
00857                         for (unsigned long k=0;k<vectSize;k++) meanOut[i]+=W(i,k+1)*mean[k];
00858                         }
00859                 outM.getDistrib(j).setMeanVect(meanOut);        //update the mean vector of the out Mixture
00860         }
00861         
00862         if(verbose) cout<<"MLLR finished, New Means computed"<<endl;
00863                 
00864         copyVar(inM, outM);
00865         copyWeight(inM,outM);
00866 
00867 return W;
00868 }
00869 
00870 
00871 // The main function for estimate a client model by bayesian adaptattion of a aprioriModel model
00872 // Using EM and MAP 
00873 void adaptModel(Config& config,StatServer &ss,MixtureServer &ms,FeatureServer &fs,SegCluster& selectedSegments,
00874                 MixtureGD &aprioriModel,MixtureGD &clientMixture,MAPCfg &mapCfg){ 
00875   if (verbose) mapCfg.showConfig();
00876   // if (verboseLevel>1) cout << "Mean LLK Init = " << meanLikelihood(ss,fs,clientMixture,selectedSegments,config)<< endl;    
00877   for (unsigned long trainIt=0; trainIt<mapCfg.getNbTrainIt(); trainIt++){    // Begin the initial adaptation loop (with bagged frames)
00878     MixtureStat &emAcc=ss.createAndStoreMixtureStat(clientMixture);             // Create a statistic accumulator using the curent model
00879     SegServer segServer;                                                      // Create a local segment server 
00880     SegCluster & baggedFramesCluster=segServer.createCluster(1,"","");        // Create the cluster for describing the selected frames
00881     baggedSegments(selectedSegments,baggedFramesCluster,mapCfg.getBaggedFrameProbability());
00882     emAcc.resetEM();
00883     srand(trainIt);
00884     double llkPreviousIt=accumulateStatEM(ss,fs,emAcc,baggedFramesCluster,config);// Accumulate the EM statistics
00885     clientMixture = emAcc.getEM();                                             // Get the EM estimate    
00886     unsigned long frameCount=(unsigned long) emAcc.getEMFeatureCount();
00887     llkPreviousIt=llkPreviousIt/(double) frameCount;
00888     if (verbose)cout <<"ML (partial) estimate it["<<trainIt<<"] (take care, it corresponds to the previous it,0 means init likelihood) = "
00889                      <<llkPreviousIt<<endl;
00890     if(mapCfg.getMethod()=="MLLR") {
00891             //DoubleSquareMatrix W=computeMLLR(aprioriModel,clientMixture,frameCount,config);                   //MLLR adaptation
00892             Matrix <double> W=computeMLLR(aprioriModel,clientMixture,frameCount,config);                        //MLLR adaptation
00893             //outputDSM(W,clientMixture,config) ;
00894             String MLLR_matrix = "MLLR_matrix.mat";
00895             W.save(MLLR_matrix, config);
00896      } 
00897     else {
00898                 computeMAP(ms,aprioriModel,clientMixture,frameCount,config);               // Bayesian Adaptation client=MAP(aprioriModel,client)
00899         }
00900     if (mapCfg.getNormalizeModel()) normalizeMixture(clientMixture,mapCfg,config);    // Normalize/fit the model if needed
00901     ss.deleteMixtureStat(emAcc);  
00902     if (verboseLevel>2) cout << "Likelihood on all frames= "<< meanLikelihood(ss,fs,clientMixture, selectedSegments,config) << endl;        
00903     }    
00904   if (verboseLevel>1) cout << "Final likelihood on all frames= "<< meanLikelihood(ss,fs,clientMixture, selectedSegments,config) << endl;                               
00905   if (debug) cout <<"adaptModel nb distrib:"<<ms.getDistribCount() <<"nb mixt:"<<ms.getMixtureCount()<<endl;
00906 }
00907 
00908 void adaptModel(Config& config,StatServer &ss,MixtureServer &ms,FeatureServer &fs,SegCluster& selectedSegments,
00909                 MixtureGD &aprioriModel,MixtureGD &clientMixture){ 
00910   MAPCfg mapCfg(config);
00911   adaptModel(config,ss,ms,fs,selectedSegments,aprioriModel,clientMixture,mapCfg);
00912 }
00913 
00914 
00915 //------------------------------------------------------------------------
00916 // ** New training algo based on a true EM/ML estimate of the training data before to apply MAP
00917 void modelBasedadaptModel(Config& config,StatServer &ss,MixtureServer &ms,FeatureServer &fs,SegCluster& selectedSegments,
00918                           MixtureGD &aprioriModel,MixtureGD &clientMixture, MixtureGD &initModel){
00919   MAPCfg mapCfg(config);
00920   if (verbose){
00921     cout <<"Model adaptation based on true EM/ML estimate of training data"<<endl;
00922     mapCfg.showConfig();
00923   }
00924   MixtureServer msTmp(config);
00925   MixtureGD & data=msTmp.duplicateMixture(initModel,DUPL_DISTRIB);
00926   
00927   unsigned long totalFrameCount=totalFrame(selectedSegments);
00928   //if (verboseLevel>1) cout << "Mean LLK Init = " << meanLikelihood(ss,fs,data,selectedSegments,config)<< endl;    
00929   for (unsigned long emIt=0; emIt<mapCfg.getNbEmIt(); emIt++){                 // begin the true EM/ML estimate of the adpatation data 
00930     MixtureStat &emAcc=ss.createAndStoreMixtureStat(data);                     // Create a statistic accumulator using the curent model
00931     SegServer segServer;                                                       // Create a local segment server
00932     SegCluster & baggedFramesCluster=segServer.createCluster(1,"","");         // Create the cluster for describing the selected frames
00933     baggedSegments(selectedSegments,baggedFramesCluster,mapCfg.getBaggedFrameProbability());
00934     emAcc.resetEM();
00935     double llkPreviousIt=accumulateStatEM(ss,fs,emAcc,baggedFramesCluster,config);// Accumulate the EM statistics
00936     data = emAcc.getEM();                                                         // Get the EM estimate         
00937     unsigned long frameCount=(unsigned long) emAcc.getEMFeatureCount();
00938     llkPreviousIt=llkPreviousIt/(double) frameCount;
00939     if (verbose)cout <<"ML (partial) estimate it["<<emIt<<"] (take care, it corresponds to the previous it,0 means init likelihood) = "
00940                      <<llkPreviousIt<<endl;
00941     ss.deleteMixtureStat(emAcc);
00942   }
00943   unsigned long modelNbComp =aprioriModel.getDistribCount();
00944   // Begin the estimation of the statistic using the EM/ML model of the adaptation data
00945   unsigned long vectSize=fs.getVectSize();                               // Complete log likelihood of the adaptation data given the apriori model
00946   for  (unsigned long idxModel=0;idxModel<modelNbComp;idxModel++){ // Initialize the client mixture
00947     DistribGD &c=clientMixture.getDistrib(idxModel);
00948     for (unsigned long idxC=0;idxC<vectSize;idxC++){
00949       c.setMean(0.00,idxC);
00950       c.setCov(0.00,idxC);
00951     }
00952   }
00953   DoubleVector apProbaTot(modelNbComp,modelNbComp); 
00954   apProbaTot.setAllValues(0.0);
00955   for (unsigned long idxData=0;idxData<data.getDistribCount();idxData++){
00956     if (debug) cout <<"Distrib Data["<<idxData<<"]"<<endl;
00957     DistribGD &d=data.getDistrib(idxData);
00958     double totLk=0.0;   // Likelihood of the current data component given the apriori model
00959     DoubleVector apProba(modelNbComp,modelNbComp); 
00960     apProba.setAllValues(0.0);
00961     for  (unsigned long idxModel=0;idxModel<modelNbComp;idxModel++){
00962       if (debug) cout <<"Distrib A Priori model["<<idxModel<<"]"<<endl;
00963       DistribGD &m=aprioriModel.getDistrib(idxModel);
00964       apProba[idxModel]=aprioriModel.weight(idxModel)*likelihoodGD(d,m);
00965       totLk+=apProba[idxModel]; 
00966     }
00967     for  (unsigned long idxModel=0;idxModel<modelNbComp;idxModel++){
00968       DistribGD &c=clientMixture.getDistrib(idxModel);
00969       apProba[idxModel]/=totLk;
00970       for (unsigned long idxC=0;idxC<vectSize;idxC++){
00971         c.setMean(c.getMean(idxC)+(d.getMean(idxC)*apProba[idxModel]*data.weight(idxData)),idxC);
00972         c.setCov(c.getCov(idxC)+((d.getMean(idxC)*d.getMean(idxC))*apProba[idxModel]*data.weight(idxData)),idxC);
00973       }
00974       apProbaTot[idxModel]+=apProba[idxModel]*data.weight(idxData);
00975     }
00976   }
00977   for (unsigned long idxModel=0;idxModel<modelNbComp;idxModel++){
00978     DistribGD &c=clientMixture.getDistrib(idxModel);
00979     for (unsigned long idxC=0;idxC<vectSize;idxC++){
00980       c.setMean(c.getMean(idxC)/apProbaTot[idxModel],idxC);
00981       //        c.setCov(c.getCov(idxC),idxC);
00982     }
00983   }
00984   for (unsigned long idxModel=0;idxModel<modelNbComp;idxModel++){
00985     DistribGD &c=clientMixture.getDistrib(idxModel);
00986     c.computeAll();
00987   }
00988   //
00989   computeMAP(ms,aprioriModel,clientMixture,totalFrameCount,config);                      // Bayesian Adaptation client=MAP(aprioriModel,client)
00990   if (mapCfg.getNormalizeModel()) normalizeMixture(clientMixture,mapCfg,config);    // Normalize/fit the model if needed 
00991   if (verboseLevel>2) cout << "Likelihood on all frames= "<< meanLikelihood(ss,fs,clientMixture, selectedSegments,config) << endl;       
00992   if (verboseLevel>1) cout << "Final likelihood on all frames= "<< meanLikelihood(ss,fs,clientMixture, selectedSegments,config) << endl;  if (debug) cout <<"adaptModel nb distrib:"<<ms.getDistribCount() <<"nb mixt:"<<ms.getMixtureCount()<<endl;  
00993 }
00994 //-------------------------------------------------------------------------
00995 void trainModel(Config& config,StatServer &ss,FeatureServer &fs,SegCluster& selectedSegments,
00996                          DoubleVector & globalMean,DoubleVector &globalCov,MixtureGD &world,TrainCfg &trainCfg){ 
00997   float varianceFlooring = (float)trainCfg.getInitVarFloor();
00998   float varianceCeiling  = (float)trainCfg.getInitVarCeil();   
00999   if (verbose) trainCfg.showConfig();
01000   if (verboseLevel>1) cout << "Train It : initial model: ll world = " <<  meanLikelihood(ss,fs,world,selectedSegments,config)<< endl;
01001   try{          
01002     for (unsigned long trainIt=0; trainIt<trainCfg.getNbTrainIt(); trainIt++){                           // Begin the initial EM iteration loop 
01003       MixtureStat& emAcc=ss.createAndStoreMixtureStat(world);             // Create a statistic accumulator using the init model
01004       // Set the variance control parameters
01005       varianceFlooring = (float)setItParameter(trainCfg.getInitVarFloor(),trainCfg.getFinalVarFloor(),trainCfg.getNbTrainIt(),trainIt);
01006       varianceCeiling  = (float)setItParameter(trainCfg.getInitVarCeil(),trainCfg.getFinalVarCeil(), trainCfg.getNbTrainIt(), trainIt);
01007       if (verbose) cout << "Train it["<<trainIt<<"], Variance floor["<<varianceFlooring
01008                         <<"] ceiling["<<varianceCeiling<<"]"<<endl; 
01009       SegServer segServer;                                        // Create a local segment server 
01010       SegCluster & baggedFramesCluster=segServer.createCluster(1,"",""); // Create the cluster for describing the selected frames
01011       srand(trainIt);    
01012       baggedSegments(selectedSegments,baggedFramesCluster,trainCfg.getBaggedFrameProbability());
01013       emAcc.resetEM();                                                                                    // EM stuff
01014       double llkPreviousIt=accumulateStatEM(ss,fs,emAcc,baggedFramesCluster,config);                        // Compute EM statistics
01015       llkPreviousIt=llkPreviousIt/(double) emAcc.getEMFeatureCount();
01016       world = emAcc.getEM();                                                                             // Get the EM estimate
01017       varianceControl(world,varianceFlooring,varianceCeiling,globalCov);
01018       if (trainCfg.getNormalizeModel()) normalizeMixture(world,config); 
01019       if (verbose) cout << "Partial Train it["<<trainIt<<"] (take care, it corresponds to the previous it,0 means init likelihood) ="<<llkPreviousIt<<" Nb Frames="<<emAcc.getEMFeatureCount()<<endl;
01020       if (verboseLevel>2) cout << "Train it["<<trainIt <<"] Complete LLK=[" << meanLikelihood(ss,fs,world,selectedSegments,config)<< "]"<<endl;       
01021       ss.deleteMixtureStat(emAcc);
01022     }
01023     if (verboseLevel>1) cout << " Final ll world = " << meanLikelihood(ss,fs,world,selectedSegments,config)<< endl;
01024   }
01025   catch (Exception& e){
01026     cout << e.toString() << endl;
01027   }
01028 }
01029 
01030 //-------------------------------------------------------------------------
01031 // stream version, should become the only one !!!
01032 void trainModelStream(Config& config,MixtureServer &ms,StatServer &ss,FeatureServer **fsTab,SegCluster** segTab,
01033                 double *weightTab,unsigned long nbStream,
01034                 DoubleVector & globalMean,DoubleVector &globalCov,MixtureGD* &world,TrainCfg &trainCfg){ 
01035   unsigned long initialDistribCount=world->getDistribCount();
01036   double varianceFlooring = trainCfg.getInitVarFloor();
01037   double varianceCeiling  = trainCfg.getInitVarCeil(); 
01038   unsigned long initRand=0; //initRand allows to run several TrainWorld using different set of (random) data
01039   if (config.existsParam("initRand")) initRand=config.getParam("initRand").toLong();  
01040   unsigned long minimumLength=3;
01041   unsigned long maximumLength=7;
01042   if (config.existsParam("baggedMinimalLength")) minimumLength=config.getParam("baggedMinimalLength").toLong();
01043   if (config.existsParam("baggedMaximalLength")) maximumLength=config.getParam("baggedMaximalLength").toLong();
01044   if (verbose) trainCfg.showConfig();
01045   if (verbose) cout <<"baggedMinimalLength["<< minimumLength<<"] MaximalLength["<<maximumLength<<"]"<<endl;
01046   if (verboseLevel>1) cout <<"LLK Initial model= " <<  meanLikelihood(ss,fsTab,segTab,nbStream,*world,config)<< endl;
01047   try{          
01048     for (unsigned long trainIt=0; trainIt<trainCfg.getNbTrainIt(); trainIt++){             // Begin the initial EM iteration loop;
01049       MixtureStat& emAcc=ss.createAndStoreMixtureStat(*world);                             // Create a statistic accumulator using the init model
01050       // Set the variance control parameters
01051       varianceFlooring = setItParameter(trainCfg.getInitVarFloor(),trainCfg.getFinalVarFloor(),trainCfg.getNbTrainIt(),trainIt);
01052       varianceCeiling  = setItParameter(trainCfg.getInitVarCeil(),trainCfg.getFinalVarCeil(), trainCfg.getNbTrainIt(), trainIt);
01053       if (verbose) cout << "Train it["<<trainIt<<"], Variance floor["<<varianceFlooring
01054                         <<"] ceiling["<<varianceCeiling<<"]"<<endl; 
01055       unsigned long nbTotalFrame=0;
01056       for (unsigned long stream=0;stream<nbStream;stream++) nbTotalFrame+=(unsigned long) ((double)totalFrame(*segTab[stream])*weightTab[stream]);
01057       double nbFrameToSelect=trainCfg.getBaggedFrameProbability()*nbTotalFrame;
01058       if (verbose) cout <<"total frames with stream weighting["<<nbTotalFrame<<"] total frame to select ["<<(unsigned long) nbFrameToSelect<<"]"<<endl;
01059       emAcc.resetEM();  
01060       double llkPreviousIt=0;
01061       for(unsigned long stream=0;stream<nbStream;stream++){
01062         unsigned long nbBaggedIt=1;
01063         double baggedProba=(nbFrameToSelect*weightTab[stream])/(double)totalFrame(*segTab[stream]);
01064         if (baggedProba>1){
01065           nbBaggedIt=(unsigned long) baggedProba+1;
01066           baggedProba/=nbBaggedIt;
01067         }
01068         for (unsigned long baggedIt=0;baggedIt<nbBaggedIt;baggedIt++){
01069           if (debug || verboseLevel) cout <<"Stream["<<stream<<"] Bagged="<<baggedProba<<endl;
01070           SegServer segServer;                                        // Create a local segment server 
01071           SegCluster & baggedFramesCluster=segServer.createCluster(1,"",""); // Create the cluster for describing the selected frames
01072       srand(((trainIt+1+initRand)*200)+(((stream+1)*20)+(baggedIt+1)));   
01073           baggedSegments(*segTab[stream],baggedFramesCluster,baggedProba,minimumLength,maximumLength);
01074           llkPreviousIt+=accumulateStatEM(ss,*fsTab[stream],emAcc,baggedFramesCluster,config);                        // Compute EM statistics
01075         }
01076       }
01077       llkPreviousIt=llkPreviousIt/(double) emAcc.getEMFeatureCount();
01078       (*world) = emAcc.getEM(); // Get the EM estimate
01079       varianceControl(*world,varianceFlooring,varianceCeiling,globalCov);
01080       if (trainCfg.getComponentReduction()){
01081         // Tableau dynamique instancié sans pointeur (ancien code)
01082         //bool selectCompA[world->getDistribCount()] TODO netoyage memoire
01083         bool * selectCompA = new bool[world->getDistribCount()];
01084 
01085         double diff=(initialDistribCount-trainCfg.getTargetDistribCount())/(double) trainCfg.getNbTrainIt();
01086         unsigned long nbTop=initialDistribCount-(unsigned long)((double)(trainIt+1)*diff);
01087         if (trainIt== (trainCfg.getNbTrainIt()-1)) nbTop=trainCfg.getTargetDistribCount();
01088         if (nbTop<world->getDistribCount())
01089           {
01090             if (verbose) cout <<"target number of d:"<<nbTop<<endl;
01091             unsigned long nbOutputDistrib=selectComponent(selectCompA,nbTop,*world);
01092             if (verbose) cout <<" suppress distrib nb initial:"<<world->getDistribCount()<<" nb final :"<<nbOutputDistrib;
01093             MixtureGD &outputM=ms.createMixtureGD(nbOutputDistrib);
01094             double totWeights=reduceModel(selectCompA,*world,outputM);
01095             if (verbose) cout <<" Total weights["<<totWeights<<"] normalized to 1"<<endl;
01096             normalizeWeights(outputM);
01097             world=&outputM;
01098           }
01099       }
01100       if (trainCfg.getNormalizeModel()) normalizeMixture(*world,trainCfg,config);       
01101  
01102       if (verbose) cout << "Partial Train it["<<trainIt<<"] (take care, it corresponds to the previous it,0 means init likelihood) ="<<llkPreviousIt<<" Nb Frames="<<(unsigned long) emAcc.getEMFeatureCount()<<endl;
01103        if (verboseLevel>2) cout << "Train it["<<trainIt <<"] Complete LLK=[" << meanLikelihood(ss,fsTab,segTab,nbStream,*world,config)<< "]"<<endl;    
01104       ss.deleteMixtureStat(emAcc);
01105 
01106     }
01107     if (verboseLevel>1) cout << " Final ll world = " << meanLikelihood(ss,fsTab,segTab,nbStream,*world,config)<< endl;
01108   }
01109   catch (Exception& e){
01110     cout << e.toString() << endl;
01111   }
01112 }
01113 void trainModel(Config& config,StatServer &ss,FeatureServer &fs,SegCluster& selectedSegments,
01114                          DoubleVector & globalMean,DoubleVector &globalCov,MixtureGD &world){
01115   TrainCfg trainCfg(config);
01116   trainModel(config,ss,fs,selectedSegments,globalMean,globalCov,world,trainCfg) ;
01117 }
01118 void trainModel(Config& config,MixtureServer &ms,StatServer &ss,FeatureServer **fsTab,SegCluster** segTab,double *weightTab,unsigned long nbStream,
01119                 DoubleVector & globalMean,DoubleVector &globalCov,MixtureGD* &world){ 
01120   TrainCfg trainCfg(config);
01121   if (verbose) trainCfg.showConfig();
01122   trainModelStream(config,ms,ss,fsTab,segTab,weightTab,nbStream,globalMean,globalCov,world,trainCfg);
01123 }
01124 #endif //!defined(ALIZE_TrainTools_cpp)