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