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

SHOGUN Machine Learning Toolbox - Documentation