00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #if !defined(ALIZE_CovIntra_cpp)
00056 #define ALIZE_CovIntra_cpp
00057
00058 #include <iostream>
00059 #include <fstream>
00060 #include <cstdio>
00061 #include <cassert>
00062 #include <cmath>
00063 #include <liatools.h>
00064 #include "CovIntra.h"
00065 extern "C" {
00066 #include "svdlib.h"
00067 }
00068
00069 #if defined(_WIN32)
00070 #include <cfloat>
00071 #define ISNAN(x) _isnan(x)
00072 #define ISINF(x) (!_finite(x))
00073 #elif defined(linux) || defined(__linux) || defined(__CYGWIN__) || defined(__APPLE__)
00074 #define ISNAN(x) isnan(x)
00075 #define ISINF(x) isinf(x)
00076 #else
00077 #error "Unsupported OS\n"
00078 #endif
00079
00080
00081 #define myTINY 1e-11
00082 using namespace std;
00083 using namespace alize;
00084
00085
00086 void dividesSvByInteger(RealVector <double> & v, unsigned long nb) {
00087 if (nb==0) throw Exception("Divides by 0!",__FILE__,__LINE__);
00088 for (unsigned long j=0;j<v.size();j++)
00089 v[j]/=nb;
00090 }
00091
00092
00093 void dividesSvByInteger(Matrix <double> & v, unsigned long nb) {
00094 if (nb==0) throw Exception("Divides by 0!",__FILE__,__LINE__);
00095 for (unsigned long j=0;j<v.cols();j++)
00096 v(0,j)/=nb;
00097 }
00098
00099 bool badSv(Matrix <double> & v) {
00100 for (unsigned long j=0;j<v.cols();j++) {
00101 if (abs(v(0,j))>myTINY) return false;
00102 if (ISNAN(v(0,j)) || ISINF(v(0,j))) return true;
00103 }
00104 return true;
00105 }
00106
00107 void loadMeanSv(String id,Matrix <double> & v,Config & config) {
00108 MixtureServer ms(config);
00109 MixtureGD & curr=ms.loadMixtureGD(id);
00110 RealVector <double> currSv;
00111 if (config.getParam("vsize").toLong()!= (long)(ms.getDistribCount()*ms.getVectSize())) throw Exception("VectSize mismatch, check vsize parameter",__FILE__,__LINE__);
00112 currSv.setSize(config.getParam("vsize").toLong());
00113 if (config.existsParam("klgmm")) getKLVector(curr,currSv,config);
00114 else modelToSv(curr,currSv);
00115 v.setDimensions(1,currSv.size());
00116 for (unsigned long j=0;j<currSv.size();j++)
00117 v(0,j)=currSv[j];
00118 }
00119
00120 template <class T> class RealVectorStat {
00121 private:
00122 unsigned long _size;
00123 unsigned long _nb;
00124 RealVector <T> _xAcc;
00125 RealVector <T> _xxAcc;
00126 RealVector <double> _mean;
00127 RealVector <double> _covInv;
00128 public:
00129 explicit RealVectorStat(unsigned long size) {
00130 _size=size;
00131 _nb=0;
00132 _xAcc.setSize(_size);_xxAcc.setSize(_size);_mean.setSize(_size);_covInv.setSize(_size);
00133 _xAcc.setAllValues(0);_xxAcc.setAllValues(0);_mean.setAllValues(0.0);_covInv.setAllValues(0.0);
00134 }
00135 ~ RealVectorStat() {};
00136 void acc(RealVector <T> &v) {
00137 if (_size!=v.size()) throw Exception("(RealVectorStat) size does not match!",__FILE__,__LINE__);
00138 for (unsigned long i=0;i<v.size();i++) {
00139 _xAcc[i]+=v[i];
00140 _xxAcc[i]+=v[i]*v[i];
00141 }
00142 _nb++;
00143 };
00144 RealVector <double> & covInv() {
00145 if (_nb==0) throw Exception("(RealVectorStat) Nothing accumulated!",__FILE__,__LINE__);
00146 for (unsigned long i=0;i<_size;i++) {
00147 _mean[i]=((double)_xAcc[i])/_nb;
00148 _covInv[i]=1/((((double)_xxAcc[i])/_nb)-(_mean[i]*_mean[i]));
00149 }
00150 return _covInv;
00151 };
00152 RealVector <double> & mean() {
00153 if (_nb==0) throw Exception("(RealVectorStat) Nothing accumulated!",__FILE__,__LINE__);
00154 for (unsigned long i=0;i<_size;i++)
00155 _mean[i]=((double)_xAcc[i])/_nb;
00156 return _mean;
00157 };
00158 };
00159
00160 int CovIntra(Config & config) {
00161 try {
00162 bool gmm=false;
00163 if (config.existsParam("gmm")) {if(verbose) cout << "(CovIntra) Gmm mode: reading SV from gmm models"<<endl;gmm=true;}
00164 bool svd=false;
00165 if (config.existsParam("svd")) {if(verbose) cout << "(CovIntra) Computing the SVD"<<endl;svd=true;}
00166 if (config.existsParam("klgmm")) {if(verbose) cout << "(CovIntra) Gmm KL mode: computing KL distance from gmm models"<<endl;gmm=true;}
00167 SVDVerbosity=verboseLevel;
00168 XList fileList(config.getParam("ndx"),config);
00169 XLine *pline;
00170 String *pModel;
00171 unsigned long svSize=config.getParam("vsize").toLong();
00172 unsigned long nbSpeakers=fileList.getLineCount();
00173 if (config.existsParam("nbSpeakers") && config.getParam("nbSpeakers").toLong() <= (long) nbSpeakers) nbSpeakers=config.getParam("nbSpeakers").toLong();
00174
00175
00176 unsigned long nbEx=0;
00177 for (unsigned long s=0;s<nbSpeakers;s++)
00178 nbEx+=fileList.getLine(s).getElementCount();
00179 fileList.rewind();
00180 Matrix <double> UBMsv;
00181 loadMeanSv(config.getParam("inputWorldFilename"),UBMsv,config);
00182 DMat CCt=svdNewDMat(svSize,nbEx);
00183 RealVectorStat <double> acc(svSize);
00184 if (verbose) cout<<"Channel Matrix dimension: "<<svSize<<","<<nbEx <<endl << "Speaker Matrix dimension: "<<svSize<<","<<nbSpeakers<<endl;
00185 unsigned long idx=0;
00186 for (unsigned long r=0;r<nbSpeakers;r++) {
00187 pline=fileList.getLine();
00188 if (verbose) cout << "Sp ["<<r<<"] " <<pline->getElementCount() << " sessions, " <<endl;
00189
00190 Matrix <double> meanSv;
00191 meanSv.setDimensions(1,svSize);
00192 while((pModel=pline->getElement())!=NULL) {
00193 if (verboseLevel > 1) cout << "Load " <<*pModel<<endl;
00194 String filename;
00195 Matrix <double> currSv;
00196 if (!gmm) currSv.load(config.getParam("vectorFilesPath")+*pModel+config.getParam("vectorFilesExtension"),config);
00197 else loadMeanSv(*pModel,currSv,config);
00198 meanSv+=currSv;
00199 }
00200
00201
00202 RealVector <double> vm;
00203 for (unsigned long i=0;i<meanSv.cols();i++) {
00204 double val=meanSv(0,i)/(pline->getElementCount());
00205 val-=UBMsv(0,i);
00206 vm.addValue(val);
00207 }
00208 acc.acc(vm);
00209
00210
00211 for (unsigned long c=0;c<pline->getElementCount();c++) {
00212 Matrix <double> currSv;
00213 if (!gmm) currSv.load(config.getParam("vectorFilesPath")+pline->getElement(c)+config.getParam("vectorFilesExtension"),config);
00214 else loadMeanSv(pline->getElement(c),currSv,config);
00215 Matrix <double> meanMinusCurrent(meanSv);
00216 meanMinusCurrent-=currSv;
00217 dividesSvByInteger(meanMinusCurrent,(pline->getElementCount()-1));
00218 currSv-=meanMinusCurrent;
00219 if (debug && badSv(currSv)) cout <<pline->getElement(c)<<" gives a bad channel supervector (zero|inf|nan value)"<<endl;
00220
00221
00222 for(unsigned long val=0;val<currSv.cols(); val++) {
00223 CCt->value[val][idx]=currSv(0,val);
00224 if(abs(CCt->value[val][idx])<myTINY) CCt->value[val][idx]=0.0;
00225 }
00226 idx++;
00227 }
00228 }
00229
00230 RealVector <double>& interSp=acc.mean();
00231 ((Matrix <double>)interSp).saveDT((String)"mean.inter",config);
00232
00233 String filename=config.getParam("channelMatrix");
00234 char *out=strdup(filename.c_str());
00235 if (verbose && !svd) cout << "(CovIntra) Covariance matrix saved in " << config.getParam("channelMatrix")<< ", need to perform eigenvalue analysis yourself or add --svd flag to the config file" <<endl;
00236 svdWriteDenseMatrix(CCt,out, SVD_F_DB);
00237 free(out);
00238 if (!svd) exit(1);
00239
00240
00241 unsigned long nbIt=0;
00242 double kappa=1e-6;
00243 double las2end[2] = {-1.0e-30, 1.0e-30};
00244 if (config.existsParam("nbIt")) nbIt=config.getParam("nbIt").toLong();
00245 if (config.existsParam("kappa")) kappa=config.getParam("kappa").toDouble();
00246 if (config.existsParam("bound")) {
00247 las2end[1] = config.getParam("bound").toDouble();
00248 las2end[0] = -las2end[1];
00249 }
00250
00251 SMat SCCt=svdConvertDtoS(CCt);
00252 svdFreeDMat(CCt);
00253 for(int i=0;i<SCCt->vals;i++)
00254 if (ISNAN(SCCt->value[i]) || ISINF(SCCt->value[i])) throw Exception("Error:nan or inf in sparse matrix file",__FILE__,__LINE__);
00255 unsigned long nbEv=config.getParam("nbEigenVectors").toLong();
00256 if (verbose) cout << "(CovIntra) Begin eigenValue problem resolution (using Doug Rohde's SVD C Library)" << endl;
00257 SVDRec res=svdLAS2(SCCt,nbEv,nbIt,las2end,kappa);
00258 svdFreeSMat(SCCt);
00259
00260 Matrix <double> ev(1,res->d);
00261 for (int i=0;i<res->d;i++) ev(0,i)=res->S[i];
00262 String evFile=config.getParam("channelMatrix")+".S";
00263 if (verbose) cout << "(CovIntra) Singluar Values (square root) in " <<evFile<< endl;
00264 ev.saveDT(evFile,config);
00265
00266 Matrix <double> NAP(res->Ut->rows,res->Ut->cols);
00267 if (verbose) cout<< "(CovIntra) Dimensions of U: ("<<NAP.rows()<<","<<NAP.cols()<<")"<< endl;
00268 for (int i=0;i<res->Ut->rows;i++)
00269 for (int j=0;j<res->Ut->cols;j++)
00270 NAP(i,j)=res->Ut->value[i][j];
00271 svdFreeSVDRec(res);
00272 if (verbose) cout << "(CovIntra) U saved in " << config.getParam("channelMatrix")<<endl;
00273 NAP.save(config.getParam("channelMatrix"),config);
00274 }
00275 catch (Exception& e) {cout << e.toString() << endl;}
00276 return 0;
00277 }
00278
00279
00280
00281 #endif