SHOGUN  v1.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Plif.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 1999-2008 Gunnar Raetsch
8  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
9  */
10 
11 
12 #include <stdio.h>
13 #include <string.h>
14 
15 #include <shogun/lib/config.h>
16 #include <shogun/io/SGIO.h>
17 #include <shogun/structure/Plif.h>
18 
19 //#define PLIF_DEBUG
20 
21 using namespace shogun;
22 
23 CPlif::CPlif(int32_t l)
24 : CPlifBase()
25 {
26  limits=NULL;
27  penalties=NULL;
28  cum_derivatives=NULL;
29  id=-1;
31  name=NULL;
32  max_value=0;
33  min_value=0;
34  cache=NULL;
35  use_svm=0;
36  use_cache=false;
37  len=0;
38  do_calc = true;
39  if (l>0)
40  set_plif_length(l);
41 }
42 
44 {
45  SG_FREE(limits);
47  SG_FREE(name);
48  SG_FREE(cache);
50 }
51 
52 bool CPlif::set_transform_type(const char *type_str)
53 {
55 
56  if (strcmp(type_str, "linear")==0)
58  else if (strcmp(type_str, "")==0)
60  else if (strcmp(type_str, "log")==0)
61  transform = T_LOG ;
62  else if (strcmp(type_str, "log(+1)")==0)
64  else if (strcmp(type_str, "log(+3)")==0)
66  else if (strcmp(type_str, "(+3)")==0)
68  else
69  {
70  SG_ERROR( "unknown transform type (%s)\n", type_str) ;
71  return false ;
72  }
73  return true ;
74 }
75 
77 {
78  if (!use_cache)
79  return ;
80  if (cache || use_svm)
81  return ;
82  if (max_value<=0)
83  return ;
84 
85  float64_t* local_cache=SG_MALLOC(float64_t, ((int32_t) max_value) + 2);
86 
87  if (local_cache)
88  {
89  for (int32_t i=0; i<=max_value; i++)
90  {
91  if (i<min_value)
92  local_cache[i] = -CMath::INFTY ;
93  else
94  local_cache[i] = lookup_penalty(i, NULL) ;
95  }
96  }
97  this->cache=local_cache ;
98 }
99 
100 void CPlif::set_plif_name(char *p_name)
101 {
102  SG_FREE(name);
103  name=SG_MALLOC(char, strlen(p_name)+3);
104  strcpy(name,p_name) ;
105 }
106 
107 void CPlif::delete_penalty_struct(CPlif** PEN, int32_t P)
108 {
109  for (int32_t i=0; i<P; i++)
110  delete PEN[i] ;
111  SG_FREE(PEN);
112 }
113 
115  float64_t p_value, float64_t *d_values) const
116 {
117  ASSERT(use_svm>0);
118  float64_t d_value=d_values[use_svm-1] ;
119 #ifdef PLIF_DEBUG
120  SG_PRINT("%s.lookup_penalty_svm(%f)\n", get_name(), d_value) ;
121 #endif
122 
123  if (!do_calc)
124  return d_value;
125  switch (transform)
126  {
127  case T_LINEAR:
128  break ;
129  case T_LOG:
130  d_value = log(d_value) ;
131  break ;
132  case T_LOG_PLUS1:
133  d_value = log(d_value+1) ;
134  break ;
135  case T_LOG_PLUS3:
136  d_value = log(d_value+3) ;
137  break ;
138  case T_LINEAR_PLUS3:
139  d_value = d_value+3 ;
140  break ;
141  default:
142  SG_ERROR("unknown transform\n");
143  break ;
144  }
145 
146  int32_t idx = 0 ;
147  float64_t ret ;
148  for (int32_t i=0; i<len; i++)
149  if (limits[i]<=d_value)
150  idx++ ;
151  else
152  break ; // assume it is monotonically increasing
153 
154 #ifdef PLIF_DEBUG
155  SG_PRINT(" -> idx = %i ", idx) ;
156 #endif
157 
158  if (idx==0)
159  ret=penalties[0] ;
160  else if (idx==len)
161  ret=penalties[len-1] ;
162  else
163  {
164  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
165  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
166 #ifdef PLIF_DEBUG
167  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]) ;
168 #endif
169  }
170 #ifdef PLIF_DEBUG
171  SG_PRINT(" -> ret=%1.3f\n", ret) ;
172 #endif
173 
174  return ret ;
175 }
176 
177 float64_t CPlif::lookup_penalty(int32_t p_value, float64_t* svm_values) const
178 {
179  if (use_svm)
180  return lookup_penalty_svm(p_value, svm_values) ;
181 
182  if ((p_value<min_value) || (p_value>max_value))
183  {
184  //SG_PRINT("Feature:%s, %s.lookup_penalty(%i): return -inf min_value: %f, max_value: %f\n", name, get_name(), p_value, min_value, max_value) ;
185  return -CMath::INFTY ;
186  }
187  if (!do_calc)
188  return p_value;
189  if (cache!=NULL && (p_value>=0) && (p_value<=max_value))
190  {
191  float64_t ret=cache[p_value] ;
192  return ret ;
193  }
194  return lookup_penalty((float64_t) p_value, svm_values) ;
195 }
196 
198 {
199  if (use_svm)
200  return lookup_penalty_svm(p_value, svm_values) ;
201 
202 #ifdef PLIF_DEBUG
203  SG_PRINT("%s.lookup_penalty(%f)\n", get_name(), p_value) ;
204 #endif
205 
206 
207  if ((p_value<min_value) || (p_value>max_value))
208  {
209  //SG_PRINT("Feature:%s, %s.lookup_penalty(%f): return -inf min_value: %f, max_value: %f\n", name, get_name(), p_value, min_value, max_value) ;
210  return -CMath::INFTY ;
211  }
212 
213  if (!do_calc)
214  return p_value;
215 
216  float64_t d_value = (float64_t) p_value ;
217  switch (transform)
218  {
219  case T_LINEAR:
220  break ;
221  case T_LOG:
222  d_value = log(d_value) ;
223  break ;
224  case T_LOG_PLUS1:
225  d_value = log(d_value+1) ;
226  break ;
227  case T_LOG_PLUS3:
228  d_value = log(d_value+3) ;
229  break ;
230  case T_LINEAR_PLUS3:
231  d_value = d_value+3 ;
232  break ;
233  default:
234  SG_ERROR( "unknown transform\n") ;
235  break ;
236  }
237 
238 #ifdef PLIF_DEBUG
239  SG_PRINT(" -> value = %1.4f ", d_value) ;
240 #endif
241 
242  int32_t idx = 0 ;
243  float64_t ret ;
244  for (int32_t i=0; i<len; i++)
245  if (limits[i]<=d_value)
246  idx++ ;
247  else
248  break ; // assume it is monotonically increasing
249 
250 #ifdef PLIF_DEBUG
251  SG_PRINT(" -> idx = %i ", idx) ;
252 #endif
253 
254  if (idx==0)
255  ret=penalties[0] ;
256  else if (idx==len)
257  ret=penalties[len-1] ;
258  else
259  {
260  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
261  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
262 #ifdef PLIF_DEBUG
263  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]) ;
264 #endif
265  }
266  //if (p_value>=30 && p_value<150)
267  //SG_PRINT("%s %i(%i) -> %1.2f\n", PEN->name, p_value, idx, ret) ;
268 #ifdef PLIF_DEBUG
269  SG_PRINT(" -> ret=%1.3f\n", ret) ;
270 #endif
271 
272  return ret ;
273 }
274 
276 {
277  for (int32_t i=0; i<len; i++)
278  cum_derivatives[i]=0.0 ;
279 }
280 
281 void CPlif::penalty_add_derivative(float64_t p_value, float64_t* svm_values, float64_t factor)
282 {
283  if (use_svm)
284  {
285  penalty_add_derivative_svm(p_value, svm_values, factor) ;
286  return ;
287  }
288 
289  if ((p_value<min_value) || (p_value>max_value))
290  {
291  return ;
292  }
293  float64_t d_value = (float64_t) p_value ;
294  switch (transform)
295  {
296  case T_LINEAR:
297  break ;
298  case T_LOG:
299  d_value = log(d_value) ;
300  break ;
301  case T_LOG_PLUS1:
302  d_value = log(d_value+1) ;
303  break ;
304  case T_LOG_PLUS3:
305  d_value = log(d_value+3) ;
306  break ;
307  case T_LINEAR_PLUS3:
308  d_value = d_value+3 ;
309  break ;
310  default:
311  SG_ERROR( "unknown transform\n") ;
312  break ;
313  }
314 
315  int32_t idx = 0 ;
316  for (int32_t i=0; i<len; i++)
317  if (limits[i]<=d_value)
318  idx++ ;
319  else
320  break ; // assume it is monotonically increasing
321 
322  if (idx==0)
323  cum_derivatives[0]+= factor ;
324  else if (idx==len)
325  cum_derivatives[len-1]+= factor ;
326  else
327  {
328  cum_derivatives[idx] += factor * (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
329  cum_derivatives[idx-1]+= factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
330  }
331 }
332 
334 {
335  ASSERT(use_svm>0);
336  float64_t d_value=d_values[use_svm-1] ;
337 
338  if (d_value<-1e+20)
339  return;
340 
341  switch (transform)
342  {
343  case T_LINEAR:
344  break ;
345  case T_LOG:
346  d_value = log(d_value) ;
347  break ;
348  case T_LOG_PLUS1:
349  d_value = log(d_value+1) ;
350  break ;
351  case T_LOG_PLUS3:
352  d_value = log(d_value+3) ;
353  break ;
354  case T_LINEAR_PLUS3:
355  d_value = d_value+3 ;
356  break ;
357  default:
358  SG_ERROR( "unknown transform\n") ;
359  break ;
360  }
361 
362  int32_t idx = 0 ;
363  for (int32_t i=0; i<len; i++)
364  if (limits[i]<=d_value)
365  idx++ ;
366  else
367  break ; // assume it is monotonically increasing
368 
369  if (idx==0)
370  cum_derivatives[0]+=factor ;
371  else if (idx==len)
372  cum_derivatives[len-1]+=factor ;
373  else
374  {
375  cum_derivatives[idx] += factor*(d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
376  cum_derivatives[idx-1] += factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
377  }
378 }
379 
380 void CPlif::get_used_svms(int32_t* num_svms, int32_t* svm_ids)
381 {
382  if (use_svm)
383  {
384  svm_ids[(*num_svms)] = use_svm;
385  (*num_svms)++;
386  }
387  SG_PRINT("->use_svm:%i plif_id:%i name:%s trans_type:%s ",use_svm, get_id(), get_name(), get_transform_type());
388 }
389 
391 {
392  return do_calc;
393 }
394 
395 void CPlif::set_do_calc(bool b)
396 {
397  do_calc = b;;
398 }

SHOGUN Machine Learning Toolbox - Documentation