SpkAdapt.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_SpkAdapt_cpp)
00056 #define ALIZE_SpkAdapt_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 "SpkAdapt.h"
00065 #include "FileInfo.h"
00066 #include "UnsupervisedTools.h"
00067 
00068 using namespace alize;
00069 using namespace std;
00070 
00071 /************************************************************************/
00072 /*
00073 UNSUPERVISED ADAPTATION PROCESS
00074 
00075 NEED THE TRAIN TARGET CONFIG FILE + NDX
00076 NEED A CONFIG FOR TRIALS ADAPTATION (SEE CONFIG CHECKER) + NDX, SYNTAX (LINE  =     MODEL GENDER, TRIAL)  
00077 -- IF WMAPGMM MODE : NEED TWO GMM OF SCORES
00078 -- IF SCORES BY CLIENT MODE : NEED A SET OF TAR GMM LEARNT ON ANOTHER DATABASE AND 
00079 A SET OF NON GMM LEARN BY COMPUTING LLR OF SOME IMPOSTORS ON CLIENTS MODELS
00080 -- SEGMODE NOT DEBUGGED
00081 
00082 FAST MODE : FAST LLR GIVES ABOUT THE SAME RESULTS AS CLASSICAL LLR (10-3)
00083 
00084 */
00085 /*************************************************************************/
00086 
00087 
00088 
00089 
00090 int TrainTargetAdapt(Config & config, Config & configTest)
00091 {
00092    //LOAD PARAM FROM CONFIG
00093   String outputLLRFileName  =     config.getParam("outputLLRFilename");
00094   ofstream outLLR(outputLLRFileName.c_str(), ios::out | ios::trunc);
00095   String fullFileName,fullFileNameTrain;
00096         
00097   // CHOICE OF THE PROTOCOL BATCH OR NIST
00098    bool NIST  =     true; 
00099   if (config.existsParam("NISTprotocol"))        
00100     NIST  =     config.getParam("NISTprotocol").toBool();
00101   
00102   bool becomeCurrent  =     true,
00103        selected       =     true;
00104   
00105   //LOAD LISTS
00106   String inputClientListFileName    =     config.getParam("targetIdList");
00107   String inputTestsListFileName     =     config.getParam("testsIdList");
00108   String inputWorldFilename         =     config.getParam("inputWorldFilename");
00109   String outputSERVERFilename       =     config.getParam("mixtureServer");
00110   
00111   double LLRRatio   =     0.0, 
00112          LLRRatio2  =     0.0,
00113          LLRTrain   =     0.0;
00114          //previousLLR =    -10000;        //NEW
00115   
00116   //FOR LOGISTIC REGRESSION ON SCORES
00117   bool regress  =     false;
00118   if (configTest.existsParam("REGRESS"))
00119     regress  =     configTest.getParam("REGRESS").toBool();
00120   
00121   //SIMPLE WMAP CURVE (1 GAUSSIAN)
00122   bool wmap  =     false;
00123   if (configTest.existsParam("WMAP"))
00124     wmap  =     configTest.getParam("WMAP").toBool();
00125   
00126   //WMAP USING GMM
00127   bool wmapGmm  =     false;
00128   if (configTest.existsParam("WMAPGMM"))
00129     wmapGmm  =     configTest.getParam("WMAPGMM").toBool();
00130   
00131   //FAST MODE USE TOP DISTRIB FOR LLR COMPUTATION AND FUSEMODEL FOR UPDATE OF MODEL
00132   bool Fast  =     false;
00133   if (configTest.existsParam("FAST"))
00134     Fast  =     configTest.getParam("FAST").toBool();
00135   int countTests;
00136   bool saveEmptyModel  =     false;
00137   if (config.existsParam("saveEmptyModel"))
00138     saveEmptyModel  =     config.getParam("saveEmptyModel").toBool();
00139   
00140   //TNORM SCORES, USES TNORM SCORES FOR WMAP
00141   bool tnorm  =     false;
00142   if (configTest.existsParam("TNORM"))
00143     tnorm  =     configTest.getParam("TNORM").toBool();
00144   
00145   //ZNORM SCORES, USES TNORM SCORES FOR WMAP
00146   bool znorm  =  false, ztnorm = false;
00147   if (configTest.existsParam("ZNORM"))
00148     znorm  =     configTest.getParam("ZNORM").toBool();
00149   
00150   //SUPERVISED MODE, NEED A LIST OF TRUE TARGET CLIENT (targetTests)
00151   bool oracle  =     false;
00152   if (configTest.existsParam("Oracle"))
00153     oracle  =     configTest.getParam("Oracle").toBool();
00154   
00155   //CROSS VALIDATION OF TEST DATA
00156   bool cross  =     false;
00157   if (configTest.existsParam("CrossValid"))
00158     cross  =     configTest.getParam("CrossValid").toBool();
00159   
00160   //USES A SCORES FILE FOR LLR OF TESTS ON CLIENT MODEL, A WAY OF USING ANOTHER DECISION SYSTEM
00161   String inputResFilename;
00162   bool fromResFile  =     false;
00163   if (configTest.existsParam("FromResFile")){
00164     fromResFile  =     configTest.getParam("FromResFile").toBool();
00165     inputResFilename =     configTest.getParam("InputResFilename");
00166   }
00167   //NEEDEED FOR STORING A GMM AFTER EACH ADAPTATION ITERATION
00168   bool saveAfterIt  =     false;
00169   if (configTest.existsParam("SaveAfterIt"))
00170     saveAfterIt  =     configTest.getParam("SaveAfterIt").toBool();
00171   
00172   //GMM OF TAR AND NON FOR EACH CLIENT INSTEAD OF GLOBAL ONES  
00173   bool ScoresByTarget  =     false;
00174   if (configTest.existsParam("ScoresByTarget"))
00175     ScoresByTarget  =     configTest.getParam("ScoresByTarget").toBool();
00176   
00177    //TRY USING TRAIN DATA TO CONTROLL ADAPTATION
00178   bool assess  =     false;
00179   if (configTest.existsParam("Assess"))
00180     assess  =     configTest.getParam("Assess").toBool();
00181   
00182   //FIXED PRIORS FROM THE CONFIG OR UPDATE DURING PROCESSING
00183      bool fixedPriors  =     true;
00184    if (configTest.existsParam("fixedPriors"))
00185     fixedPriors  =     configTest.getParam("fixedPriors").toBool(); 
00186    
00187   //USE MAP ADAPTATION FOR CLIENT AND TESTS MODELS INSTEAD OF ML.
00188    bool map  =     false;
00189    if (configTest.existsParam("MAP"))
00190     map  =     configTest.getParam("MAP").toBool(); 
00191    
00192    unsigned long resetNb =    0;
00193    if (configTest.existsParam("ResetNbAdapt"))
00194     resetNb  =     configTest.getParam("ResetNbAdapt").toLong(); 
00195    
00196   //To stock Tnorm parameters, not need to be declared if Tnorm =    false!
00197   ObjectRefVector stockTnorm; 
00198    
00199    //To stock Znorm parameters, not need to be declared if Znorm =    false!
00200   ObjectRefVector stockZnorm;
00201    
00202   //NEW //To stock the LK for the client models with the impostor data !!!!!!!CAPACITE A CHANGER!!!!!!!!
00203   DoubleVector decision;//,decisionOnlyTests; 
00204    
00205   DoubleVector tmp;        //For NIST protocol 
00206   DoubleVector NbFramesSelected, NbFramesSelectedForTests;
00207   ObjectRefVector FeatServ;    //To stock the feature servers
00208   ObjectRefVector SegServ;    //To stock the seg clusters 
00209    
00210   if (tnorm)
00211   {                //load Tnorm parameters
00212       String testFile  =     (config.getParam("impScoreFile"));
00213       String TestNames  =     (config.getParam("testNames"));
00214       loadTnormParam(TestNames, testFile, stockTnorm, config);
00215   }
00216   
00217   String impCohortFile ;
00218   if(znorm) {
00219       impCohortFile  =     (configTest.getParam("impCohortFile"));
00220   }
00221   
00222   // label for selected frames - Only the frames associated with this label, in the label files, will be used
00223   bool fixedLabelSelectedFrame  =     true;
00224   String labelSelectedFrames;
00225   // the ID of each speaker is used as labelSelectedFrame ?
00226   if (config.existsParam("useIdForSelectedFrame"))    
00227     fixedLabelSelectedFrame  =     (config.getParam("useIdForSelectedFrame")  ==     "false");
00228   
00229   if (fixedLabelSelectedFrame)    // the label is decided by the command line and is unique for the run
00230     labelSelectedFrames  =     config.getParam("labelSelectedFrames");
00231   
00232   debug  =     config.getParam_debug();
00233   if (config.existsParam("verbose"))
00234     verbose  =     true;
00235   else
00236     verbose  =     false;
00237   
00238   // read the Id + filenames for each client
00239   XList inputClientList(inputClientListFileName, config);    
00240   XLine *linep;
00241   inputClientList.getLine(0);
00242   XList inputTestsList(inputTestsListFileName, configTest);
00243   XLine *lineTests;
00244   inputTestsList.getLine(0);
00245   MixtureServer ms(config);
00246   
00247   //CREATE CONFIG + MIXTURE SERVER FOR GMM OF SCORES
00248   Config configScores(config);    
00249   configScores.setParam("vectSize", "1");
00250   configScores.setParam("mixtureDistribCount", configTest.getParam("mixtureDistribCountForGMMScores"));
00251   MixtureServer msScores(configScores);
00252   StatServer ss(config, ms);
00253   StatServer ssScores(configScores, msScores);
00254   
00255   XLine testsToCompute;//,onlyTests;//NEW
00256   
00257   if (verbose)
00258     cout << "TrainTarget - Load world model [" << inputWorldFilename << "]"  << endl;
00259   
00260   MixtureGD & world  =     ms.loadMixtureGD(inputWorldFilename);
00261   
00262   // load TAR and NON GMM
00263   MixtureGD & non  =        msScores.createMixtureGD();
00264   MixtureGD & tar  =        msScores.createMixtureGD();
00265    
00266   if(!ScoresByTarget){
00267     non   =      msScores.loadMixtureGD(configTest.getParam("NONScoresModel"));
00268     tar   =      msScores.loadMixtureGD(configTest.getParam("TARScoresModel"));
00269   }
00270 
00271   
00272   /****************ADAPTED TNORM STUFF*********************/
00273  double shift =    0.0;//used for TNorm shift computation
00274  bool tnormAdapt  =     false;
00275  if (configTest.existsParam("TnormAdapt"))
00276     tnormAdapt  =     configTest.getParam("TnormAdapt").toBool(); 
00277  Matrix <double> tnormA;
00278  if(tnormAdapt && tnorm) {    //compute Adaptative TNORM
00279     //load Matrix of LLRs
00280     tnormA.load(configTest.getParam("TnormAMatrix"),configTest);
00281  }
00282  unsigned long session_nb =    1;
00283  /****************END ADAPTED TNORM STUFF*********************/  
00284  
00285  String idAux  =     (ms.createMixtureGD(world.getDistribCount())).getId();
00286  String idTmp  =     (ms.createMixtureGD(world.getDistribCount())).getId();
00287 
00288   // *********** Target loop ***************** 
00289        // linep gives the XLine with the Id of a given client and the list of files
00290   while ((linep  =     inputClientList.getLine()) !=     NULL)
00291   {   
00292       //   load needed for each client because of the mixture server reset          
00293       MixtureGD & world  =     ms.getMixtureGD(ms.getMixtureIndex(inputWorldFilename));    
00294       MixtureGD & tmpMixture  =     ms.getMixtureGD(ms.getMixtureIndex(idAux));
00295       MixtureGD & auxMixture  =     ms.getMixtureGD(ms.getMixtureIndex(idTmp));
00296       // Get the Client ID (id)     
00297       String *id  =     linep->getElement();   
00298       // Get the list of feature file for the client (end of the line)      
00299       XLine featureFileListp  =     linep->getElements();  
00300             
00301       if (verbose)
00302           cout << "Train model [" << *id << "]" << endl;
00303       
00304       if (!fixedLabelSelectedFrame)
00305       {            // the ID is used as label for selecting the frame
00306           labelSelectedFrames  =     *id;
00307           if (debug)
00308               cout << *id << " is used for label selected frames" << endl;
00309       }
00310       //STUFF FOR TRAIN DATA
00311       // Reading the features (from several files)
00312       FeatureServer & fs          =     *new FeatureServer(config, featureFileListp);
00313       
00314       // Create the segment server for managing the segments/clusters
00315       SegServer & segmentsServer  =     *new SegServer();   
00316       
00317       // Create the lable server, for indexing the segments/clusters
00318       LabelServer labelServer;
00319       
00320       // Reading the segmentation files for each feature input file
00321       initializeClusters(featureFileListp, segmentsServer, labelServer, config);
00322       
00323       // Verify if the segments ending before the end of the feature files...
00324       verifyClusterFile(segmentsServer, fs, config); 
00325       
00326       MixtureGD & clientMixture  =     ms.duplicateMixture(world, DUPL_DISTRIB);
00327       //MixtureGD & mixtureOnlyTests  =     ms.duplicateMixture(world, DUPL_DISTRIB);//NEW
00328       MixtureGD & clientMixtureEM  =     ms.duplicateMixture(world, DUPL_DISTRIB);
00329       
00330       // Get the index of the cluster with in interest audio segments
00331       long codeSelectedFrame  =     labelServer.getLabelIndexByString(labelSelectedFrames);    
00332       if (codeSelectedFrame  ==     -1)
00333       {            // No data for this model !!!!!!!!!!!!!!
00334           cout << " WARNING - NO DATA FOR TRAINING [" << *id << "]";
00335       }
00336       else
00337       {
00338           // Gives the cluster of the selected/used segments                                   
00339           SegCluster & selectedSegments  =     segmentsServer.getCluster(codeSelectedFrame);    
00340           countTests  =     0;    //reset the counter of tests segments (  train data included)
00341           if (!Fast)
00342           {
00343               //add train data to objectrefvector
00344               FeatServ.addObject(fs);
00345               SegServ.addObject(selectedSegments);
00346           }
00347           
00348           adaptModel(config, ss, ms, fs, selectedSegments, world, clientMixture);
00349           if(!map){
00350               adaptModelEM(config, ss, ms, fs, selectedSegments, world, clientMixtureEM);
00351               ms.setMixtureId(clientMixtureEM, *id);
00352           }
00353           else ms.setMixtureId(clientMixture, *id);
00354                   
00355           testsToCompute.addElement(*id);
00356           
00357           //compute the LLR with the client train data and store it to compute probability
00358           fullFileNameTrain  =     getFullFileName(*id, configTest);
00359           
00360           //Fast LLR is not used for L(data train/ client model)
00361           //NO more needed if proba is fixed to 1, tweak to init LKVector
00362           LLRTrain  =     computeLLR(configTest,ss, fs, world, clientMixture, selectedSegments,fullFileNameTrain); 
00363           
00364           //L(data train/ client model) always the first element of the doublevector
00365           decision.addValue(LLRTrain);    
00366           countTests++;
00367           
00368           //stock the number of frames selected (used for fuseModels)
00369           if(!map) NbFramesSelected.addValue(SegClusterFrame(selectedSegments)); 
00370                   
00371           MixtureGD & SAVclientMixture  =      ms.duplicateMixture(clientMixture, DUPL_DISTRIB);
00372           
00373           /*
00374            MEMORY OF 2 MODELS, INIT  = train model
00375           */
00376           MixtureGD & clientMixture_2  =      ms.duplicateMixture(clientMixture, DUPL_DISTRIB);
00377           MixtureGD & clientMixture_3  =      ms.duplicateMixture(clientMixture, DUPL_DISTRIB);
00378           
00379           
00380           //If NonByTarget is set the global Non model is replaced by the non model idclient.non.gmm (should be created before) 
00381           if(ScoresByTarget){
00382               String TARListFilename  =     configTest.getParam("TARListFilename");
00383               non  =     msScores.loadMixtureGD(((*id)+".non"));
00384               if (verbose) cout << "load "<<(*id)+".non"<<" NON file"<<endl;
00385               String idTar  =     selectNearestTarModel(TARListFilename, fullFileNameTrain,configTest, ss, fs, world,  selectedSegments,ms);
00386               if (verbose) cout <<"TAR SELECTED : "<< idTar<<endl;
00387               tar  =     msScores.loadMixtureGD(((idTar)+".tar"));
00388           }
00389           
00390           //COMPUTE AND STORE THE TNORM PARAMETERS FOR THIS CLIENT MODEL
00391           if(znorm)
00392           {   if(tnorm && znorm) ztnorm = true;
00393               computeAndStoreZnormParam(ss, impCohortFile, (*id), clientMixture,stockZnorm, world, configTest, ztnorm, stockTnorm); 
00394           }
00395           
00396           /***********************************************************************************/
00397           /*******************************  ADAPTATION  PROCESS ******************************/
00398           /************!!!!!!INCLUDING THE CURRENT SEGMENT IS NOT PERFORMED !!!!!!!!!!!*******/
00399           /***********************************************************************************/
00400           shift =    0.0;
00401           // ***********  tests loop ***************** 
00402           while ((lineTests  =     inputTestsList.getLine()) !=     NULL)
00403           {
00404               //file format : column client model name, column gender, column tests in one word (i.e : toto_A)
00405               String *idclient  =     lineTests->getElement();
00406               if (*idclient  ==     *id)
00407               {        
00408                   MixtureGD & testMixtureEM   =     ms.duplicateMixture(world, DUPL_DISTRIB);
00409                       
00410                   // Get the Tests ID (id)
00411                   String & idTest             =     lineTests->getElement(2, becomeCurrent);
00412                       
00413                   // Get the list of feature file for the tests (end of the line)
00414                   XLine featureFileListTests  =     lineTests->getElements();    
00415                   
00416                   if (verbose)
00417                       cout << "Train model for test [" << idTest << "]" << endl;
00418                   
00419                   // the ID is used as label for selecting the frame
00420                   if (!fixedLabelSelectedFrame)
00421                   {        
00422                       labelSelectedFrames  =     idTest;
00423                       if (debug)
00424                           cout << idTest << " is used for label selected frames" << endl;
00425                   }
00426                   
00427                   //TEST DATA STUFF
00428                   FeatureServer & fsTests  =       *new FeatureServer(configTest, featureFileListTests);
00429             
00430                   // Create the segment server for managing the segments/clusters
00431                   SegServer & segmentsServerTests  =     *new SegServer();    
00432             
00433                   // Create the lable server, for indexing the segments/clusters
00434                   LabelServer labelServerTests; 
00435                   
00436                   // Reading the segmentation files for each feature input file
00437                   initializeClusters(featureFileListTests, segmentsServerTests, labelServerTests, configTest);
00438                   
00439                   // Verify if the segments ending before the end of the feature files...
00440                   verifyClusterFile(segmentsServerTests, fsTests, configTest);  
00441                   
00442                   // Get the index of the cluster with in interest audio segments
00443                   long codeSelectedFrame  =     labelServerTests.getLabelIndexByString(labelSelectedFrames);    
00444                   if (codeSelectedFrame  ==     -1)
00445                   {        // No data for this model !!!!!!!!!!!!!!
00446                       cout << " WARNING - NO DATA FOR TRAINING [" << idTest << "]";
00447                   }
00448                   else
00449                   { 
00450                       SegCluster & allFramesTest          =     segmentsServerTests.getCluster(codeSelectedFrame);
00451                       SegCluster & selectedSegmentsTests  =     segmentsServerTests.createCluster(1,"","");
00452                 
00453                       if(cross)
00454                       {
00455                           /* int indx =    -1;
00456                           if((indx  =     findClusterInRefvector(SegServ,idTest))! =    -1) copyCluster((static_cast <SegCluster & >(SegServ.getObject(indx))),selectedSegmentsTests);
00457                           else{*/
00458                           crossValid(configTest, ss,  ms, fsTests, allFramesTest,world,testMixtureEM,selectedSegmentsTests,idTest);
00459                           ms.setMixtureId(testMixtureEM, idTest);
00460               
00461                           /* selectedSegmentsTests.setSourceName(idTest); //set name of the segcluster for findClusterInRefVector function
00462                           //cout <<"SOURCE NAME : " <<selectedSegmentsTests.sourceName()<<endl;
00463                           SegServ.addObject(selectedSegmentsTests); //stock selected cluster in RefVector to avoid recalculation (take care it could be memory consumming)
00464                           }*/
00465                       }
00466                       else {//copy allFrameTests in selectedSegmensTests
00467                           copyCluster(allFramesTest,selectedSegmentsTests);
00468                           segmentsServerTests.remove(allFramesTest);
00469                       }
00470                      
00471                       
00472                       if (Fast)
00473                       {
00474                            
00475                            //onlyTests.addElement(idTest);//NEW
00476                           int index  =     ms.getMixtureIndex(idTest); //IF STOCKED (ALREADY COMPUTED) LOAD MODEL
00477                           if (index  ==     -1)
00478                           { 
00479                               String fullMixtureName =    getFullMixtureName(idTest,config);
00480                               
00481                               //IF TEST MIXTURE NOT STORED ON THE HARD DRIVE
00482                               if (FileExists(fullMixtureName)  ==     false)
00483                               {
00484                                   //create the EM model for the test 
00485                                   if(!map) 
00486                                       adaptModelEM(config, ss, ms, fsTests, selectedSegmentsTests, world, testMixtureEM);    
00487                                   
00488                                   else adaptModel(config, ss, ms, fsTests, selectedSegmentsTests, world, testMixtureEM);
00489                                           
00490                                   ms.setMixtureId(testMixtureEM, idTest);
00491                                   
00492                                   //SAVE test mixture 
00493                                   testMixtureEM.save(idTest,config);        
00494                               }
00495                               else testMixtureEM =     ms.loadMixtureGD(idTest);
00496                          }    // Set the client model Id
00497                          else
00498                              testMixtureEM  =     ms.getMixtureGD(index);
00499                       }
00500                       //Compute LLR and write it on a res file
00501                       LLRRatio  =     0.0;
00502                       fullFileName  =     getFullFileName(idTest, configTest);
00503                       
00504                       //TAKE CARE : by using it you should have 2 GMM of scores and a TNORM RES file according to the system used for computing the RES file 
00505                       if(!tnormAdapt){
00506                           
00507                           //TEST SHIFT TNORM                          
00508                           if (fromResFile)        
00509                           {
00510                               LLRRatio  =      searchLLRFromResFile(*id, idTest,  inputResFilename, configTest);
00511                           }
00512                           else
00513                           {
00514                               //Choice wether to use FastLLR or LLR (FastLLR is used when the top component are already computed for this Feature Server)
00515                           
00516                               //first time seeing this test
00517                               if (FileExists(fullFileName)  ==     false  || Fast  ==     false || cross)
00518                               {   
00519                                   //For proba, take the decision on the original target model
00520                                   LLRRatio  =     computeLLR(configTest, ss, fsTests, world, SAVclientMixture, selectedSegmentsTests, fullFileName);    
00521                               }
00522                               //For proba, take the decision on the original target model
00523                               else
00524                                   LLRRatio  =     computeFastLLR(ss, fsTests, world, SAVclientMixture, selectedSegmentsTests, fullFileName, configTest);    
00525                           }
00526                 
00527                           if (tnorm) normalizeScore(idTest, LLRRatio, stockTnorm,shift);
00528                           if (znorm) normalizeScore(*id, LLRRatio, stockZnorm,shift);     
00529                      }
00530             
00531                      
00532                      
00533                      LLRRatio2  =     0.0;
00534                      if (FileExists(fullFileName)  ==     false  || Fast  ==     false || cross)
00535                      {    
00536                          //first time seeing this test
00537                          LLRRatio2  =    computeLLR(configTest, ss, fsTests, world,clientMixture, selectedSegmentsTests,fullFileName);
00538                      }
00539                      else   LLRRatio2  =     computeFastLLR(ss, fsTests, world, clientMixture, selectedSegmentsTests, fullFileName, configTest);    //for LLR output
00540 
00541                      if(tnormAdapt && tnorm)
00542                      {
00543                 
00544                          shift =    findNearestLLRInMatrix(tnormA, session_nb, LLRRatio2);
00545                          cout <<"SHIFT  =     " <<shift<<endl;
00546                          LLRRatio2 -=    shift;
00547                      }
00548                 
00549                      //if (tnorm)   TnormalizeScore(idTest, LLRRatio2, stockTnorm,shift);
00550                          
00551                      if (tnorm) normalizeScore(idTest, LLRRatio2, stockTnorm,shift);
00552                      if (znorm) normalizeScore(*id, LLRRatio2, stockZnorm,shift);
00553                                 
00554                     /*
00555                     TEST TRIAL ON MEMORY 
00556                     */
00557                     double L2 = computeFastLLR(ss, fsTests, world, clientMixture_2, selectedSegmentsTests, fullFileName, configTest);    
00558                     double L3 = computeFastLLR(ss, fsTests, world, clientMixture_3, selectedSegmentsTests, fullFileName, configTest);    
00559                      
00560                     /*
00561                      TRAIN DATA ON MEMORY, take care TNORM not available for train data
00562                     */  
00563                     double Ltrain   = computeFastLLR(ss, fs, world, clientMixture, selectedSegments, fullFileNameTrain, configTest);    
00564                     double Ltrain_2 = computeFastLLR(ss, fs, world, clientMixture_2, selectedSegments, fullFileNameTrain, configTest);    
00565                     double Ltrain_3 = computeFastLLR(ss, fs, world, clientMixture_3, selectedSegments, fullFileNameTrain, configTest);    
00566                      
00567                      
00568                     //DISPLAY STATS
00569                     cout <<" Model : "<< *id << " , train data : "
00570                          <<" LLR test adapt -1 : " << Ltrain
00571                          <<" LLR test adapt -2 : " << Ltrain_2
00572                          <<" LLR test adapt -3 : " << Ltrain_3 <<endl;
00573                  
00574                      
00575                      
00576                     if (tnorm) normalizeScore(idTest, L2, stockTnorm,shift);
00577                     if (tnorm) normalizeScore(idTest, L3, stockTnorm,shift);
00578                             
00579                     //DISPLAY STATS
00580                     cout <<" Model : "<< *id << " , current test : " << idTest
00581                          <<" LLR test adapt -1 : " << LLRRatio2
00582                          <<" LLR test adapt -2 : " << L2
00583                          <<" LLR test adapt -3 : " << L3
00584                          <<" LLR test train model : " << LLRRatio <<endl;
00585                 
00586                     
00587                     
00588                     //TEST FOR ADAPTATION ERRORS, N-1 equal current client model
00589                    /* if(LLRRatio2 > (L2 + 0.24)) //ERROR OCCURS AT N-1
00590                     {   
00591                         //IF ERRORS OUTPUT LLR ON MODEL N-1 AND SET TRIAL N-1 WEIGHT TO 0
00592                         cout << "Found adaptation error, Model : "<<*id<<" Test : " << testsToCompute.getElement(countTests-1, false)<<endl; 
00593                         LLRRatio2 = L2;
00594                         clientMixture =  clientMixture_2;
00595                         decision[countTests-1] = configTest.getParam("meanImp").toDouble();
00596                     }
00597                     
00598                     if(LLRRatio2 > (L3 + 0.24) && (L2-L3 > 0.24)) //ERROR OCCURS AT N-2
00599                     {   
00600                         //IF ERRORS OUTPUT LLR ON MODEL N-2 AND SET TRIAL N-2 WEIGHT TO 0
00601                         cout << "Found adaptation error, Model : "<<*id<<" Test : " << testsToCompute.getElement(countTests-2, false)<<endl; 
00602                         LLRRatio2 = L3;
00603                         clientMixture =  clientMixture_3;
00604                         clientMixture_2 =  clientMixture_3;
00605                         decision[countTests-2] = configTest.getParam("meanImp").toDouble();
00606                     }
00607                     */
00608                     
00609                     // Output the result
00610                     outLLR << "M " << *id << " 0 " << idTest << " " << LLRRatio2 << endl;    
00611                
00612                     
00613                     /**********************DEBUG******************************************/
00614                     //if(LLRRatio < 0) LLRRatio  =     configTest.getParam("meanImp").toDouble();
00615                     /**********************END DEBUG******************************************/
00616             
00617                     if(tnormAdapt)
00618                         LLRRatio =    LLRRatio2;
00619                     
00620                     //if Oracle == true , DO NOT SET regress, wmap or wmapgmm to true!!!
00621                     if (oracle)
00622                         Oracle(*id, idTest, LLRRatio, configTest, tar, non, ssScores);
00623                     
00624                     //IF TRIAL SELECTED FOR ADAPTATION (DEFAULT : ALWAYS ON)
00625                     if(selected) //VALID FOR THE CURRENT, SHOULD BE UPDATED FOR PAST TRIALS
00626                     {
00627                         //Take the WMAP decision on adapted client model (LLRRatio2) or one session record (LLRRatio)               
00628                         decision.addValue(LLRRatio);
00629                         
00630                          //add tests data to objectrefvector
00631                         if (!Fast)
00632                         {
00633                             FeatServ.addObject(fsTests);
00634                             SegServ.addObject(selectedSegmentsTests);
00635                         }    
00636                         countTests++; 
00637                         
00638                         //stock the number of frames selected (used for fuseModels)
00639                         if(!map) NbFramesSelected.addValue(SegClusterFrame(selectedSegmentsTests));    
00640                         testsToCompute.addElement(idTest);
00641                         
00642                         selected = true;
00643                     }
00644               
00645                    /**********************************NIST protocol*******************************/
00646                    //SAVE LLRs because WMAP will modify them       
00647                    tmp  =     decision;    
00648                    //compute FS weights
00649                    if (regress)
00650                        expandLLR(decision, configTest);
00651                    else if (wmap)
00652                        WMAP(decision, configTest);
00653                    else if (wmapGmm){
00654                        if(fixedPriors)
00655                            WMAPGMMFixedPriors(decision, configTest, tar, non, ssScores);
00656                        else                        
00657                            WMAPGMM(decision, configTest, tar, non, ssScores);
00658                     }
00659                 
00660                     /**************************for debug***************/
00661                     /*   cout <<"Reset weights > 0.5 (for test)"<<endl;
00662                     for(unsigned long e =    1; e<decision.size();e++){
00663                     //if(decision[e]>0.5 || decision[e]<0.1)
00664                     if (decision[e]<0.8)
00665                     decision[e] =    0;
00666              
00667                     }*/
00668                     /***********************end***********************/
00669     
00670                     cout <<"Set weight of train data to 1"<<endl;
00671                     decision[0]  =     1;    //SET a weight of 1 for the train data
00672       
00673                     //create the new client model 
00674                     if (Fast)
00675                     {
00676                         if(assess){
00677                             assessAdaptation(ss,clientMixture ,selectedSegments, configTest, fs, world, tmp, fullFileNameTrain, countTests, LLRTrain);
00678                         }
00679         
00680                         //STUFF FOR DELETING PREVIOUS ADAPTATION, BACK TO TRAIN MODEL
00681                         if(resetNb && resetNb < (unsigned long)countTests)
00682                         {   
00683                             //new model  =     init client
00684                             //RESET
00685                             testsToCompute.reset();
00686                             NbFramesSelected.clear();
00687                             decision.clear();
00688                             //RELOAD WITH CLIENT ONLY
00689 
00690                             if(!map) NbFramesSelected.addValue(SegClusterFrame(selectedSegments));
00691                             testsToCompute.addElement(*id);
00692                             decision.addValue(1);    
00693                         }
00694                    
00695                         //UPDATE MEMORY MODELS
00696                         clientMixture_3 = clientMixture_2; 
00697                         clientMixture_2 = clientMixture;
00698                         //EXIT the oldest clientMixture_3
00699                    
00700                    
00701                         //Create adapted clientmodel
00702                         if(!map)
00703                             computeMAPmodelFromEMones(configTest, ss, ms, NbFramesSelected, world, clientMixture, auxMixture, tmpMixture, decision, testsToCompute);
00704                         else fuseMAP(config, ss,  ms, world, clientMixture, auxMixture,tmpMixture, decision, testsToCompute);
00705                
00706                         if(saveAfterIt){
00707                             /* SAVE THE TARGET MODEL AFTER EACH ITERATION        */                
00708                             cout << "Save client model [" << *id << "]" <<" after IT : "<< countTests-1 << endl;
00709                             char  toto[256];
00710                             sprintf(toto,"%d",(countTests-1));         
00711                             clientMixture.save((*id)+"."+toto, config);    // Save the client model
00712                         } 
00713 
00714                             
00715                        }
00716                     else 
00717                     {
00718                         clientMixture  =     world;    //reset clientMixture to MAP from world
00719                         adaptModel(config, ss, ms, FeatServ, SegServ, world, clientMixture, decision);
00720                     }
00721               
00722                     //TEST SHIFT TNORM
00723                     if(tnormAdapt)
00724                     {    
00725                         double toto =    0.0;
00726                         for (unsigned long e =    0; e < NbFramesSelected.size(); e++)
00727                                toto  +=    NbFramesSelected[e]*decision[e];
00728                         cout <<"Total Frames used for learning the adapted model  =     " << toto<<endl;
00729                 
00730                         /*if(0.0 <toto && toto <9500.0)          shift  =     0.0;
00731                         else if (9500.0 <toto && toto <17000.0)  shift  =     0.10869;    
00732                         else if (17000.0 <toto && toto <25500.0) shift  =     0.15848;    
00733                         else if (25500.0 <toto && toto <34000.0) shift  =     0.18503;    
00734                         else if (34000.0 <toto && toto <42400.0) shift  =     0.20503;    
00735                         else if (42400.0 <toto && toto <50000.0) shift  =     0.22061;    
00736                         else if ( 50000.0<toto && toto <59400.0) shift  =     0.23417;    
00737                         else if ( 59400.0<toto && toto <67900.0) shift  =     0.24945;    
00738                         else if ( 67900.0<toto && toto <76400.0) shift  =     0.26698;    
00739                         else if (76400.0 <toto && toto <85000.0) shift  =     0.28624;    
00740                         else if (toto>85000.0)                   shift  =     0.28624;    */
00741                 
00742                         if (9500.0 < toto && toto < 17000.0)        session_nb =    2;    
00743                         else if ( 17000.0 < toto && toto < 25500.0) session_nb =    3;    
00744                         else if ( 25500.0 < toto && toto < 34000.0) session_nb =    4;    
00745                         else if ( 34000.0 < toto && toto < 42400.0) session_nb =    5;    
00746                         else if ( 42400.0 < toto && toto < 50000.0) session_nb =    6;    
00747                         else if ( 50000.0 < toto && toto < 59400.0) session_nb =    7;    
00748                         else if ( 59400.0 < toto && toto < 67900.0) session_nb =    8;    
00749                         else if ( 67900.0 < toto && toto < 76400.0) session_nb =    9;    
00750                         else if ( 76400.0 < toto && toto < 85000.0) session_nb =    10;    
00751                         else if (toto > 85000.0)                    session_nb =    10;
00752                 
00753                 
00754                     }
00755                 
00756                     decision  =     tmp; //RESTORE LLRs
00757                     tmp.clear();
00758                       
00759               }
00760               if (Fast)
00761               {        //delete object created with new, not nedded anymore
00762                   delete & segmentsServerTests;
00763                   delete & fsTests;
00764               }
00765               //UNTIL NOW LOAD EACH TEST MIXTURE
00766               if (ms.getMixtureCount() > (unsigned long)configTest.getParam("MaxMixturesCount").toLong())
00767               { 
00768               
00769                   if(verbose && verboseLevel>1)
00770                       cout <<"Exceeding capacity of the mixtureServer ("<<(unsigned long)configTest.getParam("MaxMixturesCount").toLong()<<")"<<endl;
00771                 
00772                   ms.deleteMixture(testMixtureEM); //delete current test mixture
00773                   ms.deleteUnusedDistribs();
00774                 
00775               }
00776             
00777             }
00778         
00779         }            //end tests loop
00780 
00781         if (verbose)
00782             cout << "Save client model [" << *id << "]" << endl;
00783         clientMixture.save(*id, config);    // Save the client model
00784         inputTestsList.rewind();    //rewind the xlist, needed when changing target
00785     
00786         //delete all client Mixtures 
00787         ms.deleteMixture(clientMixture);
00788         ms.deleteMixture(clientMixtureEM);
00789         ms.deleteMixture(SAVclientMixture);
00790         ms.deleteUnusedDistribs();
00791 
00792         NbFramesSelected.clear();
00793         decision.clear();
00794         
00795         /***************************NEW STUFF*********************  */    
00796         /* NbFramesSelectedForTests.clear();
00797         decisionOnlyTests.clear(); 
00798         ms.deleteMixture(mixtureOnlyTests);
00799         onlyTests.reset();
00800         previousLLR =    -10000;*/
00801         /*************************** END NEW STUFF*********************  */
00802         
00803         if (!Fast)
00804         {
00805            FeatServ.deleteAllObjects();
00806            SegServ.deleteAllObjects();
00807         }
00808         
00809         testsToCompute.reset();
00810         
00811         if (Fast)
00812         {        //delete object created with new, not nedded anymore
00813            delete & fs;
00814            delete & segmentsServer;
00815         }
00816         
00817         //reset mixtureServer to free memory (reload needed for several mixtures)
00818         if (ms.getMixtureCount() > (unsigned long)configTest.getParam("MaxMixturesCount").toLong())
00819         {
00820             if (verbose)
00821                 cout << "Reset MixtureServer and reload  of the used mixtures" << endl;
00822             
00823             ms.reset();
00824             MixtureGD & world  =     ms.loadMixtureGD(inputWorldFilename);    //load needed for each client because of the mixture server reset 
00825             
00826             //temporate mixtures used in computeMAPmodelFromEMones, create here to accelerate
00827             idAux  =     (ms.createMixtureGD(world.getDistribCount())).getId();
00828             idTmp  =     (ms.createMixtureGD(world.getDistribCount())).getId();
00829         }
00830     }
00831 }                // end of the the target loop 
00832 
00833 //When end delete all mixture in the server
00834   ms.deleteMixtures(0, ms.getMixtureCount());
00835   ms.deleteUnusedDistribs();
00836 
00837   if (tnorm)
00838       stockTnorm.deleteAllObjects();
00839   if(znorm)
00840       stockZnorm.deleteAllObjects();
00841   outLLR.close();
00842 
00843   return 0;
00844 }
00845 
00846 
00847 
00848 
00849 
00850 #endif //!defined(ALIZE_TrainTarget_cpp)