RandomFourierGaussPreproc.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) 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation