FKFeatures.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 1999-2008 Soeren Sonnenburg
00008  * Written (W) 1999-2008 Gunnar Raetsch
00009  * Copyright (C) 1999-2008 Fraunhofer Institute FIRST and Max-Planck-Society
00010  */
00011 
00012 #include "features/FKFeatures.h"
00013 #include "features/StringFeatures.h"
00014 #include "lib/io.h"
00015 
00016 CFKFeatures::CFKFeatures(INT size, CHMM* p, CHMM* n)
00017 : CRealFeatures(size)
00018 {
00019     pos_prob=NULL;
00020     neg_prob=NULL;
00021     weight_a=-1;
00022     set_models(p,n);
00023 }
00024 
00025 CFKFeatures::CFKFeatures(const CFKFeatures &orig)
00026 : CRealFeatures(orig), pos(orig.pos), neg(orig.neg), weight_a(orig.weight_a)
00027 { 
00028 }
00029 
00030 CFKFeatures::~CFKFeatures()
00031 {
00032     SG_UNREF(pos);
00033     SG_UNREF(neg);
00034 }
00035 
00036 double CFKFeatures::deriv_a(double a, INT dimension)
00037 {
00038     CStringFeatures<WORD> *Obs=pos->get_observations() ;
00039     double deriv=0.0 ;
00040     INT i=dimension ;
00041 
00042     if (dimension==-1)
00043     {
00044         for (i=0; i<Obs->get_num_vectors(); i++)
00045         {
00046             //double pp=pos->model_probability(i) ;
00047             //double pn=neg->model_probability(i) ;
00048             double pp=(pos_prob) ? pos_prob[i] : pos->model_probability(i);
00049             double pn=(neg_prob) ? neg_prob[i] : neg->model_probability(i);
00050             double sub=pp ;
00051             if (pn>pp) sub=pn ;
00052             pp-=sub ;
00053             pn-=sub ;
00054             pp=exp(pp) ;
00055             pn=exp(pn) ;
00056             double p=a*pp+(1-a)*pn ;
00057             deriv+=(pp-pn)/p ;
00058 
00059             /*double d1=(pp-pn)/p ;
00060               pp=exp(pos->model_probability(i)) ;
00061               pn=exp(neg->model_probability(i)) ;
00062               p=a*pp+(1-a)*pn ;
00063               double d2=(pp-pn)/p ;
00064               fprintf(stderr, "d1=%e  d2=%e,  d1-d2=%e\n",d1,d2) ;*/
00065         } ;
00066     } else
00067     {
00068         double pp=pos->model_probability(i) ;
00069         double pn=neg->model_probability(i) ;
00070         double sub=pp ;
00071         if (pn>pp) sub=pn ;
00072         pp-=sub ;
00073         pn-=sub ;
00074         pp=exp(pp) ;
00075         pn=exp(pn) ;
00076         double p=a*pp+(1-a)*pn ;
00077         deriv+=(pp-pn)/p ;
00078     } ;
00079 
00080     return deriv ;
00081 }
00082 
00083 
00084 double CFKFeatures::set_opt_a(double a)
00085 {
00086     if (a==-1)
00087     {
00088         SG_INFO( "estimating a.\n");
00089         pos_prob=new double[pos->get_observations()->get_num_vectors()];
00090         neg_prob=new double[pos->get_observations()->get_num_vectors()];
00091         for (INT i=0; i<pos->get_observations()->get_num_vectors(); i++)
00092         {
00093             pos_prob[i]=pos->model_probability(i) ;
00094             neg_prob[i]=neg->model_probability(i) ;
00095         }
00096 
00097         double la=0;
00098         double ua=1;
00099         a=(la+ua)/2;
00100         while (CMath::abs(ua-la)>1e-6)
00101         {
00102             double da=deriv_a(a);
00103             if (da>0)
00104                 la=a;
00105             if (da<=0)
00106                 ua=a;
00107             a=(la+ua)/2;
00108             SG_INFO( "opt_a: a=%1.3e  deriv=%1.3e  la=%1.3e  ua=%1.3e\n", a, da, la ,ua);
00109         }
00110         delete[] pos_prob;
00111         delete[] neg_prob;
00112         pos_prob=NULL;
00113         neg_prob=NULL;
00114     }
00115 
00116     weight_a=a;
00117     SG_INFO( "setting opt_a: %g\n", a);
00118     return a;
00119 }
00120 
00121 void CFKFeatures::set_models(CHMM* p, CHMM* n)
00122 {
00123     ASSERT(p && n);
00124     SG_REF(p);
00125     SG_REF(n);
00126 
00127     pos=p; 
00128     neg=n;
00129     set_num_vectors(0);
00130 
00131     free_feature_matrix();
00132 
00133     SG_INFO( "pos_feat=[%i,%i,%i,%i],neg_feat=[%i,%i,%i,%i]\n", pos->get_N(), pos->get_N(), pos->get_N()*pos->get_N(), pos->get_N()*pos->get_M(), neg->get_N(), neg->get_N(), neg->get_N()*neg->get_N(), neg->get_N()*neg->get_M()) ;
00134 
00135     if (pos && pos->get_observations())
00136         set_num_vectors(pos->get_observations()->get_num_vectors());
00137     if (pos && neg)
00138         num_features=1+pos->get_N()*(1+pos->get_N()+1+pos->get_M()) + neg->get_N()*(1+neg->get_N()+1+neg->get_M()) ;
00139 }
00140 
00141 DREAL* CFKFeatures::compute_feature_vector(INT num, INT &len, DREAL* target)
00142 {
00143   DREAL* featurevector=target;
00144   
00145   if (!featurevector)
00146     featurevector=new DREAL[ 1+pos->get_N()*(1+pos->get_N()+1+pos->get_M()) + neg->get_N()*(1+neg->get_N()+1+neg->get_M()) ];
00147   
00148   if (!featurevector)
00149     return NULL;
00150   
00151   compute_feature_vector(featurevector, num, len);
00152 
00153   return featurevector;
00154 }
00155 
00156 void CFKFeatures::compute_feature_vector(DREAL* featurevector, INT num, INT& len)
00157 {
00158     INT i,j,p=0,x=num;
00159 
00160     double posx=pos->model_probability(x);
00161     double negx=neg->model_probability(x);
00162 
00163     len=1+pos->get_N()*(1+pos->get_N()+1+pos->get_M()) + neg->get_N()*(1+neg->get_N()+1+neg->get_M());
00164 
00165     featurevector[p++] = deriv_a(weight_a, x);
00166     double px=CMath::logarithmic_sum(posx+log(weight_a),negx+log(1-weight_a)) ;
00167 
00168     //first do positive model
00169     for (i=0; i<pos->get_N(); i++)
00170     {
00171         featurevector[p++]=weight_a*exp(pos->model_derivative_p(i, x)-px);
00172         featurevector[p++]=weight_a*exp(pos->model_derivative_q(i, x)-px);
00173 
00174         for (j=0; j<pos->get_N(); j++) {
00175             featurevector[p++]=weight_a*exp(pos->model_derivative_a(i, j, x)-px);
00176         }
00177 
00178         for (j=0; j<pos->get_M(); j++) {
00179             featurevector[p++]=weight_a*exp(pos->model_derivative_b(i, j, x)-px);
00180         } 
00181 
00182     }
00183 
00184     //then do negative
00185     for (i=0; i<neg->get_N(); i++)
00186     {
00187         featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_p(i, x)-px);
00188         featurevector[p++]= (1-weight_a)* exp(neg->model_derivative_q(i, x)-px);
00189 
00190         for (j=0; j<neg->get_N(); j++) {
00191             featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_a(i, j, x)-px);
00192         }
00193 
00194         for (j=0; j<neg->get_M(); j++) {
00195             featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_b(i, j, x)-px);
00196         }
00197     }
00198 }
00199 
00200 DREAL* CFKFeatures::set_feature_matrix()
00201 {
00202     ASSERT(pos);
00203     ASSERT(pos->get_observations());
00204     ASSERT(neg);
00205     ASSERT(neg->get_observations());
00206 
00207     INT len=0;
00208     num_features=1+ pos->get_N()*(1+pos->get_N()+1+pos->get_M()) + neg->get_N()*(1+neg->get_N()+1+neg->get_M());
00209 
00210     num_vectors=pos->get_observations()->get_num_vectors();
00211     ASSERT(num_vectors);
00212 
00213     SG_INFO( "allocating FK feature cache of size %.2fM\n", sizeof(double)*num_features*num_vectors/1024.0/1024.0);
00214     free_feature_matrix();
00215     feature_matrix=new DREAL[num_features*num_vectors];
00216 
00217     SG_INFO( "calculating FK feature matrix\n");
00218 
00219     for (INT x=0; x<num_vectors; x++)
00220     {
00221         if (!(x % (num_vectors/10+1)))
00222             SG_DEBUG("%02d%%.", (int) (100.0*x/num_vectors));
00223         else if (!(x % (num_vectors/200+1)))
00224             SG_DEBUG(".");
00225 
00226         compute_feature_vector(&feature_matrix[x*num_features], x, len);
00227     }
00228 
00229     SG_DONE();
00230     
00231     num_vectors=get_num_vectors() ;
00232     num_features=get_num_features() ;
00233 
00234     return feature_matrix;
00235 }

SHOGUN Machine Learning Toolbox - Documentation