|
SHOGUN v0.9.3
|
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 }