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

SHOGUN Machine Learning Toolbox - Documentation