SHOGUN
v2.0.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 CDensePreprocessor<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 SG_ADD(&dim_input_space, "dim_input_space", 00080 "Dimensionality of the input space.", MS_NOT_AVAILABLE); 00081 SG_ADD(&cur_dim_input_space, "cur_dim_input_space", 00082 "Dimensionality of the input space.", MS_NOT_AVAILABLE); 00083 SG_ADD(&dim_feature_space, "dim_feature_space", 00084 "Dimensionality of the feature space.", MS_NOT_AVAILABLE); 00085 SG_ADD(&cur_dim_feature_space, "cur_dim_feature_space", 00086 "Dimensionality of the feature space.", MS_NOT_AVAILABLE); 00087 00088 SG_ADD(&kernelwidth, "kernelwidth", "Kernel width.", MS_AVAILABLE); 00089 SG_ADD(&cur_kernelwidth, "cur_kernelwidth", "Kernel width.", MS_AVAILABLE); 00090 00091 m_parameters->add_vector(&randomcoeff_additive,&cur_dim_feature_space,"randomcoeff_additive"); 00092 m_parameters->add_matrix(&randomcoeff_multiplicative,&cur_dim_feature_space,&cur_dim_input_space,"randomcoeff_multiplicative"); 00093 } 00094 00095 } 00096 00097 CRandomFourierGaussPreproc::CRandomFourierGaussPreproc( 00098 const CRandomFourierGaussPreproc & feats) : 00099 CDensePreprocessor<float64_t> () { 00100 00101 randomcoeff_multiplicative=NULL; 00102 randomcoeff_additive=NULL; 00103 00104 //m_parameter is inherited from CSGObject, 00105 //serialization initialization 00106 if(m_parameters) 00107 { 00108 SG_ADD(&dim_input_space, "dim_input_space", 00109 "Dimensionality of the input space.", MS_NOT_AVAILABLE); 00110 SG_ADD(&cur_dim_input_space, "cur_dim_input_space", 00111 "Dimensionality of the input space.", MS_NOT_AVAILABLE); 00112 SG_ADD(&dim_feature_space, "dim_feature_space", 00113 "Dimensionality of the feature space.", MS_NOT_AVAILABLE); 00114 SG_ADD(&cur_dim_feature_space, "cur_dim_feature_space", 00115 "Dimensionality of the feature space.", MS_NOT_AVAILABLE); 00116 00117 SG_ADD(&kernelwidth, "kernelwidth", "Kernel width.", MS_AVAILABLE); 00118 SG_ADD(&cur_kernelwidth, "cur_kernelwidth", "Kernel width.", MS_AVAILABLE); 00119 00120 m_parameters->add_vector(&randomcoeff_additive,&cur_dim_feature_space,"randomcoeff_additive"); 00121 m_parameters->add_matrix(&randomcoeff_multiplicative,&cur_dim_feature_space,&cur_dim_input_space,"randomcoeff_multiplicative"); 00122 } 00123 00124 copy(feats); 00125 } 00126 00127 CRandomFourierGaussPreproc::~CRandomFourierGaussPreproc() { 00128 00129 SG_FREE(randomcoeff_multiplicative); 00130 SG_FREE(randomcoeff_additive); 00131 00132 } 00133 00134 EFeatureClass CRandomFourierGaussPreproc::get_feature_class() { 00135 return C_DENSE; 00136 } 00137 00138 EFeatureType CRandomFourierGaussPreproc::get_feature_type() { 00139 return F_DREAL; 00140 } 00141 00142 int32_t CRandomFourierGaussPreproc::get_dim_feature_space() const { 00143 return ((int32_t) dim_feature_space); 00144 } 00145 00146 void CRandomFourierGaussPreproc::set_dim_feature_space(const int32_t dim) { 00147 if (dim <= 0) { 00148 throw ShogunException( 00149 "void CRandomFourierGaussPreproc::set_dim_feature_space(const int32 dim): dim<=0 is not allowed"); 00150 } 00151 00152 dim_feature_space = dim; 00153 00154 } 00155 00156 int32_t CRandomFourierGaussPreproc::get_dim_input_space() const { 00157 return ((int32_t) dim_input_space); 00158 } 00159 00160 void CRandomFourierGaussPreproc::set_kernelwidth(const float64_t kernelwidth2 ) { 00161 if (kernelwidth2 <= 0) { 00162 throw ShogunException( 00163 "void CRandomFourierGaussPreproc::set_kernelwidth(const float64_t kernelwidth2 ): kernelwidth2 <= 0 is not allowed"); 00164 } 00165 kernelwidth=kernelwidth2; 00166 } 00167 00168 float64_t CRandomFourierGaussPreproc::get_kernelwidth( ) const { 00169 return (kernelwidth); 00170 } 00171 00172 void CRandomFourierGaussPreproc::set_dim_input_space(const int32_t dim) { 00173 if (dim <= 0) { 00174 throw ShogunException( 00175 "void CRandomFourierGaussPreproc::set_dim_input_space(const int32 dim): dim<=0 is not allowed"); 00176 } 00177 00178 dim_input_space = dim; 00179 00180 } 00181 00182 bool CRandomFourierGaussPreproc::test_rfinited() const { 00183 00184 if ((dim_feature_space == cur_dim_feature_space) 00185 && (dim_input_space > 0) && (dim_feature_space > 0)) { 00186 if ((dim_input_space == cur_dim_input_space)&&(CMath::abs(kernelwidth-cur_kernelwidth)<1e-5)) { 00187 00188 // already inited 00189 return true; 00190 } else { 00191 return false; 00192 } 00193 } 00194 00195 return false; 00196 } 00197 00198 bool CRandomFourierGaussPreproc::init_randomcoefficients() { 00199 if (dim_feature_space <= 0) { 00200 throw ShogunException( 00201 "bool CRandomFourierGaussPreproc::init_randomcoefficients(): dim_feature_space<=0 is not allowed\n"); 00202 } 00203 if (dim_input_space <= 0) { 00204 throw ShogunException( 00205 "bool CRandomFourierGaussPreproc::init_randomcoefficients(): dim_input_space<=0 is not allowed\n"); 00206 } 00207 00208 if (test_rfinited()) { 00209 return false; 00210 } 00211 00212 00213 SG_INFO("initializing randomcoefficients \n") ; 00214 00215 float64_t pi = 3.14159265; 00216 00217 00218 SG_FREE(randomcoeff_multiplicative); 00219 randomcoeff_multiplicative=NULL; 00220 SG_FREE(randomcoeff_additive); 00221 randomcoeff_additive=NULL; 00222 00223 00224 cur_dim_feature_space=dim_feature_space; 00225 randomcoeff_additive=SG_MALLOC(float64_t, cur_dim_feature_space); 00226 cur_dim_input_space = dim_input_space; 00227 randomcoeff_multiplicative=SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00228 00229 cur_kernelwidth=kernelwidth; 00230 00231 for (int32_t i = 0; i < cur_dim_feature_space; ++i) { 00232 randomcoeff_additive[i] = CMath::random((float64_t) 0.0, 2 * pi); 00233 } 00234 00235 for (int32_t i = 0; i < cur_dim_feature_space; ++i) { 00236 for (int32_t k = 0; k < cur_dim_input_space; ++k) { 00237 float64_t x1,x2; 00238 float64_t s = 2; 00239 while ((s >= 1) ) { 00240 // Marsaglia polar for gaussian 00241 x1 = CMath::random((float64_t) -1.0, (float64_t) 1.0); 00242 x2 = CMath::random((float64_t) -1.0, (float64_t) 1.0); 00243 s=x1*x1+x2*x2; 00244 } 00245 00246 // = x1/CMath::sqrt(val)* CMath::sqrt(-2*CMath::log(val)); 00247 randomcoeff_multiplicative[i*cur_dim_input_space+k] = x1*CMath::sqrt(-2*CMath::log(s)/s )/kernelwidth; 00248 } 00249 } 00250 00251 SG_INFO("finished: initializing randomcoefficients \n") ; 00252 00253 return true; 00254 } 00255 00256 void CRandomFourierGaussPreproc::get_randomcoefficients( 00257 float64_t ** randomcoeff_additive2, 00258 float64_t ** randomcoeff_multiplicative2, int32_t *dim_feature_space2, 00259 int32_t *dim_input_space2, float64_t* kernelwidth2) const { 00260 00261 ASSERT(randomcoeff_additive2); 00262 ASSERT(randomcoeff_multiplicative2); 00263 00264 if (!test_rfinited()) { 00265 *dim_feature_space2 = 0; 00266 *dim_input_space2 = 0; 00267 *kernelwidth2=1; 00268 *randomcoeff_additive2 = NULL; 00269 *randomcoeff_multiplicative2 = NULL; 00270 return; 00271 } 00272 00273 *dim_feature_space2 = cur_dim_feature_space; 00274 *dim_input_space2 = cur_dim_input_space; 00275 *kernelwidth2=cur_kernelwidth; 00276 00277 *randomcoeff_additive2 = SG_MALLOC(float64_t, cur_dim_feature_space); 00278 *randomcoeff_multiplicative2 = SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00279 00280 std::copy(randomcoeff_additive, randomcoeff_additive+cur_dim_feature_space, 00281 *randomcoeff_additive2); 00282 std::copy(randomcoeff_multiplicative, randomcoeff_multiplicative+cur_dim_feature_space*cur_dim_input_space, 00283 *randomcoeff_multiplicative2); 00284 00285 00286 } 00287 00288 void CRandomFourierGaussPreproc::set_randomcoefficients( 00289 float64_t *randomcoeff_additive2, 00290 float64_t * randomcoeff_multiplicative2, 00291 const int32_t dim_feature_space2, const int32_t dim_input_space2, const float64_t kernelwidth2) { 00292 dim_feature_space = dim_feature_space2; 00293 dim_input_space = dim_input_space2; 00294 kernelwidth=kernelwidth2; 00295 00296 SG_FREE(randomcoeff_multiplicative); 00297 randomcoeff_multiplicative=NULL; 00298 SG_FREE(randomcoeff_additive); 00299 randomcoeff_additive=NULL; 00300 00301 cur_dim_feature_space=dim_feature_space; 00302 cur_dim_input_space = dim_input_space; 00303 cur_kernelwidth=kernelwidth; 00304 00305 if( (dim_feature_space>0) && (dim_input_space>0) ) 00306 { 00307 randomcoeff_additive=SG_MALLOC(float64_t, cur_dim_feature_space); 00308 randomcoeff_multiplicative=SG_MALLOC(float64_t, cur_dim_feature_space*cur_dim_input_space); 00309 00310 std::copy(randomcoeff_additive2, randomcoeff_additive2 00311 + dim_feature_space, randomcoeff_additive); 00312 std::copy(randomcoeff_multiplicative2, randomcoeff_multiplicative2 00313 + cur_dim_feature_space*cur_dim_input_space, randomcoeff_multiplicative); 00314 } 00315 00316 } 00317 00318 bool CRandomFourierGaussPreproc::init(CFeatures *f) { 00319 if (f->get_feature_class() != get_feature_class()) { 00320 throw ShogunException( 00321 "CRandomFourierGaussPreproc::init (CFeatures *f) requires CDenseFeatures<float64_t> as features\n"); 00322 } 00323 if (f->get_feature_type() != get_feature_type()) { 00324 throw ShogunException( 00325 "CRandomFourierGaussPreproc::init (CFeatures *f) requires CDenseFeatures<float64_t> as features\n"); 00326 } 00327 if (dim_feature_space <= 0) { 00328 throw ShogunException( 00329 "CRandomFourierGaussPreproc::init (CFeatures *f): dim_feature_space<=0 is not allowed, use void set_dim_feature_space(const int32 dim) before!\n"); 00330 } 00331 00332 SG_INFO("calling CRandomFourierGaussPreproc::init(...)\n"); 00333 int32_t num_features = 00334 ((CDenseFeatures<float64_t>*) f)->get_num_features(); 00335 00336 if (!test_rfinited()) { 00337 dim_input_space = num_features; 00338 init_randomcoefficients(); 00339 ASSERT( test_rfinited()); 00340 return true; 00341 } else { 00342 dim_input_space = num_features; 00343 // does not reinit if dimension is the same to avoid overriding a previous call of set_randomcoefficients(...) 00344 bool inited = init_randomcoefficients(); 00345 return inited; 00346 } 00347 00348 } 00349 00350 SGVector<float64_t> CRandomFourierGaussPreproc::apply_to_feature_vector(SGVector<float64_t> vector) 00351 { 00352 if (!test_rfinited()) { 00353 throw ShogunException( 00354 "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"); 00355 } 00356 00357 float64_t val = CMath::sqrt(2.0 / cur_dim_feature_space); 00358 float64_t *res = SG_MALLOC(float64_t, cur_dim_feature_space); 00359 00360 for (int32_t od = 0; od < cur_dim_feature_space; ++od) { 00361 res[od] = val * cos(randomcoeff_additive[od] + SGVector<float64_t>::dot(vector.vector, 00362 randomcoeff_multiplicative+od*cur_dim_input_space, cur_dim_input_space)); 00363 } 00364 00365 return SGVector<float64_t>(res,cur_dim_feature_space); 00366 } 00367 00368 SGMatrix<float64_t> CRandomFourierGaussPreproc::apply_to_feature_matrix(CFeatures* features) 00369 { 00370 init(features); 00371 00372 // version for case dim_feature_space < dim_input space with direct transformation on feature matrix ?? 00373 00374 int32_t num_vectors = 0; 00375 int32_t num_features = 0; 00376 float64_t* m = ((CDenseFeatures<float64_t>*) features)->get_feature_matrix( 00377 num_features, num_vectors); 00378 SG_INFO("get Feature matrix: %ix%i\n", num_vectors, num_features); 00379 00380 if (num_features!=cur_dim_input_space) 00381 { 00382 throw ShogunException( 00383 "float64_t * CRandomFourierGaussPreproc::apply_to_feature_matrix(CFeatures *f): num_features!=cur_dim_input_space is not allowed\n"); 00384 } 00385 00386 if (m) 00387 { 00388 SGMatrix<float64_t> res(cur_dim_feature_space,num_vectors); 00389 00390 float64_t val = CMath::sqrt(2.0 / cur_dim_feature_space); 00391 00392 for (int32_t vec = 0; vec < num_vectors; vec++) 00393 { 00394 for (int32_t od = 0; od < cur_dim_feature_space; ++od) 00395 { 00396 res.matrix[od + vec * cur_dim_feature_space] = val * cos( 00397 randomcoeff_additive[od] 00398 + SGVector<float64_t>::dot(m+vec * num_features, 00399 randomcoeff_multiplicative+od*cur_dim_input_space, 00400 cur_dim_input_space)); 00401 } 00402 } 00403 ((CDenseFeatures<float64_t>*) features)->set_feature_matrix(res); 00404 00405 return res; 00406 } 00407 else 00408 return SGMatrix<float64_t>(); 00409 } 00410 00411 void CRandomFourierGaussPreproc::cleanup() 00412 { 00413 00414 }