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-2009 Soeren Sonnenburg
00008  * Written (W) 1999-2008 Gunnar Raetsch
00009  * Copyright (C) 1999-2009 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 using namespace shogun;
00017 
00018 CFKFeatures::CFKFeatures(int32_t size, CHMM* p, CHMM* n)
00019 : CSimpleFeatures<float64_t>(size)
00020 {
00021     pos_prob=NULL;
00022     neg_prob=NULL;
00023     weight_a=-1;
00024     set_models(p,n);
00025 }
00026 
00027 CFKFeatures::CFKFeatures(const CFKFeatures &orig)
00028 : CSimpleFeatures<float64_t>(orig), pos(orig.pos), neg(orig.neg), weight_a(orig.weight_a)
00029 { 
00030 }
00031 
00032 CFKFeatures::~CFKFeatures()
00033 {
00034     SG_UNREF(pos);
00035     SG_UNREF(neg);
00036 }
00037 
00038 float64_t CFKFeatures::deriv_a(float64_t a, int32_t dimension)
00039 {
00040     CStringFeatures<uint16_t> *Obs=pos->get_observations() ;
00041     float64_t deriv=0.0 ;
00042     int32_t i=dimension ;
00043 
00044     if (dimension==-1)
00045     {
00046         for (i=0; i<Obs->get_num_vectors(); i++)
00047         {
00048             //float64_t pp=pos->model_probability(i) ;
00049             //float64_t pn=neg->model_probability(i) ;
00050             float64_t pp=(pos_prob) ? pos_prob[i] : pos->model_probability(i);
00051             float64_t pn=(neg_prob) ? neg_prob[i] : neg->model_probability(i);
00052             float64_t sub=pp ;
00053             if (pn>pp) sub=pn ;
00054             pp-=sub ;
00055             pn-=sub ;
00056             pp=exp(pp) ;
00057             pn=exp(pn) ;
00058             float64_t p=a*pp+(1-a)*pn ;
00059             deriv+=(pp-pn)/p ;
00060 
00061             /*float64_t d1=(pp-pn)/p ;
00062               pp=exp(pos->model_probability(i)) ;
00063               pn=exp(neg->model_probability(i)) ;
00064               p=a*pp+(1-a)*pn ;
00065               float64_t d2=(pp-pn)/p ;
00066               fprintf(stderr, "d1=%e  d2=%e,  d1-d2=%e\n",d1,d2) ;*/
00067         } ;
00068     } else
00069     {
00070         float64_t pp=pos->model_probability(i) ;
00071         float64_t pn=neg->model_probability(i) ;
00072         float64_t sub=pp ;
00073         if (pn>pp) sub=pn ;
00074         pp-=sub ;
00075         pn-=sub ;
00076         pp=exp(pp) ;
00077         pn=exp(pn) ;
00078         float64_t p=a*pp+(1-a)*pn ;
00079         deriv+=(pp-pn)/p ;
00080     } ;
00081 
00082     return deriv ;
00083 }
00084 
00085 
00086 float64_t CFKFeatures::set_opt_a(float64_t a)
00087 {
00088     if (a==-1)
00089     {
00090         SG_INFO( "estimating a.\n");
00091         pos_prob=new float64_t[pos->get_observations()->get_num_vectors()];
00092         neg_prob=new float64_t[pos->get_observations()->get_num_vectors()];
00093         for (int32_t i=0; i<pos->get_observations()->get_num_vectors(); i++)
00094         {
00095             pos_prob[i]=pos->model_probability(i) ;
00096             neg_prob[i]=neg->model_probability(i) ;
00097         }
00098 
00099         float64_t la=0;
00100         float64_t ua=1;
00101         a=(la+ua)/2;
00102         while (CMath::abs(ua-la)>1e-6)
00103         {
00104             float64_t da=deriv_a(a);
00105             if (da>0)
00106                 la=a;
00107             if (da<=0)
00108                 ua=a;
00109             a=(la+ua)/2;
00110             SG_INFO( "opt_a: a=%1.3e  deriv=%1.3e  la=%1.3e  ua=%1.3e\n", a, da, la ,ua);
00111         }
00112         delete[] pos_prob;
00113         delete[] neg_prob;
00114         pos_prob=NULL;
00115         neg_prob=NULL;
00116     }
00117 
00118     weight_a=a;
00119     SG_INFO( "setting opt_a: %g\n", a);
00120     return a;
00121 }
00122 
00123 void CFKFeatures::set_models(CHMM* p, CHMM* n)
00124 {
00125     ASSERT(p && n);
00126     SG_REF(p);
00127     SG_REF(n);
00128 
00129     pos=p; 
00130     neg=n;
00131     set_num_vectors(0);
00132 
00133     free_feature_matrix();
00134 
00135     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()) ;
00136 
00137     if (pos && pos->get_observations())
00138         set_num_vectors(pos->get_observations()->get_num_vectors());
00139     if (pos && neg)
00140         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()) ;
00141 }
00142 
00143 float64_t* CFKFeatures::compute_feature_vector(
00144     int32_t num, int32_t &len, float64_t* target)
00145 {
00146     float64_t* featurevector=target;
00147 
00148     if (!featurevector)
00149         featurevector=new float64_t[
00150             1+
00151             pos->get_N()*(1+pos->get_N()+1+pos->get_M())+
00152             neg->get_N()*(1+neg->get_N()+1+neg->get_M())
00153         ];
00154 
00155     if (!featurevector)
00156         return NULL;
00157 
00158     compute_feature_vector(featurevector, num, len);
00159 
00160     return featurevector;
00161 }
00162 
00163 void CFKFeatures::compute_feature_vector(
00164     float64_t* featurevector, int32_t num, int32_t& len)
00165 {
00166     int32_t i,j,p=0,x=num;
00167 
00168     float64_t posx=pos->model_probability(x);
00169     float64_t negx=neg->model_probability(x);
00170 
00171     len=1+pos->get_N()*(1+pos->get_N()+1+pos->get_M()) + neg->get_N()*(1+neg->get_N()+1+neg->get_M());
00172 
00173     featurevector[p++] = deriv_a(weight_a, x);
00174     float64_t px=CMath::logarithmic_sum(
00175         posx+log(weight_a),negx+log(1-weight_a));
00176 
00177     //first do positive model
00178     for (i=0; i<pos->get_N(); i++)
00179     {
00180         featurevector[p++]=weight_a*exp(pos->model_derivative_p(i, x)-px);
00181         featurevector[p++]=weight_a*exp(pos->model_derivative_q(i, x)-px);
00182 
00183         for (j=0; j<pos->get_N(); j++) {
00184             featurevector[p++]=weight_a*exp(pos->model_derivative_a(i, j, x)-px);
00185         }
00186 
00187         for (j=0; j<pos->get_M(); j++) {
00188             featurevector[p++]=weight_a*exp(pos->model_derivative_b(i, j, x)-px);
00189         } 
00190 
00191     }
00192 
00193     //then do negative
00194     for (i=0; i<neg->get_N(); i++)
00195     {
00196         featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_p(i, x)-px);
00197         featurevector[p++]= (1-weight_a)* exp(neg->model_derivative_q(i, x)-px);
00198 
00199         for (j=0; j<neg->get_N(); j++) {
00200             featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_a(i, j, x)-px);
00201         }
00202 
00203         for (j=0; j<neg->get_M(); j++) {
00204             featurevector[p++]= (1-weight_a)*exp(neg->model_derivative_b(i, j, x)-px);
00205         }
00206     }
00207 }
00208 
00209 float64_t* CFKFeatures::set_feature_matrix()
00210 {
00211     ASSERT(pos);
00212     ASSERT(pos->get_observations());
00213     ASSERT(neg);
00214     ASSERT(neg->get_observations());
00215 
00216     int32_t len=0;
00217     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());
00218 
00219     num_vectors=pos->get_observations()->get_num_vectors();
00220     ASSERT(num_vectors);
00221 
00222     SG_INFO( "allocating FK feature cache of size %.2fM\n", sizeof(float64_t)*num_features*num_vectors/1024.0/1024.0);
00223     free_feature_matrix();
00224     feature_matrix=new float64_t[num_features*num_vectors];
00225 
00226     SG_INFO( "calculating FK feature matrix\n");
00227 
00228     for (int32_t x=0; x<num_vectors; x++)
00229     {
00230         if (!(x % (num_vectors/10+1)))
00231             SG_DEBUG("%02d%%.", (int) (100.0*x/num_vectors));
00232         else if (!(x % (num_vectors/200+1)))
00233             SG_DEBUG(".");
00234 
00235         compute_feature_vector(&feature_matrix[x*num_features], x, len);
00236     }
00237 
00238     SG_DONE();
00239     
00240     num_vectors=get_num_vectors() ;
00241     num_features=get_num_features() ;
00242 
00243     return feature_matrix;
00244 }

SHOGUN Machine Learning Toolbox - Documentation