00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00076
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
00101
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
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
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
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
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
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 }