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

SHOGUN Machine Learning Toolbox - Documentation