SHOGUN
v1.1.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) 2010-2011 Alexander Binder 00008 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00009 * Copyright (C) 2010-2011 Berlin Institute of Technology 00010 */ 00011 00012 #include <shogun/preprocessor/RandomFourierGaussPreproc.h> 00013 #include <cmath> 00014 00015 using namespace shogun; 00016 00017 void CRandomFourierGaussPreproc::copy(const CRandomFourierGaussPreproc & feats) { 00018 00019 dim_input_space = feats.dim_input_space; 00020 cur_dim_input_space = feats.cur_dim_input_space; 00021 00022 dim_feature_space = feats.dim_feature_space; 00023 cur_dim_feature_space=feats.cur_dim_feature_space; 00024 00025 kernelwidth=feats.kernelwidth; 00026 cur_kernelwidth=feats.cur_kernelwidth; 00027 00028 if(cur_dim_feature_space>0) 00029 { 00030 if(feats.randomcoeff_additive==NULL) 00031 { 00032 throw ShogunException( 00033 "void CRandomFourierGaussPreproc::copy(...): feats.randomcoeff_additive==NULL && cur_dim_feature_space>0 \n"); 00034 } 00035 00036 randomcoeff_additive = SG_MALLOC(float64_t, cur_dim_feature_space); 00037 std::copy(feats.randomcoeff_additive,feats.randomcoeff_additive+cur_dim_feature_space,randomcoeff_additive); 00038 } 00039 else 00040 { 00041 randomcoeff_additive = NULL; 00042 } 00043 00044 if((cur_dim_feature_space>0)&&(cur_dim_input_space>0)) 00045 { 00046 if(feats.randomcoeff_multiplicative==NULL) 00047 { 00048 throw ShogunException( 00049 "void CRandomFourierGaussPreproc::copy(...): feats.randomcoeff_multiplicative==NULL && cur_dim_feature_space>0 &&(cur_dim_input_space>0) \n"); 00050 } 00051 00052 randomcoeff_multiplicative=SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00053 std::copy(feats.randomcoeff_multiplicative,feats.randomcoeff_multiplicative+cur_dim_feature_space*cur_dim_input_space,randomcoeff_multiplicative); 00054 } 00055 else 00056 { 00057 randomcoeff_multiplicative = NULL; 00058 } 00059 00060 } 00061 00062 CRandomFourierGaussPreproc::CRandomFourierGaussPreproc() : 00063 CSimplePreprocessor<float64_t> () { 00064 dim_feature_space = 1000; 00065 dim_input_space = 0; 00066 cur_dim_input_space = 0; 00067 cur_dim_feature_space=0; 00068 00069 randomcoeff_multiplicative=NULL; 00070 randomcoeff_additive=NULL; 00071 00072 kernelwidth=1; 00073 cur_kernelwidth=kernelwidth; 00074 00075 //m_parameter is inherited from CSGObject, 00076 //serialization initialization 00077 if(m_parameters) 00078 { 00079 m_parameters->add(&dim_input_space,"dim_input_space"); 00080 m_parameters->add(&cur_dim_input_space,"cur_dim_input_space"); 00081 m_parameters->add(&dim_feature_space,"dim_feature_space"); 00082 m_parameters->add(&kernelwidth,"kernelwidth"); 00083 m_parameters->add(&cur_kernelwidth,"cur_kernelwidth"); 00084 00085 00086 m_parameters->add(&cur_dim_feature_space,"cur_dim_feature_space"); 00087 m_parameters->add_vector(&randomcoeff_additive,&cur_dim_feature_space,"randomcoeff_additive"); 00088 m_parameters->add_matrix(&randomcoeff_multiplicative,&cur_dim_feature_space,&cur_dim_input_space,"randomcoeff_multiplicative"); 00089 } 00090 00091 } 00092 00093 CRandomFourierGaussPreproc::CRandomFourierGaussPreproc( 00094 const CRandomFourierGaussPreproc & feats) : 00095 CSimplePreprocessor<float64_t> () { 00096 00097 randomcoeff_multiplicative=NULL; 00098 randomcoeff_additive=NULL; 00099 00100 //m_parameter is inherited from CSGObject, 00101 //serialization initialization 00102 if(m_parameters) 00103 { 00104 m_parameters->add(&dim_input_space,"dim_input_space"); 00105 m_parameters->add(&cur_dim_input_space,"cur_dim_input_space"); 00106 m_parameters->add(&dim_feature_space,"dim_feature_space"); 00107 m_parameters->add(&kernelwidth,"kernelwidth"); 00108 m_parameters->add(&cur_kernelwidth,"cur_kernelwidth"); 00109 00110 m_parameters->add(&cur_dim_feature_space,"cur_dim_feature_space"); 00111 m_parameters->add_vector(&randomcoeff_additive,&cur_dim_feature_space,"randomcoeff_additive"); 00112 m_parameters->add_matrix(&randomcoeff_multiplicative,&cur_dim_feature_space,&cur_dim_input_space,"randomcoeff_multiplicative"); 00113 } 00114 00115 copy(feats); 00116 } 00117 00118 CRandomFourierGaussPreproc::~CRandomFourierGaussPreproc() { 00119 00120 SG_FREE(randomcoeff_multiplicative); 00121 SG_FREE(randomcoeff_additive); 00122 00123 } 00124 00125 EFeatureClass CRandomFourierGaussPreproc::get_feature_class() { 00126 return C_SIMPLE; 00127 } 00128 00129 EFeatureType CRandomFourierGaussPreproc::get_feature_type() { 00130 return F_DREAL; 00131 } 00132 00133 int32_t CRandomFourierGaussPreproc::get_dim_feature_space() const { 00134 return ((int32_t) dim_feature_space); 00135 } 00136 00137 void CRandomFourierGaussPreproc::set_dim_feature_space(const int32_t dim) { 00138 if (dim <= 0) { 00139 throw ShogunException( 00140 "void CRandomFourierGaussPreproc::set_dim_feature_space(const int32 dim): dim<=0 is not allowed"); 00141 } 00142 00143 dim_feature_space = dim; 00144 00145 } 00146 00147 int32_t CRandomFourierGaussPreproc::get_dim_input_space() const { 00148 return ((int32_t) dim_input_space); 00149 } 00150 00151 void CRandomFourierGaussPreproc::set_kernelwidth(const float64_t kernelwidth2 ) { 00152 if (kernelwidth2 <= 0) { 00153 throw ShogunException( 00154 "void CRandomFourierGaussPreproc::set_kernelwidth(const float64_t kernelwidth2 ): kernelwidth2 <= 0 is not allowed"); 00155 } 00156 kernelwidth=kernelwidth2; 00157 } 00158 00159 float64_t CRandomFourierGaussPreproc::get_kernelwidth( ) const { 00160 return (kernelwidth); 00161 } 00162 00163 void CRandomFourierGaussPreproc::set_dim_input_space(const int32_t dim) { 00164 if (dim <= 0) { 00165 throw ShogunException( 00166 "void CRandomFourierGaussPreproc::set_dim_input_space(const int32 dim): dim<=0 is not allowed"); 00167 } 00168 00169 dim_input_space = dim; 00170 00171 } 00172 00173 bool CRandomFourierGaussPreproc::test_rfinited() const { 00174 00175 if ((dim_feature_space == cur_dim_feature_space) 00176 && (dim_input_space > 0) && (dim_feature_space > 0)) { 00177 if ((dim_input_space == cur_dim_input_space)&&(CMath::abs(kernelwidth-cur_kernelwidth)<1e-5)) { 00178 00179 // already inited 00180 return true; 00181 } else { 00182 return false; 00183 } 00184 } 00185 00186 return false; 00187 } 00188 00189 bool CRandomFourierGaussPreproc::init_randomcoefficients() { 00190 if (dim_feature_space <= 0) { 00191 throw ShogunException( 00192 "bool CRandomFourierGaussPreproc::init_randomcoefficients(): dim_feature_space<=0 is not allowed\n"); 00193 } 00194 if (dim_input_space <= 0) { 00195 throw ShogunException( 00196 "bool CRandomFourierGaussPreproc::init_randomcoefficients(): dim_input_space<=0 is not allowed\n"); 00197 } 00198 00199 if (test_rfinited()) { 00200 return false; 00201 } 00202 00203 00204 SG_INFO("initializing randomcoefficients \n") ; 00205 00206 float64_t pi = 3.14159265; 00207 00208 00209 SG_FREE(randomcoeff_multiplicative); 00210 randomcoeff_multiplicative=NULL; 00211 SG_FREE(randomcoeff_additive); 00212 randomcoeff_additive=NULL; 00213 00214 00215 cur_dim_feature_space=dim_feature_space; 00216 randomcoeff_additive=SG_MALLOC(float64_t, cur_dim_feature_space); 00217 cur_dim_input_space = dim_input_space; 00218 randomcoeff_multiplicative=SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00219 00220 cur_kernelwidth=kernelwidth; 00221 00222 for (int32_t i = 0; i < cur_dim_feature_space; ++i) { 00223 randomcoeff_additive[i] = CMath::random((float64_t) 0.0, 2 * pi); 00224 } 00225 00226 for (int32_t i = 0; i < cur_dim_feature_space; ++i) { 00227 for (int32_t k = 0; k < cur_dim_input_space; ++k) { 00228 float64_t x1,x2; 00229 float64_t s = 2; 00230 while ((s >= 1) ) { 00231 // Marsaglia polar for gaussian 00232 x1 = CMath::random((float64_t) -1.0, (float64_t) 1.0); 00233 x2 = CMath::random((float64_t) -1.0, (float64_t) 1.0); 00234 s=x1*x1+x2*x2; 00235 } 00236 00237 // = x1/CMath::sqrt(val)* CMath::sqrt(-2*CMath::log(val)); 00238 randomcoeff_multiplicative[i*cur_dim_input_space+k] = x1*CMath::sqrt(-2*CMath::log(s)/s )/kernelwidth; 00239 } 00240 } 00241 00242 SG_INFO("finished: initializing randomcoefficients \n") ; 00243 00244 return true; 00245 } 00246 00247 void CRandomFourierGaussPreproc::get_randomcoefficients( 00248 float64_t ** randomcoeff_additive2, 00249 float64_t ** randomcoeff_multiplicative2, int32_t *dim_feature_space2, 00250 int32_t *dim_input_space2, float64_t* kernelwidth2) const { 00251 00252 ASSERT(randomcoeff_additive2); 00253 ASSERT(randomcoeff_multiplicative2); 00254 00255 if (!test_rfinited()) { 00256 *dim_feature_space2 = 0; 00257 *dim_input_space2 = 0; 00258 *kernelwidth2=1; 00259 *randomcoeff_additive2 = NULL; 00260 *randomcoeff_multiplicative2 = NULL; 00261 return; 00262 } 00263 00264 *dim_feature_space2 = cur_dim_feature_space; 00265 *dim_input_space2 = cur_dim_input_space; 00266 *kernelwidth2=cur_kernelwidth; 00267 00268 *randomcoeff_additive2 = SG_MALLOC(float64_t, cur_dim_feature_space); 00269 *randomcoeff_multiplicative2 = SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00270 00271 std::copy(randomcoeff_additive, randomcoeff_additive+cur_dim_feature_space, 00272 *randomcoeff_additive2); 00273 std::copy(randomcoeff_multiplicative, randomcoeff_multiplicative+cur_dim_feature_space*cur_dim_input_space, 00274 *randomcoeff_multiplicative2); 00275 00276 00277 } 00278 00279 void CRandomFourierGaussPreproc::set_randomcoefficients( 00280 float64_t *randomcoeff_additive2, 00281 float64_t * randomcoeff_multiplicative2, 00282 const int32_t dim_feature_space2, const int32_t dim_input_space2, const float64_t kernelwidth2) { 00283 dim_feature_space = dim_feature_space2; 00284 dim_input_space = dim_input_space2; 00285 kernelwidth=kernelwidth2; 00286 00287 SG_FREE(randomcoeff_multiplicative); 00288 randomcoeff_multiplicative=NULL; 00289 SG_FREE(randomcoeff_additive); 00290 randomcoeff_additive=NULL; 00291 00292 cur_dim_feature_space=dim_feature_space; 00293 cur_dim_input_space = dim_input_space; 00294 cur_kernelwidth=kernelwidth; 00295 00296 if( (dim_feature_space>0) && (dim_input_space>0) ) 00297 { 00298 randomcoeff_additive=SG_MALLOC(float64_t, cur_dim_feature_space); 00299 randomcoeff_multiplicative=SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00300 00301 std::copy(randomcoeff_additive2, randomcoeff_additive2 00302 + dim_feature_space, randomcoeff_additive); 00303 std::copy(randomcoeff_multiplicative2, randomcoeff_multiplicative2 00304 + cur_dim_feature_space*cur_dim_input_space, randomcoeff_multiplicative); 00305 } 00306 00307 } 00308 00309 bool CRandomFourierGaussPreproc::init(CFeatures *f) { 00310 if (f->get_feature_class() != get_feature_class()) { 00311 throw ShogunException( 00312 "CRandomFourierGaussPreproc::init (CFeatures *f) requires CSimpleFeatures<float64_t> as features\n"); 00313 } 00314 if (f->get_feature_type() != get_feature_type()) { 00315 throw ShogunException( 00316 "CRandomFourierGaussPreproc::init (CFeatures *f) requires CSimpleFeatures<float64_t> as features\n"); 00317 } 00318 if (dim_feature_space <= 0) { 00319 throw ShogunException( 00320 "CRandomFourierGaussPreproc::init (CFeatures *f): dim_feature_space<=0 is not allowed, use void set_dim_feature_space(const int32 dim) before!\n"); 00321 } 00322 00323 SG_INFO("calling CRandomFourierGaussPreproc::init(...)\n"); 00324 int32_t num_features = 00325 ((CSimpleFeatures<float64_t>*) f)->get_num_features(); 00326 00327 if (!test_rfinited()) { 00328 dim_input_space = num_features; 00329 init_randomcoefficients(); 00330 ASSERT( test_rfinited()); 00331 return true; 00332 } else { 00333 dim_input_space = num_features; 00334 // does not reinit if dimension is the same to avoid overriding a previous call of set_randomcoefficients(...) 00335 bool inited = init_randomcoefficients(); 00336 return inited; 00337 } 00338 00339 } 00340 00341 SGVector<float64_t> CRandomFourierGaussPreproc::apply_to_feature_vector(SGVector<float64_t> vector) 00342 { 00343 if (!test_rfinited()) { 00344 throw ShogunException( 00345 "float64_t * CRandomFourierGaussPreproc::apply_to_feature_vector(...): test_rfinited()==false: you need to call before CRandomFourierGaussPreproc::init (CFeatures *f) OR 1. set_dim_feature_space(const int32 dim), 2. set_dim_input_space(const int32 dim), 3. init_randomcoefficients() or set_randomcoefficients(...) \n"); 00346 } 00347 00348 float64_t val = CMath::sqrt(2.0 / cur_dim_feature_space); 00349 float64_t *res = SG_MALLOC(float64_t, cur_dim_feature_space); 00350 00351 for (int32_t od = 0; od < cur_dim_feature_space; ++od) { 00352 res[od] = val * cos(randomcoeff_additive[od] + CMath::dot(vector.vector, 00353 randomcoeff_multiplicative+od*cur_dim_input_space, cur_dim_input_space)); 00354 } 00355 00356 return SGVector<float64_t>(res,cur_dim_feature_space); 00357 } 00358 00359 SGMatrix<float64_t> CRandomFourierGaussPreproc::apply_to_feature_matrix(CFeatures* features) 00360 { 00361 init(features); 00362 00363 // version for case dim_feature_space < dim_input space with direct transformation on feature matrix ?? 00364 00365 int32_t num_vectors = 0; 00366 int32_t num_features = 0; 00367 float64_t* m = ((CSimpleFeatures<float64_t>*) features)->get_feature_matrix( 00368 num_features, num_vectors); 00369 SG_INFO("get Feature matrix: %ix%i\n", num_vectors, num_features); 00370 00371 if (num_features!=cur_dim_input_space) 00372 { 00373 throw ShogunException( 00374 "float64_t * CRandomFourierGaussPreproc::apply_to_feature_matrix(CFeatures *f): num_features!=cur_dim_input_space is not allowed\n"); 00375 } 00376 00377 if (m) { 00378 float64_t* res = SG_MALLOC(float64_t, num_vectors * cur_dim_feature_space); 00379 if (res == NULL) { 00380 throw ShogunException( 00381 "CRandomFourierGaussPreproc::apply_to_feature_matrix(...): memory allocation failed \n"); 00382 } 00383 float64_t val = CMath::sqrt(2.0 / cur_dim_feature_space); 00384 00385 for (int32_t vec = 0; vec < num_vectors; vec++) { 00386 for (int32_t od = 0; od < cur_dim_feature_space; ++od) { 00387 res[od + vec * cur_dim_feature_space] = val * cos( 00388 randomcoeff_additive[od] 00389 + CMath::dot(m+vec * num_features, 00390 randomcoeff_multiplicative+od*cur_dim_input_space, 00391 cur_dim_input_space)); 00392 } 00393 } 00394 ((CSimpleFeatures<float64_t>*) features)->set_feature_matrix(res, 00395 cur_dim_feature_space, num_vectors); 00396 00397 m = ((CSimpleFeatures<float64_t>*) features)->get_feature_matrix( 00398 num_features, num_vectors); 00399 ASSERT(num_features==cur_dim_feature_space); 00400 00401 return SGMatrix<float64_t>(res,num_vectors,cur_dim_feature_space); 00402 } else { 00403 return SGMatrix<float64_t>(); 00404 } 00405 } 00406 00407 void CRandomFourierGaussPreproc::cleanup() 00408 { 00409 00410 }