SHOGUN v0.9.0
|
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 #include "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=new float64_t[pos->get_observations()->get_num_vectors()]; 00097 neg_prob=new 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 delete[] pos_prob; 00118 delete[] 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=new 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=new 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 }