FactorAnalysis.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_FactorAnalysis_cpp)
00056 #define ALIZE_FactorAnalysis_cpp
00057 
00058 #include<FactorAnalysis.h>
00059 #include<iostream>
00060 #include<fstream>
00061 #include<cstdio>
00062 #include<cassert>
00063 #include<cmath>
00064 #include "SuperVectors.h"
00065 #include "RealVector.h"
00066 #if defined(THREAD)
00067 #include <pthread.h>
00068 #endif
00069 
00070 using namespace alize;
00071 using namespace std;
00072 
00073 FactorAnalysisStat::FactorAnalysisStat(String & featFilename,FeatureServer & fs,Config & config):_ms(config),_ss(config){ // constructor for a single file
00074         XList faNdx;    
00075         XLine featLine;
00076         featLine.addElement(featFilename);
00077         faNdx.addLine()=featLine;
00078         _init(faNdx,fs,config);
00079 }
00080 
00081 FactorAnalysisStat::FactorAnalysisStat(XList & ndx,FeatureServer & fs,Config & config):_ms(config),_ss(config){ // constructeur
00082         _init(ndx,fs,config);
00083 }
00084 
00085 void FactorAnalysisStat::_init(XList & ndx,FeatureServer & fs,Config & config){
00086         fileList=ndx;
00087         _nb_speakers=fileList.getLineCount();
00088         _nb_sent=fileList.getAllElements().getElementCount();
00089         
00090         _ndxTable=Translate(ndx);
00091         _topGauss=config.existsParam("topGauss");
00092         if (verbose) cout << "(FactorAnalysisStat) Estimate FA stats on "<<_nb_sent<< " example(s) with "<<_nb_speakers<<" speaker(s)"<<endl;
00093                 
00094         _ms.loadMixtureGD(config.getParam("inputWorldFilename")); // garde
00095         _ms.loadMixtureGD(config.getParam("inputWorldFilename")); // modifie
00096                 
00097         MixtureGD & UBM=_ms.getMixtureGD((unsigned long) 0);
00098                 
00099         if (verbose) cout <<"(FactorAnalysisStat) Model parameter Dim:" <<UBM.getVectSize()<<"___nbC:" <<UBM.getDistribCount()<<endl;
00100 
00101         _vsize=UBM.getVectSize();
00102         _mixsize=UBM.getDistribCount();
00103         _supervsize=_vsize*_mixsize;
00104         _D.setSize(_supervsize);
00105 
00106         // Random Init for U or init with an existing one (used in traintarget for instance)
00107         _matU=Matrix<double>();
00108         if (config.existsParam("initChannelMatrix")) {
00109                 _matU.load(config.getParam("initChannelMatrix"),config);
00110                 if (_matU.cols()>_matU.rows()) _matU.transpose();
00111                 if (verbose) cout << "(FactorAnalysisStat) Init for Channel Matrix: "<< config.getParam("initChannelMatrix")<< ", rank: ["<<_matU.cols() << "] sv size: [" << _matU.rows() <<"]"<<endl;
00112                 _rang=_matU.cols();
00113                 if (UBM.getDistribCount()*UBM.getVectSize()!=_matU.rows()) throw Exception("Supervector size does not match with UBM model",__FILE__,__LINE__);
00114         }
00115         else {
00116                 _rang=config.getParam("channelMatrixRank").toLong();            
00117                 _matU.setDimensions(_supervsize,_rang);
00118                 srand48(_supervsize*_rang);
00119                 _matU.randomInit();                     
00120                 if (verbose) cout << "(FactorAnalysisStat) Random Init for Channel Matrix: "<<", rank: ["<<_matU.cols() << "] sv size: [" << _matU.rows() <<"]"<<endl;                  
00121         }               
00122                 
00123         // FA stats
00124         _matY=Matrix<double>(_nb_speakers,_supervsize);
00125         _matX=Matrix<double>(_nb_sent,_rang);
00126         _matS_X=Matrix<double>(_nb_speakers,_supervsize);
00127         _matS_X_h=Matrix<double>(_nb_sent,_supervsize); 
00128         _matN_h=Matrix<double>(_nb_sent,_mixsize);      
00129         _matN=Matrix<double>(_nb_speakers,_mixsize);            
00130         
00131         _matY.setAllValues(0.0);
00132         _matX.setAllValues(0.0);        
00133         _matS_X.setAllValues(0.0);      
00134         _matS_X_h.setAllValues(0.0);    
00135         _matN_h.setAllValues(0.0);
00136         _matN.setAllValues(0.0);
00137                         
00138         _super_mean.setSize(_supervsize);
00139         _super_invvar.setSize(_supervsize);
00140         _tau=config.getParam("regulationFactor").toDouble();
00141         if (verbose) cout << "(FactorAnalysisStat) Regulation Factor ["<<_tau<<"]"<<endl;
00142         // D construction
00143         for(unsigned long i=0;i<_mixsize;i++){
00144                 DistribGD & aux=UBM.getDistrib(i);
00145                 RealVector <double> & v=aux.getCovInvVect();
00146                 RealVector <double> & u=aux.getMeanVect();
00147                 for(unsigned long j=0;j<_vsize;j++){
00148                          _D[i*_vsize+j]=sqrt(1.0/(v[j]*_tau));
00149                          _super_mean[i*_vsize+j]=u[j];
00150                          _super_invvar[i*_vsize+j]=v[j];
00151                 }
00152         }
00153                 
00154 
00155         if (verboseLevel > 1) cout <<"(FactorAnalysisStat) Number of examples " << _nb_sent << endl;
00156         for(unsigned long i=0;i<_nb_sent;i++) {
00157                 _l_h_inv.addObject(*(new DoubleSquareMatrix()),i);
00158                 _l_h_inv[i].setSize(_rang);
00159         }               
00160         if (verboseLevel >1) cout << "(FactorAnalysisStat) Y dimensions are: " << _matY.rows() <<","<<_matY.cols()<<"__ X dimensions are: "<< _matX.rows() <<","<< _matX.cols() <<endl << "(FactorAnalysisStat) FA Accumator Built"<<endl;     
00161 };  
00162 
00163 void FactorAnalysisStat::computeAndAccumulateGeneralFAStats(FeatureServer &fs,Config & config){
00164         SegServer segmentsServer;
00165         LabelServer labelServer;
00166         initializeClusters(fileList,segmentsServer,labelServer,config);
00167         verifyClusterFile(segmentsServer,fs,config);
00168         unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(config.getParam("labelSelectedFrames"));
00169         SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame); 
00170         this->computeAndAccumulateGeneralFAStats(selectedSegments,fs,config);
00171 };
00172 
00173 void FactorAnalysisStat::computeAndAccumulateGeneralFAStats(SegCluster &selectedSegments,FeatureServer &fs,Config & config){
00174         if (verbose) cout <<"(FactorAnalysisStat) Compute General FA Stats (Complete)" << endl;
00175         double *N_h, *N, *S_X_h, *S_X,*ff;      
00176         _matN_h.setAllValues(0.0);
00177         _matN.setAllValues(0.0);
00178         _matS_X_h.setAllValues(0.0);
00179         _matS_X.setAllValues(0.0);
00180         N_h=_matN_h.getArray(); N=_matN.getArray(); S_X_h=_matS_X_h.getArray();S_X=_matS_X.getArray();
00181         
00182         MixtureGD & UBM=_ms.getMixtureGD((unsigned long) 1);
00183         MixtureGDStat &acc=_ss.createAndStoreMixtureStat(UBM);
00184 
00185         // Compute Occupations and Statistics
00186         acc.resetOcc();
00187         Seg *seg; 
00188         selectedSegments.rewind();
00189         String currentSource="";unsigned long loc=0;unsigned long sent=0;
00190         while((seg=selectedSegments.getSeg())!=NULL){   
00191                 unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName());                           // Idx of the first frame of the current file in the feature server
00192                 if (currentSource!=seg->sourceName()) {
00193                 currentSource=seg->sourceName();
00194                 loc=_ndxTable.locNb(currentSource);
00195                 sent=_ndxTable.sessionNb(currentSource);        
00196                 if (verbose)cout << "Processing speaker["<<currentSource<<"]"<< endl;   
00197                 }
00198 
00199                 fs.seekFeature(begin);
00200                 Feature f;
00201                 if (!_topGauss) {
00202                         for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
00203                                 fs.readFeature(f);
00204                                 acc.computeAndAccumulateOcc(f);
00205                                 RealVector <double> aPost=acc.getOccVect();
00206                                 ff=f.getDataVector();
00207                                 for(unsigned long k=0;k<_mixsize;k++) {
00208                                         N_h[sent*_mixsize+k]+=aPost[k];
00209                                         N[loc*_mixsize+k]   +=aPost[k];
00210                                         for (unsigned long i=0;i<_vsize;i++) {
00211                                                 S_X_h[sent*_supervsize+(k*_vsize+i)]+=aPost[k]*ff[i];
00212                                                 S_X[loc*_supervsize+(k*_vsize+i)]   +=aPost[k]*ff[i];
00213                                                 }
00214                                 }       
00215                         }
00216                 } 
00217                 else throw Exception("ComputeGeneralStats TopGauss not done at this level",__FILE__,__LINE__);
00218         }                                       
00219 };
00220 /*
00221 void FactorAnalysisStat::computeAndAccumulateGeneralFAStatsTopGauss(FeatureServer &fs,Config & config){ // this does not work great
00222         if (verbose) cout <<"(FactorAnalysisStat) Compute General FA Stats (TopGauss)" << endl;
00223         unsigned long i,k,begin, nbg, k1;
00224         RealVector <double> AUX2; AUX2.setSize(_supervsize); AUX2.setAllValues(0.0);double* aux2=AUX2.getArray();       
00225         RealVector <double> _Prob; _Prob.setSize(_mixsize); double *Prob=_Prob.getArray();
00226         RealVector <double> m_xh; m_xh.setSize(_supervsize);
00227         double *super_mean, *N_h, *N, *S_X_h, *S_X,*ff; 
00228         super_mean=_super_mean.getArray(); N_h=_matN_h.getArray(); N=_matN.getArray(); S_X_h=_matS_X_h.getArray(); S_X=_matS_X.getArray();
00229         static unsigned long it=0;
00230         MixtureGD & UBM=_ms.getMixtureGD((unsigned long) 1);
00231         
00232         // Compute Occupations and Statistics
00233         unsigned long loc=0; 
00234         unsigned long sent=0;   
00235         XLine *pline; String *pFile; fileList.rewind();double sum=0.0;
00236 
00237         while((pline=fileList.getLine())!=NULL) { 
00238                 if (verbose) cout << "(FactorAnalysisStat) Process speaker [" << loc << "] ----> " <<endl;
00239                 for(i=0;i<_mixsize;i++) 
00240                         N[loc*_mixsize+i]=0.0;
00241                 for(i=0;i<_supervsize;i++) 
00242                         S_X[loc*_supervsize+i]=0.0;
00243                 while((pFile=pline->getElement())!=NULL) {
00244                         if (1) this->getSpeakerModel(UBM,loc,sent);
00245 
00246                         if (verboseLevel > 1) cout << "Session : [" << sent <<"], ";
00247                         for(i=0;i<_mixsize;i++) 
00248                                 N_h[sent*_mixsize+i]=0;//.000000001;
00249                         for(i=0;i<_mixsize;i++) 
00250                                 N[loc*_mixsize+i]+=0;//.000000001;
00251                         
00252                         for(i=0;i<_supervsize;i++) 
00253                                 S_X_h[sent*_supervsize+i]=0.0;
00254                         
00255                         this->getUX(AUX2,sent);
00256                                 
00257                         for(k=0;k<_supervsize;k++) 
00258                                 aux2[k]+=super_mean[k];
00259 
00260                         String featureFileName=(*pFile);                        // Current file basename        
00261                         begin=fs.getFirstFeatureIndexOfASource(featureFileName);
00262                         fs.seekFeature(begin);
00263                         SegServer segmentsServer;
00264                         LabelServer labelServer;
00265                         initializeClusters(featureFileName,segmentsServer,labelServer,config);
00266                         verifyClusterFile(segmentsServer,fs,config);
00267                         unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(config.getParam("labelSelectedFrames"));
00268                         SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);  
00269                         Seg *seg; 
00270                         selectedSegments.rewind();
00271                         TopGauss tg;
00272                         tg.read(featureFileName,config);
00273                         unsigned long*_idx=tg.idx().getArray();
00274                         unsigned long*_nbg=tg.nbg().getArray();
00275 
00276                         unsigned long nt=0; //frame counter
00277                         unsigned long nan=0;                    unsigned long floor=0;
00278                         while((seg=selectedSegments.getSeg())!=NULL){
00279                                 unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName());                           // Idx of the first frame of the current file in the feature server      
00280                                 fs.seekFeature(begin);
00281                                 Feature f;
00282                                 unsigned long idxBegin=tg.frameToIdx(nt); // get the begin index of gaussians in idx vectors                    
00283                                 for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
00284                                         fs.readFeature(f);
00285                                         ff=f.getDataVector();
00286                                         nbg=_nbg[nt]; // get nb gauss for this frame
00287                                         sum=0.0;
00288                                         for(unsigned long k=0;k<nbg;k++) {
00289                                                 Prob[k]=UBM.weight(_idx[idxBegin+k])*UBM.getDistrib(_idx[idxBegin+k]).computeLK(f);
00290                                                 if (isnan(Prob[k])) {Prob[k]=1e-20;nan++;}
00291                                                 sum+=Prob[k];                                                                                           
00292                                         }
00293                                         if (log(sum)<-200) {floor++;_Prob.setAllValues(0.0);}
00294                                         else {
00295                                                 for(unsigned long k=0;k<nbg;k++) 
00296                                                         Prob[k]/=sum; 
00297                                         }
00298                                         for(unsigned long k=0;k<nbg;k++) {                      
00299                                                 k1=_idx[k+idxBegin];
00300                                                 N_h[sent*_mixsize+k1]+=Prob[k];
00301                                                 N[loc*_mixsize+k1]   +=Prob[k];
00302                                                 for (unsigned long i=0;i<_vsize;i++) {
00303                                                         S_X_h[sent*_supervsize+(k1*_vsize+i)]+=Prob[k]*ff[i];
00304                                                         S_X[loc*_supervsize+(k1*_vsize+i)]   +=Prob[k]*ff[i];
00305                                                         }
00306                                         }
00307                                         idxBegin+=nbg;
00308                                         nt++;   
00309                                 }       
00310                         }
00311                         if (verboseLevel > 2) cout << "nan:" <<nan<<" floor:" <<floor<<endl;
00312                         sent++;
00313                 }
00314                 loc++;
00315         }
00316         it++;
00317         if (verboseLevel > 1) cout << "(FactorAnalysisStat) Done " << endl;
00318 };*/
00319 
00320 
00321 
00322 void FactorAnalysisStat::substractSpeakerStats(){
00323         if (verbose) cout <<"(FactorAnalysisStat) Compute and Substract Speaker FA Stats... " << endl;  
00324         RealVector <double> AUX1;AUX1.setSize(_supervsize); AUX1.setAllValues(0.0); double *aux1=AUX1.getArray();  
00325         
00326         // Compute Occupations and Statistics
00327         unsigned long loc=0; 
00328         unsigned long sent=0;           
00329         XLine *pline; String *pFile; fileList.rewind();
00330 
00331         double *N_h=_matN_h.getArray(); 
00332         double *S_X_h=_matS_X_h.getArray();
00333 
00334         while((pline=fileList.getLine())!=NULL) { 
00335                 while((pFile=pline->getElement())!=NULL) {
00336                 this->getMplusDY(AUX1,*pFile);                  
00337                         for(unsigned long k=0;k<_mixsize;k++) 
00338                                 for (unsigned long i=0;i<_vsize;i++) 
00339                                         S_X_h[sent*_supervsize+(k*_vsize+i)]-= N_h[sent*_mixsize+k]*aux1[i+k*_vsize];
00340                         sent++;
00341                 }
00342                 loc++;
00343         }
00344         if (verboseLevel >1) cout << "(FactorAnalysisStat) Done "<<endl;
00345 };
00346 
00347 void FactorAnalysisStat::substractChannelStats(){
00348         if (verbose) cout <<"(FactorAnalysisStat) Compute and Substract Channel FA Stats... "<<endl;    
00349         RealVector <double> UX;UX.setSize(_supervsize); UX.setAllValues(0.0);double* ux=UX.getArray();          
00350                 
00351         // Compute Occupations and Statistics
00352         unsigned long loc=0;
00353         unsigned long sent=0; 
00354         XLine *pline; String *pFile; 
00355         fileList.rewind();
00356         
00357         double *super_mean=_super_mean.getArray();
00358         double *N_h=_matN_h.getArray(); 
00359         double *S_X=_matS_X.getArray();
00360 
00361         while((pline=fileList.getLine())!=NULL) {               
00362                 while((pFile=pline->getElement())!=NULL) {
00363                         this->getUX(UX,*pFile);
00364                         for(unsigned long k=0;k<_supervsize;k++) 
00365                                 ux[k]+=super_mean[k];
00366                         
00367                         for(unsigned long k=0;k<_mixsize;k++)
00368                                 for (unsigned long i=0;i<_vsize;i++)
00369                                         S_X[loc*_supervsize+(k*_vsize+i)]-= N_h[sent*_mixsize+k]*ux[i+k*_vsize];
00370                         sent++;
00371                 }
00372                 loc++;
00373         }
00374 };
00375 
00376 
00377 void FactorAnalysisStat::getXEstimate(){
00378         if (verbose) cout << "(FactorAnalysisStat) Compute X Estimate "<<endl;
00379         RealVector <double> AUX;
00380         AUX.setSize(_rang);
00381         XLine *pline;
00382         String *pFile;
00383 
00384         _matX.setAllValues(0.0);
00385 
00386         double *X=_matX.getArray();     
00387         double *U=_matU.getArray();
00388         double *S_X_h=_matS_X_h.getArray();
00389         double *aux=AUX.getArray();
00390         double *super_invvar=_super_invvar.getArray();
00391         
00392         fileList.rewind();
00393         while((pline=fileList.getLine())!=NULL) {
00394                 while((pFile=pline->getElement())!=NULL) {
00395                     unsigned long sent=_ndxTable.sessionNb(*pFile);
00396                         AUX.setAllValues(0.0);
00397                         for(unsigned long i=0;i<_rang;i++)
00398                                 for(unsigned long k=0;k<_supervsize;k++) 
00399                                         aux[i]+= U[k*_rang+i]*super_invvar[k]*S_X_h[sent*_supervsize+k];        
00400                         double *l_h_inv=_l_h_inv[sent].getArray();      
00401                         for(unsigned long i=0;i<_rang;i++)
00402                                 for(unsigned long k=0;k<_rang;k++) 
00403                                         X[sent*_rang+i]+=l_h_inv[i*_rang+k]*aux[k];
00404                         sent++;
00405                 }
00406         }
00407 };
00408 
00409 void FactorAnalysisStat::estimateAndInverseL(Config & config){
00410     #if defined(THREAD)          
00411     if (config.existsParam("numThread") && config.getParam("numThread").toLong() >0) estimateAndInverseLThreaded(config.getParam("numThread").toLong());
00412     else estimateAndInverseLUnThreaded();
00413     #else
00414     estimateAndInverseLUnThreaded();
00415     #endif
00416 };
00417 
00418 void FactorAnalysisStat::estimateAndInverseLUnThreaded(){
00419         if (verbose) cout << "(FactorAnalysisStat) Inverse L Matrix ... "<<endl;        
00420         unsigned long mk;
00421         DoubleSquareMatrix L(_rang);    
00422         L.setAllValues(0.0);
00423         RealVector <double> AUX;
00424         AUX.setSize(_rang);
00425         unsigned long sent=0;
00426         XLine *pline;
00427         String *pFile;
00428         fileList.rewind();
00429 
00430         double *N_h=_matN_h.getArray(); 
00431         double *U=_matU.getArray();
00432         double *LV=L.getArray();
00433         double *super_invvar=_super_invvar.getArray();
00434         
00435         while((pline=fileList.getLine())!=NULL) {
00436                 while((pFile=pline->getElement())!=NULL) {
00437                         L.setAllValues(0.0);
00438                         AUX.setAllValues(0.0);
00439                         for(unsigned long i=0;i<_rang;i++){
00440                                 for(unsigned long j=0;j<=i;j++){
00441                                         for(unsigned long k=0;k<_supervsize;k++){
00442                                                 mk=k/_vsize;
00443                                                 LV[i*_rang+j]+=N_h[sent*_mixsize+mk]*super_invvar[k]*U[k*_rang+i]*U[k*_rang+j];
00444                                                 }
00445                                         }
00446                                 }
00447                         for(unsigned long i=0;i<_rang;i++)
00448                                 for(unsigned long j=i+1;j<_rang;j++) 
00449                                         LV[i*_rang+j]=LV[j*_rang+i];
00450                                 
00451                         for(unsigned long i=0;i<_rang;i++) 
00452                                 LV[i*_rang+i]+=1.0;
00453                         L.invert(_l_h_inv[sent]);       
00454                         sent++;
00455                 }
00456         }
00457 };
00458 
00459 /*****************************************************************************************************
00460 ********************* Threaed Version of L Matrices Inversion (Nico Scheffer)
00461 *****************************************************************************************************/
00462 #if defined(THREAD)
00463 struct Lthread_data{
00464         double *N_h;
00465         double *U;
00466         double *super_invvar;
00467         unsigned long sentBottom;
00468         unsigned long sentUp;   
00469         unsigned long rang;
00470         unsigned long sv;
00471         unsigned long vsize;
00472         unsigned long mixsize;
00473         RefVector <DoubleSquareMatrix>* linv;
00474 };
00475 
00476 void *Lthread(void *threadarg) {
00477         struct Lthread_data *my_data;
00478         my_data = (struct Lthread_data *) threadarg;
00479         double *U = my_data->U;
00480         unsigned long sentBottom = my_data->sentBottom; 
00481         unsigned long sentUp = my_data->sentUp;
00482         double *N_h=my_data->N_h;
00483         double *super_invvar=my_data->super_invvar;
00484         unsigned long _rang=my_data->rang;
00485         unsigned long _supervsize=my_data->sv;
00486         unsigned long _vsize=my_data->vsize;
00487         unsigned long _mixsize=my_data->mixsize;
00488         for (unsigned long sent=sentBottom;sent <sentUp;sent++) {
00489                 DoubleSquareMatrix L(_rang);    
00490                 L.setAllValues(0.0);    
00491                 double *LV=L.getArray();
00492                 unsigned long mk;
00493                 RealVector <double> AUX;
00494                 AUX.setSize(_rang);
00495                 AUX.setAllValues(0.0);
00496                 for(unsigned long i=0;i<_rang;i++){
00497                         for(unsigned long j=0;j<=i;j++){
00498                                 for(unsigned long k=0;k<_supervsize;k++){
00499                                         mk=k/_vsize;
00500                                         LV[i*_rang+j]+=N_h[sent*_mixsize+mk]*super_invvar[k]*U[k*_rang+i]*U[k*_rang+j];
00501                                 }
00502                         }
00503                 }
00504                 for(unsigned long i=0;i<_rang;i++)
00505                         for(unsigned long j=i+1;j<_rang;j++) 
00506                                 LV[i*_rang+j]=LV[j*_rang+i];
00507                                         
00508                 for(unsigned long i=0;i<_rang;i++) 
00509                         LV[i*_rang+i]+=1.0;     
00510                 DoubleSquareMatrix &linv=(*(my_data->linv))[sent];              
00511                 L.invert(linv);
00512         }
00513         pthread_exit((void*) 0);
00514 }
00515 
00516 void FactorAnalysisStat::estimateAndInverseLThreaded(unsigned long NUM_THREADS){
00517         if (verbose) cout << "(FactorAnalysisStat) Inverse L Matrix Threads ... "<<endl;        
00518         if (NUM_THREADS==0) throw Exception("Num threads can be 0",__FILE__,__LINE__);
00519         double *N_h=_matN_h.getArray(); 
00520         double *U=_matU.getArray();
00521         double *super_invvar=_super_invvar.getArray();
00522 
00523         int rc, status;
00524         if (NUM_THREADS > _nb_sent) NUM_THREADS=_nb_sent;
00525         struct Lthread_data thread_data_array[NUM_THREADS];
00526         pthread_t threads[NUM_THREADS]; 
00527         pthread_attr_t attr;
00528         pthread_attr_init(&attr);
00529         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00530         unsigned long offset=_nb_sent/NUM_THREADS;
00531         for(unsigned long t=0, sentBottom=0; t<NUM_THREADS; t++,sentBottom+=offset){
00532                 thread_data_array[t].N_h=N_h;
00533                 thread_data_array[t].U=U;
00534                 thread_data_array[t].super_invvar=super_invvar;
00535                 thread_data_array[t].sentBottom=sentBottom;
00536                 unsigned long sentUp=sentBottom+offset;
00537                 if (_nb_sent%NUM_THREADS!=0) sentUp++;
00538                 thread_data_array[t].sentUp=sentUp;
00539                 thread_data_array[t].rang=_rang;
00540                 thread_data_array[t].sv=_supervsize;
00541                 thread_data_array[t].vsize=_vsize;
00542                 thread_data_array[t].mixsize=_mixsize;
00543                 thread_data_array[t].linv=&(_l_h_inv);
00544 
00545                 if (verbose) cout<<"(FactorAnalysisStat) Creating thread n["<< t<< "] for sessions["<<sentBottom<<"-->"<<sentUp<<"]"<<endl;             
00546                 rc = pthread_create(&threads[t], &attr, Lthread, (void *)&thread_data_array[t]);                
00547                 if (rc) throw Exception("ERROR; return code from pthread_create() is ",__FILE__,rc);
00548         }
00549         pthread_attr_destroy(&attr);
00550         for(unsigned long t=0; t<NUM_THREADS; t++) {
00551                 rc = pthread_join(threads[t], (void **)&status);
00552                 if (rc)  throw Exception("ERROR; return code from pthread_join() is ",__FILE__,rc);
00553                 if (verbose) cout <<"(FactorAnalysisStat) Completed join with thread ["<<t<<"] status["<<status<<"]"<<endl;
00554         }
00555         if (verboseLevel > 1) cout << "(FactorAnalysisStat) Done " << endl;
00556 };
00557 #endif
00558 /****************************************** End *****************************************************/
00559 
00560 void FactorAnalysisStat::getYEstimate(){
00561         if (verbose) cout << "(FactorAnalysisStat) Compute Y Estimate "<<endl;
00562         _matY.setAllValues(0.0);
00563 
00564         double *N=_matN.getArray(); 
00565         double *Y=_matY.getArray();
00566         double *S_X=_matS_X.getArray();
00567         double *D=_D.getArray();
00568         double *super_invvar=_super_invvar.getArray();
00569 
00570         for(unsigned long loc=0;loc<_nb_speakers;loc++) {
00571                 for(unsigned long i=0;i<_supervsize;i++){
00572                         unsigned long mi=i/_vsize;
00573                         Y[loc*_supervsize+i]= (_tau/(_tau+N[loc*_mixsize+mi]))*D[i]*super_invvar[i]*S_X[loc*_supervsize+i];
00574                         }
00575                 }
00576 };
00577 
00578 void FactorAnalysisStat::getUEstimate(Config & config){
00579     #if defined(THREAD)          
00580     if (config.existsParam("numThread") && config.getParam("numThread").toLong() >0) getUEstimateThreaded(config.getParam("numThread").toLong());
00581     else getUEstimateUnThreaded();
00582     #else
00583     getUEstimateUnThreaded();
00584     #endif
00585 };
00586 
00587 void FactorAnalysisStat::getUEstimateUnThreaded(){
00588         if (verbose) cout << "(FactorAnalysisStat) Compute U Estimate "<<endl;  
00589         DoubleSquareMatrix L(_rang);
00590         DoubleSquareMatrix L_Inv(_rang);
00591         RealVector <double> R;
00592         R.setSize(_rang);
00593 
00594         double *N_h=_matN_h.getArray(); 
00595         double *X=_matX.getArray();
00596         double *S_X_h=_matS_X_h.getArray();
00597         double *U=_matU.getArray();
00598         double *RV=R.getArray();
00599         double *LV=L.getArray();
00600 
00601         /*for(i=0;i<_supervsize;i++){
00602                 unsigned long im=i/_vsize;
00603                 L.setAllValues(0.0);
00604                 R.setAllValues(0.0);
00605                 for(j=0;j<_nb_sent;j++){
00606                         double *l_h_inv=_l_h_inv[j].getArray();
00607                         for(k=0;k<_rang;k++){
00608                                 for(l=0;l<_rang;l++) 
00609                                         LV[k*_rang+l]+=(l_h_inv[k*_rang+l]+X[j*_rang+k]*X[j*_rang+l])*N_h[j*_mixsize+im];
00610                                 RV[k]+=S_X_h[j*_supervsize+i]*X[j*_rang+k];
00611                                 }
00612                         }               
00613                 L.invert(L_Inv);
00614                 double *L_InvV=L_Inv.getArray();
00615                 for(j=0;j<_rang;j++)
00616                         U[i*_rang+j]=0.0;
00617                 for(j=0;j<_rang;j++)
00618                         for(k=0;k<_rang;k++) 
00619                                 U[i*_rang+j]+=L_InvV[j*_rang+k]*RV[k];
00620         }*/
00621         _matU.setAllValues(0.0);
00622         for(unsigned long g=0;g<_mixsize;g++){          
00623                 L.setAllValues(0.0);
00624                 // Estimate LU for the gaussian g
00625                 for(unsigned long j=0;j<_nb_sent;j++){
00626                         double *l_h_inv=_l_h_inv[j].getArray();
00627                         for(unsigned long k=0;k<_rang;k++)
00628                                 for(unsigned long l=0;l<_rang;l++) 
00629                                         LV[k*_rang+l]+=(l_h_inv[k*_rang+l]+X[j*_rang+k]*X[j*_rang+l])*N_h[j*_mixsize+g];
00630                 }
00631                 L.invert(L_Inv); 
00632                 double *L_InvV=L_Inv.getArray();        
00633                 
00634                 // Estimate LU for the line lineNum
00635                 for (unsigned long i=0;i<_vsize;i++) {
00636                         unsigned long lineNum=_vsize*g+i;                       
00637                         // estime RU i
00638                         R.setAllValues(0.0);
00639                         for(unsigned long j=0;j<_nb_sent;j++)
00640                                 for(unsigned long k=0;k<_rang;k++)
00641                                         RV[k]+=S_X_h[j*_supervsize+lineNum]*X[j*_rang+k];
00642                         // estime U i
00643                         for(unsigned long j=0;j<_rang;j++)
00644                                 for(unsigned long k=0;k<_rang;k++) 
00645                                         U[lineNum*_rang+j]+=L_InvV[j*_rang+k]*RV[k];
00646                 }
00647         }       
00648 };
00649 
00650 /*****************************************************************************************************
00651 ********************* Threaded Version of U Matrix Computation (Nico Scheffer)
00652 *****************************************************************************************************/
00653 #if defined(THREAD)
00654 struct Uthread_data{
00655         double *N_h;
00656         double *U;
00657         double *S_X_h;
00658         double *X;
00659         unsigned long rang;
00660         unsigned long sv;
00661         unsigned long vsize;
00662         unsigned long mixsize;          
00663         unsigned long nbsent;   
00664         unsigned long idxBottom;        
00665         unsigned long idxUp;
00666         RefVector <DoubleSquareMatrix>* L;
00667 };
00668 
00669 void *Uthread(void *threadarg) {
00670         struct Uthread_data *my_data;
00671         my_data = (struct Uthread_data *) threadarg;
00672         // Get data
00673         double *U = my_data->U;
00674         double *N_h=my_data->N_h;       
00675         double *S_X_h=my_data->S_X_h;   
00676         double *X=my_data->X;
00677         unsigned long _rang=my_data->rang;
00678         unsigned long _supervsize=my_data->sv;  
00679         unsigned long _nb_sent=my_data->nbsent;
00680         unsigned long _vsize=my_data->vsize;
00681         unsigned long _mixsize=my_data->mixsize;
00682         unsigned long idxBottom=my_data->idxBottom;
00683         unsigned long idxUp=my_data->idxUp;
00684         RefVector <DoubleSquareMatrix>& _l_h_inv=*(my_data->L);
00685 
00686         // Routine
00687         DoubleSquareMatrix L(_rang);
00688         DoubleSquareMatrix L_Inv(_rang);
00689         RealVector <double> R;
00690         R.setSize(_rang);
00691         double *RV=R.getArray();
00692         double *LV=L.getArray();        
00693         for (unsigned long g=idxBottom;g<idxUp;g++) {
00694                 L.setAllValues(0.0);
00695                 // Estimate LU for the gaussian g
00696                 for(unsigned long j=0;j<_nb_sent;j++){
00697                         double *l_h_inv=_l_h_inv[j].getArray();
00698                         for(unsigned long k=0;k<_rang;k++)
00699                                 for(unsigned long l=0;l<_rang;l++) 
00700                                         LV[k*_rang+l]+=(l_h_inv[k*_rang+l]+X[j*_rang+k]*X[j*_rang+l])*N_h[j*_mixsize+g];
00701                 }
00702                 L.invert(L_Inv); 
00703                 double *L_InvV=L_Inv.getArray();        
00704                 
00705                 // Estimate LU for the line lineNum
00706                 for (unsigned long i=0;i<_vsize;i++) {
00707                         unsigned long lineNum=_vsize*g+i;                       
00708                         // estime RU i
00709                         R.setAllValues(0.0);
00710                         for(unsigned long j=0;j<_nb_sent;j++)
00711                                 for(unsigned long k=0;k<_rang;k++)
00712                                         RV[k]+=S_X_h[j*_supervsize+lineNum]*X[j*_rang+k];
00713                         // estime U i
00714                         for(unsigned long j=0;j<_rang;j++)
00715                                 for(unsigned long k=0;k<_rang;k++) 
00716                                         U[lineNum*_rang+j]+=L_InvV[j*_rang+k]*RV[k];
00717                 }
00718         }
00719         //
00720         pthread_exit((void*) 0);
00721 }
00722 
00723 
00724 void FactorAnalysisStat::getUEstimateThreaded(unsigned long NUM_THREADS){
00725         if (verbose) cout << "(FactorAnalysisStat) Compute U Estimate Threaded "<<endl; 
00726         double *N_h=_matN_h.getArray(); 
00727         double *X=_matX.getArray();
00728         double *S_X_h=_matS_X_h.getArray();
00729         double *U=_matU.getArray();
00730         _matU.setAllValues(0.0);
00731         if (NUM_THREADS==0) throw Exception("Num threads can not be 0",__FILE__,__LINE__);
00732         int rc, status;
00733         if (NUM_THREADS > _mixsize) NUM_THREADS=_mixsize;
00734         struct Uthread_data thread_data_array[NUM_THREADS];
00735         unsigned long offset=_mixsize/NUM_THREADS;
00736         pthread_t threads[NUM_THREADS]; 
00737         pthread_attr_t attr;
00738         pthread_attr_init(&attr);
00739         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);    
00740         for(unsigned long t=0, idxBottom=0; t<NUM_THREADS; t++,idxBottom+=offset){
00741                 thread_data_array[t].N_h=N_h;
00742                 thread_data_array[t].U=U;
00743                 thread_data_array[t].S_X_h=S_X_h;
00744                 thread_data_array[t].X=X;                       
00745                 thread_data_array[t].rang=_rang;
00746                 thread_data_array[t].sv=_supervsize;
00747                 thread_data_array[t].vsize=_vsize;
00748                 thread_data_array[t].mixsize=_mixsize;          
00749                 thread_data_array[t].nbsent=_nb_sent;
00750                 thread_data_array[t].idxBottom=idxBottom;
00751                 unsigned long idxUp=idxBottom+offset;
00752                 if (_supervsize%NUM_THREADS!=0) idxUp++;                
00753                 thread_data_array[t].idxUp=idxUp;               
00754                 thread_data_array[t].L=&(_l_h_inv);
00755                 if (verbose) cout<<"(FactorAnalysisStat) Creating thread n["<< t<< "] for U, Gaussian ["<<idxBottom<<"-->"<<idxUp<<"]"<<endl;                   
00756                 rc = pthread_create(&threads[t], &attr, Uthread, (void *)&thread_data_array[t]);
00757                 if (rc) throw Exception("ERROR; return code from pthread_create() is ",__FILE__,rc);
00758         }
00759         pthread_attr_destroy(&attr);
00760         for(unsigned long t=0; t<NUM_THREADS; t++) {
00761                 rc = pthread_join(threads[t], (void **)&status);
00762                 if (rc)  throw Exception("ERROR; return code from pthread_join() is ",__FILE__,rc);
00763                 if (verboseLevel >1) cout <<"(FactorAnalysisStat)Completed join with thread ["<<t<<"] status["<<status<<"]"<<endl;
00764         }
00765         if (verboseLevel >1) cout << "(FactorAnalysisStat) Done " << endl;      
00766 };
00767 #endif
00768 /****************************************** End *********************************************/
00769 
00770 /*void FactorAnalysisStat::getLLK(Config & config){
00771         if (verbose) cout << "(FactorAnalysisStat) # Compute Likelihoods" << endl;              
00772         unsigned long loc,sent;
00773         unsigned long cnt=0;
00774         unsigned long maxLLKcomputed=1;
00775         if (config.existsParam("computeLLK")) maxLLKcomputed=config.getParam("computeLLK").toLong();    
00776         MixtureGD & UBM=_ms.getMixtureGD((unsigned long) 1);
00777         MixtureGDStat &acc=_ss.createAndStoreMixtureStat(UBM);          
00778         DoubleVector m_xh;
00779         m_xh.setSize(_supervsize);      
00780         
00781         // Compute Occupations and Statistics
00782         loc=0; sent=0; XLine *pline; String *pFile; fileList.rewind();
00783         double glob_llk=0.0, llk_sent;
00784 
00785         while((pline=fileList.getLine())!=NULL && cnt < maxLLKcomputed) { 
00786                 while((pFile=pline->getElement())!=NULL && cnt < maxLLKcomputed) {
00787                         cnt++;
00788                         String featureFileName=(*pFile);                        // Current file basename                                
00789                         FeatureServer fs(config,*pFile);
00790                         this->getSpeakerModel(UBM,*pFile);
00791                         
00792                         if (_topGauss) {
00793                                 TopGauss tg;
00794                                 tg.read(*pFile,config);
00795                                 llk_sent=tg.get(UBM,*pFile,config);//This does not work on top gauss
00796                         }
00797                         else {
00798                                 unsigned long begin=fs.getFirstFeatureIndexOfASource(featureFileName);
00799                                 fs.seekFeature(begin);
00800                                 
00801                                 // Usual SegServer stuff
00802                                 SegServer segmentsServer;
00803                                 LabelServer labelServer;
00804                                 initializeClusters(featureFileName,segmentsServer,labelServer,config);
00805                                 verifyClusterFile(segmentsServer,fs,config);
00806                                 unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(config.getParam("labelSelectedFrames"));
00807                                 SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);  
00808                                 acc.resetOcc();
00809                                 Seg *seg;          // current selected segment
00810                                 selectedSegments.rewind();                      // reset the reader at the begin of the input stream
00811 
00812                                 acc.resetLLK();
00813                                 while((seg=selectedSegments.getSeg())!=NULL){                                   
00814                                         unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); 
00815                                         fs.seekFeature(begin);
00816                                         Feature f;
00817                                         for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
00818                                                 fs.readFeature(f); 
00819                                                 acc.computeAndAccumulateLLK(f,1.0,DETERMINE_TOP_DISTRIBS);
00820                                         }               
00821                                 }
00822                                 llk_sent= acc.getMeanLLK();
00823                         }
00824                         if (verbose) cout << "(FactorAnalysisStat) # Mean LLK on [" << " " << featureFileName << "](" << sent << ")=" << llk_sent << endl ;
00825                         glob_llk +=llk_sent;
00826                         sent++;
00827                 }
00828                 loc++;
00829         }
00830         _ss.deleteMixtureStat(acc);     
00831         if (verbose) cout << "(FactorAnalysisStat) # Total Likelihood: " << glob_llk << endl;
00832 };*/
00833 
00835 void FactorAnalysisStat::getFactorAnalysisModel(MixtureGD& FA,String& file) {
00836         if (verbose) cout << "(FactorAnalysisStat) Compute Variance adapted Speaker Model"<<endl;               
00837         this->getTrueSpeakerModel(FA,file);
00838         unsigned long loc=_ndxTable.locNb(file);        
00839 
00841         RealVector <double> sigma_s;
00842         sigma_s.setSize(_supervsize);
00843         for (unsigned long i=0;i<_mixsize;i++)  
00844                 for (unsigned long j=0;j<_vsize;j++) 
00845                         sigma_s[i*_vsize+j]=FA.getDistrib(i).getCov(j)/(_tau+_matN(loc,i));
00846                 
00848         RealVector <double> sum,prod;
00849         sum.setSize(_supervsize);prod.setSize(_supervsize);
00850         for (unsigned long i=0;i<_mixsize;i++) {
00851                 for (unsigned long j=0;j<_vsize;j++) {
00852                         sum[i*_vsize+j]=sigma_s[i*_vsize+j]+FA.getDistrib(i).getCov(j);
00853                         //cout << "i,j"<<i<<","<<j<<" sigma_s "<<sigma_s[i*_vsize+j]<<" cov:"<<FA.getDistrib(i).getCov(j)<<" N"<<_N(loc,i)<<" "<<_tau<<endl;
00854                 }
00855         }
00856 
00857         for (unsigned long i=0;i<_mixsize;i++)
00858                 for (unsigned long j=0;j<_vsize;j++)
00859                         FA.getDistrib(i).setCov(sum[i*_vsize+j],j);
00860         FA.computeAll();
00861 }
00862 
00864 double FactorAnalysisStat::getLLK(SegCluster &selectedSegments,MixtureGD &model,FeatureServer&fs,Config & config){
00865         if (verbose) cout << "(FactorAnalysisStat) Compute Likelihood" << endl;         
00866         double llk=0.0;
00867         MixtureGDStat &acc=_ss.createAndStoreMixtureStat(model);                
00868         Seg *seg;        
00869         selectedSegments.rewind();      
00870         while((seg=selectedSegments.getSeg())!=NULL){                                   
00871                 unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); 
00872                 fs.seekFeature(begin);
00873                 Feature f;
00874                 for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
00875                         fs.readFeature(f); 
00876                         acc.computeAndAccumulateLLK(f,1.0,TOP_DISTRIBS_NO_ACTION);
00877                 }               
00878         }                               
00879         llk= acc.getMeanLLK();
00880         _ss.deleteMixtureStat(acc);             
00881 return llk;
00882 };
00883 
00884 // Set Y given a mixture model (substract world and divide by D)
00885 void FactorAnalysisStat::setYFromModel(MixtureGD& M,String & file){
00886         if (verbose) cout << "(FactorAnalysisStat) Set Y from Model" << endl;
00887         unsigned long loc=_ndxTable.locNb(file);        
00888         RealVector<double> v(_supervsize,_supervsize);
00889         modelToSv(M,v);
00890         RealVector<double> w(_supervsize,_supervsize);
00891         modelToSv(_ms.getMixtureGD(0),w); // get UBM
00892         for (unsigned long i=0;i<v.size();i++) 
00893                 _matY(loc,i)=(v[i]-w[i])/_D[i];
00894 };
00895 
00896 void FactorAnalysisStat::estimateXForKnownSpeaker(MixtureGD & M,String & file,Config &config) {
00897         RealVector <double> v(_supervsize,_supervsize);
00898         modelToSv(M,v); 
00899         this->resetXY();
00900         this->setYFromModel(M,file);      
00901         for(int i=0;i<config.getParam("nbTrainIt").toLong();i++){
00902                 if (verbose) cout << "(FactorAnalysisStat) ------ Iteration ["<<i<<"] ------"<<endl;
00903                 this->substractSpeakerStats();
00904                 this->getXEstimate();
00905         }
00906         double * X=_matX.getArray();
00907         for (unsigned long i=0;i<_supervsize;i++) {
00908                 double ux=0.0;
00909                 for (unsigned long j=0;j<_rang;j++) {
00910                         ux+=_matU(i,j)*X[j];
00911                 }
00912                 v[i]+=ux;
00913         }
00914         svToModel(v,M);
00915 };
00916 
00917 void FactorAnalysisStat::getUX(RealVector <double> &ux,String& file) {
00918         ux.setAllValues(0.0);   
00919         unsigned long idx=_ndxTable.sessionNb(file);
00920         for (unsigned long i=0;i<_supervsize;i++)
00921                 for (unsigned long j=0;j<_rang;j++) 
00922                         ux[i]+=_matU(i,j)*_matX(idx,j);
00923 };
00924 
00925 // Compute supervector of client M_s_h=M+Dy_s and get a model
00926 void FactorAnalysisStat::getTrueSpeakerModel(MixtureGD & M,String &file) {
00927         if (verbose) cout << "(FactorAnalysisStat) Compute True Speaker Model"<<endl;           
00928         RealVector <double> Sp(_supervsize,_supervsize);
00929         getMplusDY(Sp,file);
00930         svToModel(Sp,M);
00931 };
00932 
00933 // Compute supervector of client M_s_h=M+Dy_s and get a model
00934 void FactorAnalysisStat::getSessionModel(MixtureGD & M,String &file) {
00935         if (verbose) cout << "(FactorAnalysisStat) Compute Channel Model"<<endl;                
00936         RealVector <double> Sp(_supervsize,_supervsize);
00937         getUX(Sp,file);
00938         for (unsigned long i=0;i<_supervsize;i++)
00939                 Sp[i]+=_super_mean[i];
00940         svToModel(Sp,M);
00941 };
00942 
00943 // Compute supervector of client M_s_h=M+Dy_s
00944 void FactorAnalysisStat::getMplusDY(RealVector <double> &Sp, String& file) {
00945         Sp.setAllValues(0.0);
00946         unsigned long loc=_ndxTable.locNb(file);                
00947         for (unsigned long i=0;i<_supervsize;i++)
00948                 Sp[i]=_super_mean[i]+_D[i]*_matY(loc,i);
00949 };
00950 
00951 // Compute supervector of client M_s_h=M+Dy_s+Ux and get a model
00952 void FactorAnalysisStat::getSpeakerModel(MixtureGD & M,String& file) {  
00953         RealVector <double> Sp;Sp.setSize(_supervsize); 
00954         RealVector <double> ux;ux.setSize(_supervsize);                         
00955         this->getUX(ux,file);
00956         this->getMplusDY(Sp,file);
00957         for (unsigned long i=0;i<_supervsize;i++)
00958                 Sp[i]+=ux[i];
00959         svToModel(Sp,M);
00960 };
00961 
00963 void FactorAnalysisStat::normalizeFeatures(SegCluster &selectedSegments,FeatureServer &fs,Config & config){
00964         if (verbose) cout << "(FactorAnalysisStat) Normalize Features" << endl; 
00965         MixtureGD & clientMixture=_ms.getMixtureGD(1); // copy the UBM mixture          
00966         unsigned long nt=0;     
00967         RealVector <double> m_xh_1; m_xh_1.setSize(_supervsize);        
00968         double *_m_xh_1=m_xh_1.getArray();
00969         Seg *seg;          // current selectd segment
00970         selectedSegments.rewind();
00971         String currentSource="";
00972         while((seg=selectedSegments.getSeg())!=NULL){                   
00973                 unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); 
00974                 if (currentSource!=seg->sourceName()) {
00975                         currentSource=seg->sourceName();
00976                         this->getUX(m_xh_1,currentSource);
00977                         this->getSpeakerModel(clientMixture,currentSource);                     
00978                         if (verbose)cout << "Processing speaker["<<currentSource<<"]"<< endl;   
00979                 }               
00980                 fs.seekFeature(begin);
00981                 Feature f;
00982                 if (!_topGauss) {
00983                         for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
00984                                 fs.readFeature(f,0);
00985                                 double *ff=f.getDataVector();                           
00986                                 double sum=0.0;
00987                                 RealVector <double> P;
00988                                 P.setSize(_mixsize);
00989                                 double *Prob=P.getArray();
00990                                 for(unsigned long k=0;k<_mixsize;k++) {
00991                                         Prob[k]=clientMixture.weight(k)*clientMixture.getDistrib(k).computeLK(f);
00992                                         sum+=Prob[k];
00993                                         }
00994                                 for(unsigned long k=0;k<_mixsize;k++) 
00995                                         Prob[k]/=sum; 
00996                                 for(unsigned long k=0;k<_mixsize;k++) {
00997                                         for (unsigned long i=0;i<_vsize;i++) 
00998                                                 ff[i]-= Prob[k]*_m_xh_1[k*_vsize+i];
00999                                         }
01000                                 fs.writeFeature(f);
01001                                 nt++;           
01002                         }       
01003                 }
01004                 else {
01005                         throw Exception("no topgauss yet",__FILE__,__LINE__);
01006                 }
01007         }
01008 };      
01009 
01010 /*void FactorAnalysisStat::normalizeFeatures(TopGauss &tg,SegCluster &selectedSegments,FeatureServer &fs,Config & config){
01011         if (verbose) cout << "(FactorAnalysisStat) Normalize Features" << endl;                 
01012         unsigned long nbg, k1;
01013         unsigned long nt=0;
01014         RealVector <double> m_xh_1; m_xh_1.setSize(_supervsize);        
01015         double *_m_xh_1=m_xh_1.getArray();
01016         Seg *seg;          // current selectd segment
01017         selectedSegments.rewind();
01018         
01019         unsigned long*_idx=tg.idx().getArray();
01020         unsigned long*_nbg=tg.nbg().getArray();         
01021 
01022         while((seg=selectedSegments.getSeg())!=NULL){                   
01023                 unsigned long begin=seg->begin()+fs.getFirstFeatureIndexOfASource(seg->sourceName()); 
01024                 fs.seekFeature(begin);
01025                 Feature f;
01026                 unsigned long idxBegin=tg.frameToIdx(nt); // get the begin index of gaussians in idx vectors                    
01027                 for (unsigned long idxFrame=0;idxFrame<seg->length();idxFrame++){
01028                         fs.readFeature(f,0);
01029                         double* ff=f.getDataVector();
01030                         nbg=_nbg[nt]; // get nb gauss for this frame                            
01031                         double sum=0.0;
01032                         RealVector <double> P;
01033                         P.setSize(nbg);
01034                         double *Prob=P.getArray();
01035                         for(unsigned long k=0;k<nbg;k++) {
01036                                 Prob[k]=clientMixture.weight(_idx[k+idxBegin])*clientMixture.getDistrib(_idx[k+idxBegin]).computeLK(f);
01037                                 sum+=Prob[k];
01038                                 }
01039                         for(unsigned long k=0;k<nbg;k++) 
01040                                 Prob[k]/=sum; 
01041                         for(unsigned long k=0;k<nbg;k++) {
01042                                 k1=_idx[k+idxBegin];
01043                                 for (unsigned long i=0;i<_vsize;i++) 
01044                                         ff[i]-= Prob[k]*_m_xh_1[k1*_vsize+i];
01045                                 }
01046                         fs.writeFeature(f);
01047                         nt++;
01048                         idxBegin+=nbg;
01049                 }
01050         }               
01051 };*/
01052 
01053 void FactorAnalysisStat::normalizeFeatures(FeatureServer &fs,Config & config){                  
01054         SegServer segmentsServer;
01055         LabelServer labelServer;
01056         initializeClusters(fileList,segmentsServer,labelServer,config);
01057         verifyClusterFile(segmentsServer,fs,config);
01058         unsigned long codeSelectedFrame=labelServer.getLabelIndexByString(config.getParam("labelSelectedFrames"));
01059         SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);  
01060         normalizeFeatures(selectedSegments,fs,config);
01061 };
01062 
01063 void FactorAnalysisStat::estimateXYAndNorm(FeatureServer &fs,Config &config) {
01064         this->resetXY();
01065 
01066         for(int i=0;i<config.getParam("nbTrainIt").toLong();i++){
01067                 if (verbose) cout << "------ Iteration ["<<i<<"] ------"<<endl;
01068                 this->computeAndAccumulateGeneralFAStats(fs,config);
01069                 this->substractSpeakerStats();
01070                 this->substractChannelStats(); 
01071                 this->estimateAndInverseL(config);
01072                 this->getXEstimate();
01073                 this->getYEstimate();
01074           }
01075         this->normalizeFeatures(fs,config);
01076 };
01077 
01078 void FactorAnalysisStat::estimateXYAndNorm(SegCluster &selectedSegments,FeatureServer &fs,Config &config) {
01079         this->resetXY();
01080         for(int i=0;i<config.getParam("nbTrainIt").toLong();i++){
01081                 if (verbose) cout << "------ Iteration ["<<i<<"] ------"<<endl;
01082                 this->computeAndAccumulateGeneralFAStats(selectedSegments,fs,config);
01083                 this->substractSpeakerStats();
01084                 this->substractChannelStats(); 
01085                 this->estimateAndInverseL(config);
01086                 this->getXEstimate();
01087                 this->getYEstimate();
01088           }
01089         this->normalizeFeatures(selectedSegments,fs,config);
01090 };
01091 #endif