SHOGUN  v2.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 #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 {
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=SG_MALLOC(char, strlen(p_name)+3);
101  strcpy(name,p_name) ;
102 }
103 
104 void CPlif::delete_penalty_struct(CPlif** PEN, int32_t P)
105 {
106  for (int32_t i=0; i<P; i++)
107  delete PEN[i] ;
108  SG_FREE(PEN);
109 }
110 
112  float64_t p_value, float64_t *d_values) const
113 {
114  ASSERT(use_svm>0);
115  float64_t d_value=d_values[use_svm-1] ;
116 #ifdef PLIF_DEBUG
117  SG_PRINT("%s.lookup_penalty_svm(%f)\n", get_name(), d_value) ;
118 #endif
119 
120  if (!do_calc)
121  return d_value;
122  switch (transform)
123  {
124  case T_LINEAR:
125  break ;
126  case T_LOG:
127  d_value = log(d_value) ;
128  break ;
129  case T_LOG_PLUS1:
130  d_value = log(d_value+1) ;
131  break ;
132  case T_LOG_PLUS3:
133  d_value = log(d_value+3) ;
134  break ;
135  case T_LINEAR_PLUS3:
136  d_value = d_value+3 ;
137  break ;
138  default:
139  SG_ERROR("unknown transform\n");
140  break ;
141  }
142 
143  int32_t idx = 0 ;
144  float64_t ret ;
145  for (int32_t i=0; i<len; i++)
146  if (limits[i]<=d_value)
147  idx++ ;
148  else
149  break ; // assume it is monotonically increasing
150 
151 #ifdef PLIF_DEBUG
152  SG_PRINT(" -> idx = %i ", idx) ;
153 #endif
154 
155  if (idx==0)
156  ret=penalties[0] ;
157  else if (idx==len)
158  ret=penalties[len-1] ;
159  else
160  {
161  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
162  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
163 #ifdef PLIF_DEBUG
164  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]) ;
165 #endif
166  }
167 #ifdef PLIF_DEBUG
168  SG_PRINT(" -> ret=%1.3f\n", ret) ;
169 #endif
170 
171  return ret ;
172 }
173 
174 float64_t CPlif::lookup_penalty(int32_t p_value, float64_t* svm_values) const
175 {
176  if (use_svm)
177  return lookup_penalty_svm(p_value, svm_values) ;
178 
179  if ((p_value<min_value) || (p_value>max_value))
180  {
181  //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) ;
182  return -CMath::INFTY ;
183  }
184  if (!do_calc)
185  return p_value;
186  if (cache!=NULL && (p_value>=0) && (p_value<=max_value))
187  {
188  float64_t ret=cache[p_value] ;
189  return ret ;
190  }
191  return lookup_penalty((float64_t) p_value, svm_values) ;
192 }
193 
195 {
196  if (use_svm)
197  return lookup_penalty_svm(p_value, svm_values) ;
198 
199 #ifdef PLIF_DEBUG
200  SG_PRINT("%s.lookup_penalty(%f)\n", get_name(), p_value) ;
201 #endif
202 
203 
204  if ((p_value<min_value) || (p_value>max_value))
205  {
206  //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) ;
207  return -CMath::INFTY ;
208  }
209 
210  if (!do_calc)
211  return p_value;
212 
213  float64_t d_value = (float64_t) p_value ;
214  switch (transform)
215  {
216  case T_LINEAR:
217  break ;
218  case T_LOG:
219  d_value = log(d_value) ;
220  break ;
221  case T_LOG_PLUS1:
222  d_value = log(d_value+1) ;
223  break ;
224  case T_LOG_PLUS3:
225  d_value = log(d_value+3) ;
226  break ;
227  case T_LINEAR_PLUS3:
228  d_value = d_value+3 ;
229  break ;
230  default:
231  SG_ERROR( "unknown transform\n") ;
232  break ;
233  }
234 
235 #ifdef PLIF_DEBUG
236  SG_PRINT(" -> value = %1.4f ", d_value) ;
237 #endif
238 
239  int32_t idx = 0 ;
240  float64_t ret ;
241  for (int32_t i=0; i<len; i++)
242  if (limits[i]<=d_value)
243  idx++ ;
244  else
245  break ; // assume it is monotonically increasing
246 
247 #ifdef PLIF_DEBUG
248  SG_PRINT(" -> idx = %i ", idx) ;
249 #endif
250 
251  if (idx==0)
252  ret=penalties[0] ;
253  else if (idx==len)
254  ret=penalties[len-1] ;
255  else
256  {
257  ret = (penalties[idx]*(d_value-limits[idx-1]) + penalties[idx-1]*
258  (limits[idx]-d_value)) / (limits[idx]-limits[idx-1]) ;
259 #ifdef PLIF_DEBUG
260  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]) ;
261 #endif
262  }
263  //if (p_value>=30 && p_value<150)
264  //SG_PRINT("%s %i(%i) -> %1.2f\n", PEN->name, p_value, idx, ret) ;
265 #ifdef PLIF_DEBUG
266  SG_PRINT(" -> ret=%1.3f\n", ret) ;
267 #endif
268 
269  return ret ;
270 }
271 
273 {
274  for (int32_t i=0; i<len; i++)
275  cum_derivatives[i]=0.0 ;
276 }
277 
278 void CPlif::penalty_add_derivative(float64_t p_value, float64_t* svm_values, float64_t factor)
279 {
280  if (use_svm)
281  {
282  penalty_add_derivative_svm(p_value, svm_values, factor) ;
283  return ;
284  }
285 
286  if ((p_value<min_value) || (p_value>max_value))
287  {
288  return ;
289  }
290  float64_t d_value = (float64_t) p_value ;
291  switch (transform)
292  {
293  case T_LINEAR:
294  break ;
295  case T_LOG:
296  d_value = log(d_value) ;
297  break ;
298  case T_LOG_PLUS1:
299  d_value = log(d_value+1) ;
300  break ;
301  case T_LOG_PLUS3:
302  d_value = log(d_value+3) ;
303  break ;
304  case T_LINEAR_PLUS3:
305  d_value = d_value+3 ;
306  break ;
307  default:
308  SG_ERROR( "unknown transform\n") ;
309  break ;
310  }
311 
312  int32_t idx = 0 ;
313  for (int32_t i=0; i<len; i++)
314  if (limits[i]<=d_value)
315  idx++ ;
316  else
317  break ; // assume it is monotonically increasing
318 
319  if (idx==0)
320  cum_derivatives[0]+= factor ;
321  else if (idx==len)
322  cum_derivatives[len-1]+= factor ;
323  else
324  {
325  cum_derivatives[idx] += factor * (d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
326  cum_derivatives[idx-1]+= factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
327  }
328 }
329 
331 {
332  ASSERT(use_svm>0);
333  float64_t d_value=d_values[use_svm-1] ;
334 
335  if (d_value<-1e+20)
336  return;
337 
338  switch (transform)
339  {
340  case T_LINEAR:
341  break ;
342  case T_LOG:
343  d_value = log(d_value) ;
344  break ;
345  case T_LOG_PLUS1:
346  d_value = log(d_value+1) ;
347  break ;
348  case T_LOG_PLUS3:
349  d_value = log(d_value+3) ;
350  break ;
351  case T_LINEAR_PLUS3:
352  d_value = d_value+3 ;
353  break ;
354  default:
355  SG_ERROR( "unknown transform\n") ;
356  break ;
357  }
358 
359  int32_t idx = 0 ;
360  for (int32_t i=0; i<len; i++)
361  if (limits[i]<=d_value)
362  idx++ ;
363  else
364  break ; // assume it is monotonically increasing
365 
366  if (idx==0)
367  cum_derivatives[0]+=factor ;
368  else if (idx==len)
369  cum_derivatives[len-1]+=factor ;
370  else
371  {
372  cum_derivatives[idx] += factor*(d_value-limits[idx-1])/(limits[idx]-limits[idx-1]) ;
373  cum_derivatives[idx-1] += factor*(limits[idx]-d_value)/(limits[idx]-limits[idx-1]) ;
374  }
375 }
376 
377 void CPlif::get_used_svms(int32_t* num_svms, int32_t* svm_ids)
378 {
379  if (use_svm)
380  {
381  svm_ids[(*num_svms)] = use_svm;
382  (*num_svms)++;
383  }
384  SG_PRINT("->use_svm:%i plif_id:%i name:%s trans_type:%s ",use_svm, get_id(), get_name(), get_transform_type());
385 }
386 
388 {
389  return do_calc;
390 }
391 
392 void CPlif::set_do_calc(bool b)
393 {
394  do_calc = b;;
395 }

SHOGUN Machine Learning Toolbox - Documentation