Plif.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) 1999-2008 Gunnar Raetsch
00008  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
00009  */
00010 
00011 
00012 #include <stdio.h>
00013 #include <string.h>
00014 
00015 #include "lib/config.h"
00016 #include "lib/io.h"
00017 #include "structure/Plif.h"
00018 
00019 //#define PLIF_DEBUG
00020 
00021 using namespace shogun;
00022 
00023 CPlif::CPlif(int32_t l)
00024 : CPlifBase()
00025 {
00026     limits=NULL;
00027     penalties=NULL;
00028     cum_derivatives=NULL;
00029     id=-1;
00030     transform=T_LINEAR;
00031     name=NULL;
00032     max_value=0;
00033     min_value=0;
00034     cache=NULL;
00035     use_svm=0;
00036     use_cache=false;
00037     len=0;
00038     do_calc = true;
00039     if (l>0)
00040         set_plif_length(l);
00041 }
00042 
00043 CPlif::~CPlif()
00044 {
00045     delete[] limits;
00046     delete[] penalties;
00047     delete[] name;
00048     delete[] cache;
00049     delete[] cum_derivatives;
00050 }
00051 
00052 bool CPlif::set_transform_type(const char *type_str)
00053 {
00054     invalidate_cache();
00055 
00056     if (strcmp(type_str, "linear")==0)
00057         transform = T_LINEAR ;
00058     else if (strcmp(type_str, "")==0)
00059         transform = T_LINEAR ;
00060     else if (strcmp(type_str, "log")==0)
00061         transform = T_LOG ;
00062     else if (strcmp(type_str, "log(+1)")==0)
00063         transform = T_LOG_PLUS1 ;
00064     else if (strcmp(type_str, "log(+3)")==0)
00065         transform = T_LOG_PLUS3 ;
00066     else if (strcmp(type_str, "(+3)")==0)
00067         transform = T_LINEAR_PLUS3 ;
00068     else
00069     {
00070         SG_ERROR( "unknown transform type (%s)\n", type_str) ;
00071         return false ;
00072     }
00073     return true ;
00074 }
00075 
00076 void CPlif::init_penalty_struct_cache()
00077 {
00078     if (!use_cache)
00079         return ;
00080     if (cache || use_svm)
00081         return ;
00082     if (max_value<=0)
00083         return ;
00084 
00085     float64_t* local_cache=new float64_t[ ((int32_t) max_value) + 2] ;
00086     
00087     if (local_cache)
00088     {
00089         for (int32_t i=0; i<=max_value; i++)
00090         {
00091             if (i<min_value)
00092                 local_cache[i] = -CMath::INFTY ;
00093             else
00094                 local_cache[i] = lookup_penalty(i, NULL) ;
00095         }
00096     }
00097     this->cache=local_cache ;
00098 }
00099 
00100 void CPlif::set_plif_name(char *p_name)
00101 {
00102     delete[] name ;
00103     name=new char[strlen(p_name)+1] ;
00104     strcpy(name,p_name) ;
00105 }
00106 
00107 void CPlif::delete_penalty_struct(CPlif** PEN, int32_t P) 
00108 {
00109     for (int32_t i=0; i<P; i++)
00110         delete PEN[i] ;
00111     delete[] PEN ;
00112 }
00113 
00114 float64_t CPlif::lookup_penalty_svm(
00115     float64_t p_value, float64_t *d_values) const
00116 {
00117     ASSERT(use_svm>0);
00118     float64_t d_value=d_values[use_svm-1] ;
00119 #ifdef PLIF_DEBUG
00120     SG_PRINT("%s.lookup_penalty_svm(%f)\n", get_name(), d_value) ;
00121 #endif
00122 
00123     if (!do_calc)
00124         return d_value;
00125     switch (transform)
00126     {
00127     case T_LINEAR:
00128         break ;
00129     case T_LOG:
00130         d_value = log(d_value) ;
00131         break ;
00132     case T_LOG_PLUS1:
00133         d_value = log(d_value+1) ;
00134         break ;
00135     case T_LOG_PLUS3:
00136         d_value = log(d_value+3) ;
00137         break ;
00138     case T_LINEAR_PLUS3:
00139         d_value = d_value+3 ;
00140         break ;
00141     default:
00142         SG_ERROR("unknown transform\n");
00143         break ;
00144     }
00145     
00146     int32_t idx = 0 ;
00147     float64_t ret ;
00148     for (int32_t i=0; i<len; i++)
00149         if (limits[i]<=d_value)
00150             idx++ ;
00151         else
00152             break ; // assume it is monotonically increasing
00153      
00154 #ifdef PLIF_DEBUG
00155     SG_PRINT("  -> idx = %i ", idx) ;
00156 #endif
00157     
00158     if (idx==0)
00159         ret=penalties[0] ;
00160     else if (idx==len)
00161         ret=penalties[len-1] ;
00162     else
00163     {
00164         ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
00165                (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;  
00166 #ifdef PLIF_DEBUG
00167         SG_PRINT("  -> (%1.3f*%1.3f, %1.3f*%1.3f)", (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]), penalties[idx], (limits[idx]-d_value)/(limits[idx]-limits[idx-1]), penalties[idx-1]) ;
00168 #endif
00169     }
00170 #ifdef PLIF_DEBUG
00171         SG_PRINT("  -> ret=%1.3f\n", ret) ;
00172 #endif
00173     
00174     return ret ;
00175 }
00176 
00177 float64_t CPlif::lookup_penalty(int32_t p_value, float64_t* svm_values) const
00178 {
00179     if (use_svm)
00180         return lookup_penalty_svm(p_value, svm_values) ;
00181 
00182     if ((p_value<min_value) || (p_value>max_value))
00183         return -CMath::INFTY ;
00184     if (!do_calc)
00185         return p_value;
00186     if (cache!=NULL && (p_value>=0) && (p_value<=max_value))
00187     {
00188         float64_t ret=cache[p_value] ;
00189         return ret ;
00190     }
00191     return lookup_penalty((float64_t) p_value, svm_values) ;
00192 }
00193 
00194 float64_t CPlif::lookup_penalty(float64_t p_value, float64_t* svm_values) const
00195 {
00196     if (use_svm)
00197         return lookup_penalty_svm(p_value, svm_values) ;
00198 
00199 #ifdef PLIF_DEBUG
00200     SG_PRINT("%s.lookup_penalty(%f)\n", get_name(), p_value) ;
00201 #endif
00202 
00203 
00204     if ((p_value<min_value) || (p_value>max_value))
00205         return -CMath::INFTY ;
00206 
00207     if (!do_calc)
00208         return p_value;
00209 
00210     float64_t d_value = (float64_t) p_value ;
00211     switch (transform)
00212     {
00213     case T_LINEAR:
00214         break ;
00215     case T_LOG:
00216         d_value = log(d_value) ;
00217         break ;
00218     case T_LOG_PLUS1:
00219         d_value = log(d_value+1) ;
00220         break ;
00221     case T_LOG_PLUS3:
00222         d_value = log(d_value+3) ;
00223         break ;
00224     case T_LINEAR_PLUS3:
00225         d_value = d_value+3 ;
00226         break ;
00227     default:
00228         SG_ERROR( "unknown transform\n") ;
00229         break ;
00230     }
00231 
00232 #ifdef PLIF_DEBUG
00233     SG_PRINT("  -> value = %1.4f ", d_value) ;
00234 #endif
00235 
00236     int32_t idx = 0 ;
00237     float64_t ret ;
00238     for (int32_t i=0; i<len; i++)
00239         if (limits[i]<=d_value)
00240             idx++ ;
00241         else
00242             break ; // assume it is monotonically increasing
00243     
00244 #ifdef PLIF_DEBUG
00245     SG_PRINT("  -> idx = %i ", idx) ;
00246 #endif
00247     
00248     if (idx==0)
00249         ret=penalties[0] ;
00250     else if (idx==len)
00251         ret=penalties[len-1] ;
00252     else
00253     {
00254         ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
00255                (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;  
00256 #ifdef PLIF_DEBUG
00257         SG_PRINT("  -> (%1.3f*%1.3f, %1.3f*%1.3f) ", (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]), penalties[idx], (limits[idx]-d_value)/(limits[idx]-limits[idx-1]), penalties[idx-1]) ;
00258 #endif
00259     }
00260     //if (p_value>=30 && p_value<150)
00261     //SG_PRINT("%s %i(%i) -> %1.2f\n", PEN->name, p_value, idx, ret) ;
00262 #ifdef PLIF_DEBUG
00263     SG_PRINT("  -> ret=%1.3f\n", ret) ;
00264 #endif
00265     
00266     return ret ;
00267 }
00268 
00269 void CPlif::penalty_clear_derivative() 
00270 {
00271     for (int32_t i=0; i<len; i++)
00272         cum_derivatives[i]=0.0 ;
00273 }
00274 
00275 void CPlif::penalty_add_derivative(float64_t p_value, float64_t* svm_values, float64_t factor)
00276 {
00277     if (use_svm)
00278     {
00279         penalty_add_derivative_svm(p_value, svm_values, factor) ;
00280         return ;
00281     }
00282     
00283     if ((p_value<min_value) || (p_value>max_value))
00284     {
00285         return ;
00286     }
00287     float64_t d_value = (float64_t) p_value ;
00288     switch (transform)
00289     {
00290     case T_LINEAR:
00291         break ;
00292     case T_LOG:
00293         d_value = log(d_value) ;
00294         break ;
00295     case T_LOG_PLUS1:
00296         d_value = log(d_value+1) ;
00297         break ;
00298     case T_LOG_PLUS3:
00299         d_value = log(d_value+3) ;
00300         break ;
00301     case T_LINEAR_PLUS3:
00302         d_value = d_value+3 ;
00303         break ;
00304     default:
00305         SG_ERROR( "unknown transform\n") ;
00306         break ;
00307     }
00308 
00309     int32_t idx = 0 ;
00310     for (int32_t i=0; i<len; i++)
00311         if (limits[i]<=d_value)
00312             idx++ ;
00313         else
00314             break ; // assume it is monotonically increasing
00315     
00316     if (idx==0)
00317         cum_derivatives[0]+= factor ;
00318     else if (idx==len)
00319         cum_derivatives[len-1]+= factor ;
00320     else
00321     {
00322         cum_derivatives[idx] += factor * (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
00323         cum_derivatives[idx-1]+= factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
00324     }
00325 }
00326 
00327 void CPlif::penalty_add_derivative_svm(float64_t p_value, float64_t *d_values, float64_t factor)
00328 {
00329     ASSERT(use_svm>0);
00330     float64_t d_value=d_values[use_svm-1] ;
00331 
00332     if (d_value<-1e+20)
00333         return;
00334     
00335     switch (transform)
00336     {
00337     case T_LINEAR:
00338         break ;
00339     case T_LOG:
00340         d_value = log(d_value) ;
00341         break ;
00342     case T_LOG_PLUS1:
00343         d_value = log(d_value+1) ;
00344         break ;
00345     case T_LOG_PLUS3:
00346         d_value = log(d_value+3) ;
00347         break ;
00348     case T_LINEAR_PLUS3:
00349         d_value = d_value+3 ;
00350         break ;
00351     default:
00352         SG_ERROR( "unknown transform\n") ;
00353         break ;
00354     }
00355     
00356     int32_t idx = 0 ;
00357     for (int32_t i=0; i<len; i++)
00358         if (limits[i]<=d_value)
00359             idx++ ;
00360         else
00361             break ; // assume it is monotonically increasing
00362     
00363     if (idx==0)
00364         cum_derivatives[0]+=factor ;
00365     else if (idx==len)
00366         cum_derivatives[len-1]+=factor ;
00367     else
00368     {
00369         cum_derivatives[idx] += factor*(d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
00370         cum_derivatives[idx-1] += factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
00371     }
00372 }
00373 
00374 void CPlif::get_used_svms(int32_t* num_svms, int32_t* svm_ids)
00375 {
00376     if (use_svm)
00377     {
00378         svm_ids[(*num_svms)] = use_svm;
00379         (*num_svms)++;
00380     }
00381     SG_PRINT("->use_svm:%i plif_id:%i name:%s trans_type:%s  ",use_svm, get_id(), get_name(), get_transform_type());
00382 }
00383 
00384 bool CPlif::get_do_calc()
00385 {
00386     return do_calc;
00387 }
00388 
00389 void CPlif::set_do_calc(bool b)
00390 {
00391     do_calc = b;;
00392 }

SHOGUN Machine Learning Toolbox - Documentation