SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 
14 #include <shogun/lib/config.h>
15 #include <shogun/io/SGIO.h>
16 #include <shogun/structure/Plif.h>
17 #include <shogun/lib/memory.h>
18 
19 //#define PLIF_DEBUG
20 
21 using namespace shogun;
22 
23 CPlif::CPlif(int32_t l)
24 : CPlifBase()
25 {
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(name);
46  SG_FREE(cache);
47 }
48 
49 bool CPlif::set_transform_type(const char *type_str)
50 {
52 
53  if (strcmp(type_str, "linear")==0)
55  else if (strcmp(type_str, "")==0)
57  else if (strcmp(type_str, "log")==0)
58  transform = T_LOG ;
59  else if (strcmp(type_str, "log(+1)")==0)
61  else if (strcmp(type_str, "log(+3)")==0)
63  else if (strcmp(type_str, "(+3)")==0)
65  else
66  {
67  SG_ERROR("unknown transform type (%s)\n", type_str)
68  return false ;
69  }
70  return true ;
71 }
72 
74 {
75  if (!use_cache)
76  return ;
77  if (cache || use_svm)
78  return ;
79  if (max_value<=0)
80  return ;
81 
82  float64_t* local_cache=SG_MALLOC(float64_t, ((int32_t) max_value) + 2);
83 
84  if (local_cache)
85  {
86  for (int32_t i=0; i<=max_value; i++)
87  {
88  if (i<min_value)
89  local_cache[i] = -CMath::INFTY ;
90  else
91  local_cache[i] = lookup_penalty(i, NULL) ;
92  }
93  }
94  this->cache=local_cache ;
95 }
96 
97 void CPlif::set_plif_name(char *p_name)
98 {
99  SG_FREE(name);
100  name=get_strdup(p_name);
101 }
102 
103 char* CPlif::get_plif_name() const
104 {
105  if (name)
106  return name;
107  else
108  {
109  char buf[20];
110  sprintf(buf, "plif%i", id);
111  return get_strdup(buf);
112  }
113 }
114 
115 void CPlif::delete_penalty_struct(CPlif** PEN, int32_t P)
116 {
117  for (int32_t i=0; i<P; i++)
118  delete PEN[i] ;
119  SG_FREE(PEN);
120 }
121 
123  float64_t p_value, float64_t *d_values) const
124 {
125  ASSERT(use_svm>0)
126  float64_t d_value=d_values[use_svm-1] ;
127 #ifdef PLIF_DEBUG
128  SG_PRINT("%s.lookup_penalty_svm(%f)\n", get_name(), d_value)
129 #endif
130 
131  if (!do_calc)
132  return d_value;
133  switch (transform)
134  {
135  case T_LINEAR:
136  break ;
137  case T_LOG:
138  d_value = log(d_value) ;
139  break ;
140  case T_LOG_PLUS1:
141  d_value = log(d_value+1) ;
142  break ;
143  case T_LOG_PLUS3:
144  d_value = log(d_value+3) ;
145  break ;
146  case T_LINEAR_PLUS3:
147  d_value = d_value+3 ;
148  break ;
149  default:
150  SG_ERROR("unknown transform\n")
151  break ;
152  }
153 
154  int32_t idx = 0 ;
155  float64_t ret ;
156  for (int32_t i=0; i<len; i++)
157  if (limits[i]<=d_value)
158  idx++ ;
159  else
160  break ; // assume it is monotonically increasing
161 
162 #ifdef PLIF_DEBUG
163  SG_PRINT(" -> idx = %i ", idx)
164 #endif
165 
166  if (idx==0)
167  ret=penalties[0] ;
168  else if (idx==len)
169  ret=penalties[len-1] ;
170  else
171  {
172  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
173  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
174 #ifdef PLIF_DEBUG
175  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])
176 #endif
177  }
178 #ifdef PLIF_DEBUG
179  SG_PRINT(" -> ret=%1.3f\n", ret)
180 #endif
181 
182  return ret ;
183 }
184 
185 float64_t CPlif::lookup_penalty(int32_t p_value, float64_t* svm_values) const
186 {
187  if (use_svm)
188  return lookup_penalty_svm(p_value, svm_values) ;
189 
190  if ((p_value<min_value) || (p_value>max_value))
191  {
192  //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)
193  return -CMath::INFTY ;
194  }
195  if (!do_calc)
196  return p_value;
197  if (cache!=NULL && (p_value>=0) && (p_value<=max_value))
198  {
199  float64_t ret=cache[p_value] ;
200  return ret ;
201  }
202  return lookup_penalty((float64_t) p_value, svm_values) ;
203 }
204 
206 {
207  if (use_svm)
208  return lookup_penalty_svm(p_value, svm_values) ;
209 
210 #ifdef PLIF_DEBUG
211  SG_PRINT("%s.lookup_penalty(%f)\n", get_name(), p_value)
212 #endif
213 
214 
215  if ((p_value<min_value) || (p_value>max_value))
216  {
217  //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)
218  return -CMath::INFTY ;
219  }
220 
221  if (!do_calc)
222  return p_value;
223 
224  float64_t d_value = (float64_t) p_value ;
225  switch (transform)
226  {
227  case T_LINEAR:
228  break ;
229  case T_LOG:
230  d_value = log(d_value) ;
231  break ;
232  case T_LOG_PLUS1:
233  d_value = log(d_value+1) ;
234  break ;
235  case T_LOG_PLUS3:
236  d_value = log(d_value+3) ;
237  break ;
238  case T_LINEAR_PLUS3:
239  d_value = d_value+3 ;
240  break ;
241  default:
242  SG_ERROR("unknown transform\n")
243  break ;
244  }
245 
246 #ifdef PLIF_DEBUG
247  SG_PRINT(" -> value = %1.4f ", d_value)
248 #endif
249 
250  int32_t idx = 0 ;
251  float64_t ret ;
252  for (int32_t i=0; i<len; i++)
253  if (limits[i]<=d_value)
254  idx++ ;
255  else
256  break ; // assume it is monotonically increasing
257 
258 #ifdef PLIF_DEBUG
259  SG_PRINT(" -> idx = %i ", idx)
260 #endif
261 
262  if (idx==0)
263  ret=penalties[0] ;
264  else if (idx==len)
265  ret=penalties[len-1] ;
266  else
267  {
268  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
269  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
270 #ifdef PLIF_DEBUG
271  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])
272 #endif
273  }
274  //if (p_value>=30 && p_value<150)
275  //SG_PRINT("%s %i(%i) -> %1.2f\n", PEN->name, p_value, idx, ret)
276 #ifdef PLIF_DEBUG
277  SG_PRINT(" -> ret=%1.3f\n", ret)
278 #endif
279 
280  return ret ;
281 }
282 
284 {
285  for (int32_t i=0; i<len; i++)
286  cum_derivatives[i]=0.0 ;
287 }
288 
289 void CPlif::penalty_add_derivative(float64_t p_value, float64_t* svm_values, float64_t factor)
290 {
291  if (use_svm)
292  {
293  penalty_add_derivative_svm(p_value, svm_values, factor) ;
294  return ;
295  }
296 
297  if ((p_value<min_value) || (p_value>max_value))
298  {
299  return ;
300  }
301  float64_t d_value = (float64_t) p_value ;
302  switch (transform)
303  {
304  case T_LINEAR:
305  break ;
306  case T_LOG:
307  d_value = log(d_value) ;
308  break ;
309  case T_LOG_PLUS1:
310  d_value = log(d_value+1) ;
311  break ;
312  case T_LOG_PLUS3:
313  d_value = log(d_value+3) ;
314  break ;
315  case T_LINEAR_PLUS3:
316  d_value = d_value+3 ;
317  break ;
318  default:
319  SG_ERROR("unknown transform\n")
320  break ;
321  }
322 
323  int32_t idx = 0 ;
324  for (int32_t i=0; i<len; i++)
325  if (limits[i]<=d_value)
326  idx++ ;
327  else
328  break ; // assume it is monotonically increasing
329 
330  if (idx==0)
331  cum_derivatives[0]+= factor ;
332  else if (idx==len)
333  cum_derivatives[len-1]+= factor ;
334  else
335  {
336  cum_derivatives[idx] += factor * (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
337  cum_derivatives[idx-1]+= factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
338  }
339 }
340 
342 {
343  ASSERT(use_svm>0)
344  float64_t d_value=d_values[use_svm-1] ;
345 
346  if (d_value<-1e+20)
347  return;
348 
349  switch (transform)
350  {
351  case T_LINEAR:
352  break ;
353  case T_LOG:
354  d_value = log(d_value) ;
355  break ;
356  case T_LOG_PLUS1:
357  d_value = log(d_value+1) ;
358  break ;
359  case T_LOG_PLUS3:
360  d_value = log(d_value+3) ;
361  break ;
362  case T_LINEAR_PLUS3:
363  d_value = d_value+3 ;
364  break ;
365  default:
366  SG_ERROR("unknown transform\n")
367  break ;
368  }
369 
370  int32_t idx = 0 ;
371  for (int32_t i=0; i<len; i++)
372  if (limits[i]<=d_value)
373  idx++ ;
374  else
375  break ; // assume it is monotonically increasing
376 
377  if (idx==0)
378  cum_derivatives[0]+=factor ;
379  else if (idx==len)
380  cum_derivatives[len-1]+=factor ;
381  else
382  {
383  cum_derivatives[idx] += factor*(d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
384  cum_derivatives[idx-1] += factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
385  }
386 }
387 
388 void CPlif::get_used_svms(int32_t* num_svms, int32_t* svm_ids)
389 {
390  if (use_svm)
391  {
392  svm_ids[(*num_svms)] = use_svm;
393  (*num_svms)++;
394  }
395  SG_PRINT("->use_svm:%i plif_id:%i name:%s trans_type:%s ",use_svm, get_id(), get_name(), get_transform_type())
396 }
397 
399 {
400  return do_calc;
401 }
402 
403 void CPlif::set_do_calc(bool b)
404 {
405  do_calc = b;;
406 }

SHOGUN Machine Learning Toolbox - Documentation