SHOGUN  6.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
ModelSelectionParameters.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) 2011-2012 Heiko Strathmann
8  * Written (W) 2012 Jacob Walker
9  *
10  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
11  */
12 
15 #include <shogun/lib/DataType.h>
16 #include <shogun/base/Parameter.h>
17 #include <shogun/base/DynArray.h>
18 #include <shogun/lib/Set.h>
19 
20 using namespace shogun;
21 
23 {
24  init();
25 }
26 
28 {
29  init();
30 
31  m_node_name=node_name;
32 }
33 
35  CSGObject* sgobject)
36 {
37  init();
38 
39  m_node_name=node_name;
40  m_sgobject=sgobject;
41  SG_REF(sgobject);
42 }
43 
44 void CModelSelectionParameters::init()
45 {
46  m_node_name=NULL;
47  m_sgobject=NULL;
48  m_child_nodes=new CDynamicObjectArray();
49  SG_REF(m_child_nodes);
50  m_value_type=MSPT_NONE;
51  m_values=NULL;
52  m_values_length=0;
53 
54  /* no parameter registering. These parameter nodes will not be serialized */
55 }
56 
58 {
59  SG_UNREF(m_child_nodes);
60  SG_UNREF(m_sgobject);
61 
62  delete_values();
63 }
64 
66 {
67  /* only possible if there are no values set */
68  if (m_values)
69  SG_ERROR("not possible to append child: there already is a range\n")
70 
71  /* do a basic check if the add is possible */
72  if (m_sgobject)
73  {
74  /* (does this node's CSGObject contain a parameter with the name of the
75  * child?) to prevent problems when trying to set parameters that do not
76  * exist */
77  if (child->m_node_name)
78  {
79  if (!m_sgobject->m_parameters->contains_parameter(child->m_node_name))
80  {
81  SG_ERROR("Not possible to add child, node with CSGObject \"%s\""
82  " does not contain a parameter called \"%s\"\n",
83  m_sgobject->get_name(), child->m_node_name);
84  }
85  }
86  else
87  {
88  SG_ERROR("Not possible to add child which has no name.\n")
89  }
90  }
91 
92  m_child_nodes->append_element(child);
93 }
94 
96  ERangeType type, float64_t step, float64_t type_base)
97 {
98  build_values(MSPT_FLOAT64, (void*)&min, (void*)&max, type, (void*)&step,
99  (void*)&type_base);
100 }
101 
103  ERangeType type, void* vector, index_t* size, float64_t step, float64_t type_base)
104 {
105  build_values(MSPT_FLOAT64_VECTOR, (void*)&min, (void*)&max, type, (void*)&step,
106  (void*)&type_base);
107  m_vector_length = size;
108  m_vector = vector;
109 }
110 
112  ERangeType type, void* vector, float64_t step, float64_t type_base)
113 {
114  build_values(MSPT_FLOAT64_SGVECTOR, (void*)&min, (void*)&max, type, (void*)&step,
115  (void*)&type_base);
116  m_vector = vector;
117 }
118 
120  ERangeType type, int32_t step, int32_t type_base)
121 {
122  build_values(MSPT_INT32, (void*)&min, (void*)&max, type, (void*)&step,
123  (void*)&type_base);
124 }
125 
127  ERangeType type, void* vector, index_t* size, int32_t step, int32_t type_base)
128 {
129  build_values(MSPT_INT32_VECTOR, (void*)&min, (void*)&max, type, (void*)&step,
130  (void*)&type_base);
131  m_vector_length = size;
132  m_vector = vector;
133 }
134 
136  ERangeType type, void* vector, int32_t step, int32_t type_base)
137 {
138  build_values(MSPT_INT32_SGVECTOR, (void*)&min, (void*)&max, type, (void*)&step,
139  (void*)&type_base);
140  m_vector = vector;
141 }
142 
143 void CModelSelectionParameters::build_values(EMSParamType value_type, void* min,
144  void* max, ERangeType type, void* step, void* type_base)
145 {
146  if (m_sgobject || has_children())
147  {
148  SG_ERROR("unable to set range for an CSGObject model selection "
149  "parameter\n");
150  }
151 
152  /* possibly delete old range values */
153  delete_values();
154 
155  /* save new type */
156  m_value_type=value_type;
157 
158  if (value_type==MSPT_FLOAT64 ||
159  value_type==MSPT_FLOAT64_VECTOR
160  || value_type==MSPT_FLOAT64_SGVECTOR)
161  {
162  SGVector<float64_t> values=create_range_array<float64_t>(
163  *((float64_t*)min),
164  *((float64_t*)max),
165  type,
166  *((float64_t*)step),
167  *((float64_t*)type_base));
168 
169  m_values=values.vector;
170  m_values_length=values.vlen;
171  }
172  else if (value_type==MSPT_INT32 ||
173  value_type==MSPT_INT32_VECTOR
174  || value_type==MSPT_INT32_SGVECTOR)
175  {
176  SGVector<int32_t> values=create_range_array<int32_t>(
177  *((int32_t*)min),
178  *((int32_t*)max),
179  type,
180  *((int32_t*)step),
181  *((int32_t*)type_base));
182 
183  m_values=values.vector;
184  m_values_length=values.vlen;
185  }
186  else if (value_type==MSPT_NONE)
187  {
188  SG_ERROR("Value node has no type!\n")
189  }
190  else
191  {
192  SG_ERROR("Unknown type for model selection parameter!\n")
193  }
194 }
195 
197  bool is_rand)
198 {
199  /* If this is a value node, then randomly pick a value from the built
200  * range */
201  if (m_values)
202  {
203 
204  index_t i = 0;
205 
206  if (is_rand)
207  i = CMath::random(0, m_values_length-1);
208 
209  Parameter* p=new Parameter();
210 
211  switch (m_value_type)
212  {
214  {
215  SGVector<float64_t>* param_vect = (SGVector<float64_t>*)m_vector;
216 
217  for (index_t j = 0; j < param_vect->vlen; j++)
218  {
219  if (is_rand)
220  i = CMath::random(0, m_values_length-1);
221  (*param_vect)[j] = ((float64_t*)m_values)[i];
222  }
223  p->add(param_vect, m_node_name);
224  break;
225  }
226  case MSPT_FLOAT64_VECTOR:
227  {
228  float64_t* param_vect = (float64_t*)m_vector;
229 
230  for (index_t j = 0; j < *m_vector_length; j++)
231  {
232  if (is_rand)
233  i = CMath::random(0, m_values_length-1);
234  (param_vect)[j] = ((float64_t*)m_values)[i];
235  }
236  p->add_vector(&param_vect, m_vector_length, m_node_name);
237  break;
238  }
239  case MSPT_INT32_SGVECTOR:
240  {
241  SGVector<int32_t>* param_vect = (SGVector<int32_t>*)m_vector;
242 
243  for (index_t j = 0; j < param_vect->vlen; j++)
244  {
245  if (is_rand)
246  i = CMath::random(0, m_values_length-1);
247  (*param_vect)[j] = ((int32_t*)m_values)[i];
248  }
249  p->add(param_vect, m_node_name);
250  break;
251  }
252  case MSPT_INT32_VECTOR:
253  {
254  int32_t* param_vect = (int32_t*)m_vector;
255 
256  for (index_t j = 0; j < *m_vector_length; j++)
257  {
258  if (is_rand)
259  i = CMath::random(0, m_values_length-1);
260  (param_vect)[j] = ((int32_t*)m_values)[i];
261  }
262  p->add_vector(&param_vect, m_vector_length, m_node_name);
263  break;
264  }
265  case MSPT_FLOAT64:
266  p->add(&((float64_t*)m_values)[i], m_node_name);
267  break;
268  case MSPT_INT32:
269  p->add(&((int32_t*)m_values)[i], m_node_name);;
270  break;
271  case MSPT_NONE:
272  SG_ERROR("Value node has no type!\n")
273  break;
274  default:
275  SG_ERROR("Unknown type for model selection parameter!\n")
276  break;
277  }
278 
279  return new CParameterCombination(p);
280  }
281 
282  CParameterCombination* new_root=NULL;
283 
284  /*Complain if we have a bad node*/
285  if (!((m_sgobject && m_node_name) || (!m_node_name && !m_sgobject)))
286  SG_ERROR("Illegal CModelSelectionParameters node type.\n")
287 
288  /* Incorporate SGObject and root nodes with children*/
289  if (m_child_nodes->get_num_elements())
290  {
291 
292  if (m_sgobject)
293  {
294  Parameter* p=new Parameter();
295  p->add(&m_sgobject, m_node_name);
296  new_root = new CParameterCombination(p);
297  }
298 
299  else
300  new_root = new CParameterCombination();
301 
302  for (index_t i = 0; i < m_child_nodes->get_num_elements(); ++i)
303  {
304  CModelSelectionParameters* current =
305  (CModelSelectionParameters*)m_child_nodes->get_element(i);
306 
307  CParameterCombination* c = current->get_single_combination(is_rand);
308 
309  new_root->append_child(c);
310 
311  SG_UNREF(current);
312  }
313 
314  return new_root;
315  }
316 
317  /*Incorporate childless nodes*/
318  else
319  {
320 
321  if (m_sgobject)
322  {
323  Parameter* p = new Parameter();
324  p->add(&m_sgobject, m_node_name);
325  return new CParameterCombination(p);
326  }
327 
328  else
329  {
330  new_root = new CParameterCombination();
331  return new_root;
332  }
333  }
334 
335 }
336 
337 
338 
340  index_t num_prefix)
341 {
342  char* prefix=SG_MALLOC(char, num_prefix+1);
343  prefix[num_prefix]='\0';
344  for (index_t i=0; i<num_prefix; ++i)
345  prefix[i]='\t';
346 
347  SG_DEBUG("%s------>entering CModelSelectionParameters::get_combinations() "
348  "for \"%s\"\n", prefix, m_node_name ? m_node_name : "root");
350 
351  /* value case: node with values and no children.
352  * build trees of Parameter instances which each contain one value
353  */
354 
355  if (m_values)
356  {
357  for (index_t i=0; i<m_values_length; ++i)
358  {
359  // create tree with only one parameter element //
360  Parameter* p=new Parameter();
361 
362  switch (m_value_type)
363  {
364  case MSPT_FLOAT64:
365  p->add(&((float64_t*)m_values)[i], m_node_name);
366  break;
367  case MSPT_INT32:
368  p->add(&((int32_t*)m_values)[i], m_node_name);;
369  break;
370  case MSPT_NONE:
371  SG_ERROR("%sValue node has no type!\n", prefix)
372  break;
373  default:
374  SG_ERROR("%sUnknown type for model selection parameter!\n",
375  prefix);
376  break;
377  }
378 
379  result->append_element(new CParameterCombination(p));
380  }
381 
382  SG_DEBUG("%s------>leaving CModelSelectionParameters::get_combinations()"
383  "for \"%s\"\n", prefix, m_node_name ? m_node_name : "root");
384 
385  SG_FREE(prefix);
386  return result;
387  }
388 
389 
390  /* two cases here, similar
391  * -case CSGObject:
392  * -case root node (no name, no values, but children
393  * build all permutations of the result trees of children with values and
394  * combine them iteratively children which are something different
395  */
396  if (!((m_sgobject && m_node_name) || (!m_node_name && !m_sgobject)))
397  SG_ERROR("%sIllegal CModelSelectionParameters node type.\n", prefix)
398 
399  /* only consider combinations if this node has children */
400  if (m_child_nodes->get_num_elements())
401  {
402  /* split value and non-value child combinations */
403  CDynamicObjectArray value_children;
404  CDynamicObjectArray non_value_children;
405 
406  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
407  {
408  CModelSelectionParameters* current=
409  (CModelSelectionParameters*)m_child_nodes->get_element(i);
410 
411  /* split children with values and children with other */
412  if (current->m_values)
413  value_children.append_element(current);
414  else
415  non_value_children.append_element(current);
416 
417  SG_UNREF(current);
418  }
419 
420  /* extract all tree sets of all value children */
421  CDynamicObjectArray value_node_sets;
422  for (index_t i=0; i<value_children.get_num_elements(); ++i)
423  {
424  /* recursively get all combinations in a new array */
425  CModelSelectionParameters* value_child=
426  (CModelSelectionParameters*)value_children.get_element(i);
427  value_node_sets.append_element(value_child->get_combinations(
428  num_prefix+1));
429  SG_UNREF(value_child);
430  }
431 
432  /* build product of all these tree sets */
433 
434  /* new root node is needed for new trees, depends on current case */
435  CParameterCombination* new_root=NULL;
436  if (m_sgobject)
437  {
438  Parameter* p=new Parameter();
439  p->add(&m_sgobject, m_node_name);
440  new_root=new CParameterCombination(p);
441  }
442  else
443  new_root=new CParameterCombination();
444 
445  SG_REF(new_root);
446 
447  CDynamicObjectArray* value_combinations=
449  new_root);
450 
451  SG_UNREF(new_root);
452 
453  if (!non_value_children.get_num_elements())
454  *result=*value_combinations;
455  /* in the other case, the non-values have also to be treated, but
456  * combined iteratively */
457  else
458  {
459  /* extract all tree sets of non-value nodes */
460 // SG_PRINT("%sextracting combinations of non-value nodes\n", prefix)
461  CDynamicObjectArray* non_value_combinations=
462  new CDynamicObjectArray();
463  for (index_t i=0; i<non_value_children.get_num_elements(); ++i)
464  {
465  /* recursively get all combinations in a new array */
466  CModelSelectionParameters* non_value_child=
468  non_value_children.get_element(i);
469 
470 // SG_PRINT("%s\tcurrent non-value child\n", prefix)
471 // non_value_child->print_tree(num_prefix+1);
472 
473  CDynamicObjectArray* current_combination=
474  non_value_child->get_combinations(num_prefix+2);
475  non_value_combinations->append_element(current_combination);
476  SG_UNREF(non_value_child);
477 
478 // SG_PRINT("%s\tcombinations of non-value nodes:\n", prefix)
479 // for (index_t j=0; j<current_combination->get_num_elements(); ++j)
480 // {
481 // CParameterCombination* c=(CParameterCombination*)
482 // current_combination->get_element(j);
483 // c->print_tree(num_prefix+2);
484 // SG_UNREF(c);
485 // }
486  }
487 // SG_PRINT("%sdone extracting combinations of non-value nodes\n",
488 // prefix);
489 
490  /* Now, combine combinations of value and non-value nodes */
491 
492  /* if there are only non-value children, nothing is combined */
493  if (!value_combinations->get_num_elements())
494  {
495  /* non-value children have to be multipied first, then, all
496  * these products are just appended */
497 
498  /* temporary new root is needed to put fron all product trees */
499  if (m_sgobject)
500  {
501  Parameter* p=new Parameter();
502  p->add(&m_sgobject, m_node_name);
503  new_root=new CParameterCombination(p);
504  }
505  else
506  new_root=new CParameterCombination();
507 
508  CDynamicObjectArray* non_value_products=
510  non_value_combinations, new_root);
511 
512  SG_UNREF(new_root);
513 
514  SG_UNREF(non_value_combinations);
515  non_value_combinations=non_value_products;
516 
517  /* append all non-value combinations to result */
518  for (index_t i=0; i<non_value_combinations->get_num_elements(); ++i)
519  {
521  non_value_combinations->get_element(i);
522  result->append_element(current);
523  SG_UNREF(current);
524  }
525  }
526  else
527  {
528  /* before combinations are built, produce products of non-value
529  * combinations. new root is temporarily needed to put front
530  * all new trees */
531  if (m_sgobject)
532  {
533  Parameter* p=new Parameter();
534  p->add(&m_sgobject, m_node_name);
535  new_root=new CParameterCombination(p);
536  }
537  else
538  new_root=new CParameterCombination();
539 
540  CDynamicObjectArray* non_value_products=
542  non_value_combinations, new_root);
543 
544  SG_UNREF(new_root);
545 
546  SG_UNREF(non_value_combinations);
547  non_value_combinations=non_value_products;
548 
549  for (index_t i=0; i<value_combinations->get_num_elements(); ++i)
550  {
551  CParameterCombination* current_value_tree=
553  value_combinations->get_element(i);
554 
555  for (index_t j=0; j
556  <non_value_combinations->get_num_elements(); ++j)
557  {
558  CParameterCombination* current_non_value_tree=
560  non_value_combinations->get_element(j);
561 
562  /* copy current value tree and add all childs of non-
563  * value combination. Then add new node to result */
564  CParameterCombination* value_copy=
565  current_value_tree->copy_tree();
566 
567  value_copy->merge_with(current_non_value_tree);
568  result->append_element(value_copy);
569 
570  SG_UNREF(current_non_value_tree);
571  }
572 
573  SG_UNREF(current_value_tree);
574  }
575  }
576 
577  /* clean up*/
578  SG_UNREF(non_value_combinations);
579  }
580 
581  SG_UNREF(value_combinations);
582  }
583  else
584  {
585  /* if there are no children of a sgobject or root node, result is
586  * only one element (sgobject node) or empty (root node)
587  */
588  if (m_sgobject)
589  {
590  Parameter* p=new Parameter();
591  p->add(&m_sgobject, m_node_name);
592  result->append_element(new CParameterCombination(p));
593  }
594  }
595 
596 // SG_PRINT("%sresult is a set of %d elements:\n", prefix,
597 // result->get_num_elements());
598 // for (index_t i=0; i<result->get_num_elements(); ++i)
599 // {
600 // CParameterCombination* current=(CParameterCombination*)
601 // result->get_element(i);
602 // current->print_tree(num_prefix+1);
603 // SG_UNREF(current);
604 // }
605 
606  SG_DEBUG("%s------>leaving CModelSelectionParameters::get_combinations()"
607  "for \"%s\"\n", prefix, m_node_name ? m_node_name : "root");
608  SG_FREE(prefix);
609  return result;
610 }
611 
613 {
614  /* prefix is enlarged */
615  char* prefix=SG_MALLOC(char, prefix_num+1);
616  for (index_t i=0; i<prefix_num; ++i)
617  prefix[i]='\t';
618 
619  prefix[prefix_num]='\0';
620 
621  if (has_children())
622  {
623  if (m_sgobject)
624  SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name())
625  else
626  SG_PRINT("%s%s with\n", prefix, m_node_name ? m_node_name : "root")
627 
628  /* now recursively print successors */
629 
630  /* cast safe because only CModelSelectionParameters are added to list */
631  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
632  {
634  (CModelSelectionParameters*)m_child_nodes->get_element(i);
635  child->print_tree(prefix_num+1);
636  SG_UNREF(child);
637  }
638  }
639  else
640  {
641  /* has to be a node with name and a numeric range or a single sg_object
642  * without children*/
643  if (m_sgobject)
644  {
645  SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name())
646  }
647  else
648  {
649  if (m_values)
650  {
651  // value node
652  SG_PRINT("%s%s with values: ", prefix, m_node_name)
653 
654  switch (m_value_type)
655  {
658 
660  m_values_length);
661  break;
662  case MSPT_INT32: case MSPT_INT32_VECTOR:
663  case MSPT_INT32_SGVECTOR:
664 
665  SGVector<int32_t>::display_vector((int32_t*)m_values,
666  m_values_length);;
667  break;
668  case MSPT_NONE:
669  SG_ERROR("Value node has no type!\n")
670  break;
671  default:
672  SG_ERROR("Unknown type for model selection parameter!\n")
673  break;
674  }
675  }
676  else
677  SG_PRINT("root\n")
678  }
679  }
680 
681  SG_FREE(prefix);
682 }
683 
684 void CModelSelectionParameters::delete_values()
685 {
686  if (m_values)
687  {
688  switch (m_value_type)
689  {
692 
693  SG_FREE((float64_t*)m_values);
694  break;
695  case MSPT_INT32: case MSPT_INT32_VECTOR:
696  case MSPT_INT32_SGVECTOR:
697 
698  SG_FREE((int32_t*)m_values);
699  break;
700  case MSPT_NONE:
701  SG_ERROR("Value node has no type!\n")
702  break;
703  default:
704  SG_ERROR("Unknown type for model selection parameter!\n")
705  break;
706  }
707  }
708 }
virtual const char * get_name() const =0
int32_t index_t
Definition: common.h:72
#define SG_ERROR(...)
Definition: SGIO.h:128
Parameter * m_parameters
Definition: SGObject.h:567
CParameterCombination * copy_tree() const
#define SG_REF(x)
Definition: SGObject.h:52
Class to select parameters and their ranges for model selection. The structure is organized as a tree...
static uint64_t random()
Definition: Math.h:1014
void display_vector(const char *name="vector", const char *prefix="") const
Definition: SGVector.cpp:396
void add(bool *param, const char *name, const char *description="")
Definition: Parameter.cpp:38
index_t vlen
Definition: SGVector.h:545
#define SG_PRINT(...)
Definition: SGIO.h:136
Parameter class.
Class SGObject is the base class of all shogun objects.
Definition: SGObject.h:125
void merge_with(CParameterCombination *node)
double float64_t
Definition: common.h:60
void append_child(CParameterCombination *child)
void build_values_vector(float64_t min, float64_t max, ERangeType type, void *vector, index_t *size, float64_t step=1.0, float64_t type_base=2.0)
void build_values(float64_t min, float64_t max, ERangeType type, float64_t step=1.0, float64_t type_base=2.0)
Dynamic array class for CSGObject pointers that creates an array that can be used like a list or an a...
Class that holds ONE combination of parameters for a learning machine. The structure is organized as ...
CParameterCombination * get_single_combination(bool rand=true)
void build_values_sgvector(float64_t min, float64_t max, ERangeType type, void *vector, float64_t step=1.0, float64_t type_base=2.0)
#define SG_UNREF(x)
Definition: SGObject.h:53
bool contains_parameter(const char *name)
Definition: Parameter.cpp:2935
void add_vector(bool **param, index_t *length, const char *name, const char *description="")
Definition: Parameter.cpp:335
#define SG_DEBUG(...)
Definition: SGIO.h:106
all of classes and functions are contained in the shogun namespace
Definition: class_list.h:18
CDynamicObjectArray * get_combinations(index_t prefix_num=1)
CSGObject * get_element(int32_t index) const
T max(const Container< T > &a)
void append_child(CModelSelectionParameters *child)
static CDynamicObjectArray * non_value_tree_multiplication(const CDynamicObjectArray *sets, const CParameterCombination *new_root)
bool append_element(CSGObject *e)
static CDynamicObjectArray * leaf_sets_multiplication(const CDynamicObjectArray &sets, const CParameterCombination *new_root)

SHOGUN Machine Learning Toolbox - Documentation