MixtureStat.cpp

Go to the documentation of this file.
00001 /*
00002         This file is part of ALIZE which is an open-source tool for 
00003         speaker recognition.
00004 
00005     ALIZE is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU Lesser General Public License as 
00007     published by the Free Software Foundation, either version 3 of 
00008     the License, or any later version.
00009 
00010     ALIZE is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public 
00016     License along with ALIZE.
00017     If not, see <http://www.gnu.org/licenses/>.
00018         
00019         ALIZE is a development project initiated by the ELISA consortium
00020         [alize.univ-avignon.fr/] and funded by the French Research 
00021         Ministry in the framework of the TECHNOLANGUE program 
00022         [www.technolangue.net]
00023 
00024         The ALIZE project team wants to highlight the limits of voice
00025         authentication in a forensic context.
00026         The "Person  Authentification by Voice: A Need of Caution" paper 
00027         proposes a good overview of this point (cf. "Person  
00028         Authentification by Voice: A Need of Caution", Bonastre J.F., 
00029         Bimbot F., Boe L.J., Campbell J.P., Douglas D.A., Magrin-
00030         chagnolleau I., Eurospeech 2003, Genova].
00031         The conclusion of the paper of the paper is proposed bellow:
00032         [Currently, it is not possible to completely determine whether the 
00033         similarity between two recordings is due to the speaker or to other 
00034         factors, especially when: (a) the speaker does not cooperate, (b) there 
00035         is no control over recording equipment, (c) recording conditions are not 
00036         known, (d) one does not know whether the voice was disguised and, to a 
00037         lesser extent, (e) the linguistic content of the message is not 
00038         controlled. Caution and judgment must be exercised when applying speaker 
00039         recognition techniques, whether human or automatic, to account for these 
00040         uncontrolled factors. Under more constrained or calibrated situations, 
00041         or as an aid for investigative purposes, judicious application of these 
00042         techniques may be suitable, provided they are not considered as infallible.
00043         At the present time, there is no scientific process that enables one to 
00044         uniquely characterize a person=92s voice or to identify with absolute 
00045         certainty an individual from his or her voice.]
00046         Contact Jean-Francois Bonastre for more information about the licence or
00047         the use of ALIZE
00048 
00049         Copyright (C) 2003-2010
00050         Laboratoire d'informatique d'Avignon [lia.univ-avignon.fr]
00051         ALIZE admin [alize@univ-avignon.fr]
00052         Jean-Francois Bonastre [jean-francois.bonastre@univ-avignon.fr]
00053 */
00054 
00055 #if !defined(ALIZE_MixtureStat_cpp)
00056 #define ALIZE_MixtureStat_cpp
00057 
00058 //#include <cmath>
00059 #include "MixtureStat.h"
00060 #include "alizeString.h"
00061 #include "Mixture.h"
00062 #include "Distrib.h"
00063 #include "Exception.h"
00064 #include "Feature.h"
00065 #include "Config.h"
00066 #include "RealVector.h"
00067 #include "StatServer.h"
00068 
00069 using namespace alize;
00070 typedef MixtureStat S;
00071 //-------------------------------------------------------------------------
00072 S::MixtureStat(StatServer& ss, const Mixture& m, const Config& c)
00073 :Object(), _distribCount(m.getDistribCount()), _pMixture(&m), _config(c), 
00074  _minLLK(c.getParam_minLLK()), _maxLLK(c.getParam_maxLLK()), _llk(0),
00075  _accumulatedLLK(0), _occVect(_distribCount, _distribCount),
00076  _accumulatedOccVect(_distribCount, _distribCount),
00077  _meanOccVect(_distribCount, _distribCount), _resetedEM(false),
00078  _pStatServer(&ss), _featureCounterForEM(0.0)
00079 {
00080   resetLLK();
00081   resetOcc();
00082 }
00083 //-------------------------------------------------------------------------
00084 Mixture& S::getMixture() const { return const_cast<Mixture&>(*_pMixture); }
00085 //-------------------------------------------------------------------------
00086 lk_t S::computeLLK(const Feature& f)
00087 { return _llk =  _pStatServer->computeLLK(*_pMixture, f); }
00088 //-------------------------------------------------------------------------
00089 lk_t S::computeLLK(const Feature& f, unsigned long idx)
00090 { return _llk =  _pStatServer->computeLLK(*_pMixture, f, idx); }
00091 //-------------------------------------------------------------------------
00092 lk_t S::getLLK() const { return _llk; }
00093 //-------------------------------------------------------------------------
00094 void S::resetLLK()
00095 {
00096   _accumulatedLLK = 0.0;
00097   _featureCounterForAccumulatedLK = 0.0;
00098 }
00099 //-------------------------------------------------------------------------
00100 lk_t S::accumulateLLK(lk_t llk, double w)
00101 {
00102   _accumulatedLLK += (_llk = llk*w);
00103   _featureCounterForAccumulatedLK += w;
00104   return llk;
00105 }
00106 //-------------------------------------------------------------------------
00107 lk_t S::computeAndAccumulateLLK()
00108 {
00109   lk_t llk = _pStatServer->computeLLK(K::k, *_pMixture);
00110   return accumulateLLK(llk, 1.0);
00111 }
00112 //-------------------------------------------------------------------------
00113 lk_t S::computeAndAccumulateLLK(const Feature& f, double w,
00114                                 const TopDistribsAction& a)
00115 {
00116   lk_t llk = _pStatServer->computeLLK(K::k, *_pMixture, f, a);
00117   return accumulateLLK(llk, w);
00118 }
00119 //-------------------------------------------------------------------------
00120 lk_t S::computeAndAccumulateLLK(const Feature& f, 
00121                 const LKVector& topDistribsVector, double w)
00122 {
00123   lk_t llk = _pStatServer->computeLLK(K::k, *_pMixture, f, topDistribsVector);
00124   return accumulateLLK(llk, w);
00125 }
00126 //-------------------------------------------------------------------------
00127 lk_t S::getAccumulatedLLK() const { return _accumulatedLLK; }
00128 //-------------------------------------------------------------------------
00129 lk_t S::getMeanLLK() const
00130 {
00131   if (_featureCounterForAccumulatedLK == 0.0)
00132     throw Exception("No features -> no mean", __FILE__, __LINE__);
00133   return _accumulatedLLK/_featureCounterForAccumulatedLK;
00134 }
00135 //-------------------------------------------------------------------------
00136 //const DoubleVector& S::getDistribLKVect() { return _distribLKVect; }
00137 //-------------------------------------------------------------------------
00138 void S::resetOcc()
00139 {
00140   _accumulatedOccVect.setAllValues(0.0);
00141   _featureCounterForAccumulatedOcc = 0.0;
00142 }
00143 //-------------------------------------------------------------------------
00144 real_t S::computeAndAccumulateOcc(const Feature& f, weight_t w)
00145 {
00146   real_t sum = computeOccVect(f);
00147   _accumulatedOccVect += (_occVect *= w);
00148   _featureCounterForAccumulatedOcc += w;
00149   return sum;
00150 }
00151 //-------------------------------------------------------------------------
00152 // calcule la contribution de la trame à chaque distribution de la mixture
00153 // -> _occVect[nb distrib]
00154 // 0 < occ(distrib) <= 1
00155 //-------------------------------------------------------------------------
00156 real_t S::computeOccVect(const Feature& f) // private
00157 {
00158   // source : Amiral AppMM_IterationApp.c ContributionTrame(...)
00159 
00160   // EPS_APP : Utilise pour tester si une trame a un poids total
00161   // non negligeable
00162 
00163   const real_t EPS_APP = 1e-200;
00164 
00165   occ_t sum = 0.0;
00166   unsigned long c;
00167   weight_t* weightVect  = _pMixture->getTabWeight().getArray();
00168   Distrib** distribVect = _pMixture->getTabDistrib();
00169   occ_t*  occVect   = _occVect.getArray(); 
00170 
00171   for (c=0; c<_distribCount; c++)
00172   {
00173     Distrib* d = distribVect[c];
00174     occVect[c] = weightVect[c] * d->computeLK(f);
00175     sum += _occVect[c];
00176   }
00177   if (sum > EPS_APP) /* si la trame a un poids non negligeable */
00178   {
00179     for (c=0; c<_distribCount; c++)
00180     { _occVect[c] /= sum; } /* normalisation   Somme des occ = 1 */
00181   }
00182   else /* si la trame a un poids negligeable */
00183   {
00184     for (c=0; c<_distribCount; c++)
00185     {
00186       //if (_occVect[c] != 0.0)
00187         _occVect[c] = EPS_APP;
00188     }
00189     sum  = EPS_APP;
00190   }
00191   return sum;
00192 }
00193 //-------------------------------------------------------------------------
00194 DoubleVector& S::getOccVect() { return _occVect; }
00195 //-------------------------------------------------------------------------
00196 const DoubleVector& S::getOccVect() const { return _occVect; }
00197 //-------------------------------------------------------------------------
00198 const DoubleVector& S::getAccumulatedOccVect() const
00199 { return _accumulatedOccVect; }
00200 //-------------------------------------------------------------------------
00201 DoubleVector& S::getAccumulatedOccVect() { return _accumulatedOccVect; }
00202 //-------------------------------------------------------------------------
00203 occ_t S::getAccumulatedOcc()
00204 { return _accumulatedOccVect.computeSum(); }
00205 //-------------------------------------------------------------------------
00206 real_t S::getAccumulatedOccFeatureCount() const
00207 { return _featureCounterForAccumulatedOcc; }
00208 //-------------------------------------------------------------------------
00209 double S::getAccumulatedLLKFeatureCount() const
00210 { return _featureCounterForAccumulatedLK; }
00211 //-------------------------------------------------------------------------
00212 real_t S::getEMFeatureCount() const
00213 { return _featureCounterForEM; }
00214 //-------------------------------------------------------------------------
00215 DoubleVector& S::getMeanOccVect()
00216 {
00217   if (_featureCounterForAccumulatedOcc == 0.0)
00218     throw Exception("no occ accumulated", __FILE__, __LINE__);
00219 
00220   occ_t* meanOccVect = _meanOccVect.getArray();
00221   for (unsigned long c=0; c<_distribCount; c++)
00222     meanOccVect[c] = _accumulatedOccVect[c]
00223              / _featureCounterForAccumulatedOcc;
00224   return _meanOccVect;
00225 }
00226 //-------------------------------------------------------------------------
00227 void S::assertResetEMDone() const
00228 {
00229   if (!_resetedEM)
00230     throw Exception("EM not reseted", __FILE__, __LINE__);
00231 }
00232 //-------------------------------------------------------------------------
00233 String S::toString() const
00234 // TODO : a completer
00235 {
00236   return Object::toString()
00237     + "\n  id        = '" + _pMixture->getId() + "'"
00238     + "\n  llk       = " + String::valueOf(_llk)
00239     + "\n  accum llk     = " + String::valueOf(_accumulatedLLK)
00240     + "\n  feature counter = "
00241             + String::valueOf(_featureCounterForAccumulatedLK);
00242 }
00243 //-------------------------------------------------------------------------
00244 S::~MixtureStat() {}
00245 //-------------------------------------------------------------------------
00246 
00247 #endif // !defined(ALIZE_MixtureStat_cpp)