SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShareBoost.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) 2012 Chiyuan Zhang
8  * Copyright (C) 2012 Chiyuan Zhang
9  */
10 
11 #include <algorithm>
12 
13 #include <shogun/lib/Time.h>
19 
20 using namespace shogun;
21 
23  :CLinearMulticlassMachine(), m_nonzero_feas(0)
24 {
25  init_sb_params();
26 }
27 
28 CShareBoost::CShareBoost(CDenseFeatures<float64_t> *features, CMulticlassLabels *labs, int32_t num_nonzero_feas)
29  :CLinearMulticlassMachine(new CMulticlassOneVsRestStrategy(), features, NULL, labs), m_nonzero_feas(num_nonzero_feas)
30 {
31  init_sb_params();
32 }
33 
34 void CShareBoost::init_sb_params()
35 {
36  SG_ADD(&m_nonzero_feas, "m_nonzero_feas", "Number of non-zero features", MS_NOT_AVAILABLE);
37 }
38 
40 {
41  return m_activeset.clone();
42 }
43 
45 {
46  if (data)
47  set_features(data);
48 
49  if (m_features == NULL)
50  SG_ERROR("No features given for training\n")
51  if (m_labels == NULL)
52  SG_ERROR("No labels given for training\n")
53 
54  if (m_nonzero_feas <= 0)
55  SG_ERROR("Set a valid (> 0) number of non-zero features to seek before training\n")
56  if (m_nonzero_feas >= dynamic_cast<CDenseFeatures<float64_t>*>(m_features)->get_num_features())
57  SG_ERROR("It doesn't make sense to use ShareBoost with num non-zero features >= num features in the data\n")
58 
59  m_fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features)->get_feature_matrix();
61  m_rho_norm = SGVector<float64_t>(m_fea.num_cols);
63  m_pred.zero();
64 
65  m_activeset = SGVector<int32_t>(m_fea.num_rows);
66  m_activeset.vlen = 0;
67 
69  for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
71 
72  CTime *timer = new CTime();
73 
74  float64_t t_compute_pred = 0; // t of 1st round is 0, since no pred to compute
75  for (int32_t t=0; t < m_nonzero_feas; ++t)
76  {
77  timer->start();
78  compute_rho();
79  int32_t i_fea = choose_feature();
80  m_activeset.vector[m_activeset.vlen] = i_fea;
81  m_activeset.vlen += 1;
82  float64_t t_choose_feature = timer->cur_time_diff();
83  timer->start();
84  optimize_coefficients();
85  float64_t t_optimize = timer->cur_time_diff();
86 
87  SG_SDEBUG(" SB[round %03d]: (%8.4f + %8.4f) sec.\n", t,
88  t_compute_pred + t_choose_feature, t_optimize);
89 
90  timer->start();
91  compute_pred();
92  t_compute_pred = timer->cur_time_diff();
93  }
94 
95  SG_UNREF(timer);
96 
97  // release memory
98  m_fea = SGMatrix<float64_t>();
99  m_rho = SGMatrix<float64_t>();
100  m_rho_norm = SGVector<float64_t>();
101  m_pred = SGMatrix<float64_t>();
102 
103  return true;
104 }
105 
106 void CShareBoost::compute_pred()
107 {
109  CDenseSubsetFeatures<float64_t> *subset_fea = new CDenseSubsetFeatures<float64_t>(fea, m_activeset);
110  SG_REF(subset_fea);
111  for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
112  {
113  CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
114  CRegressionLabels *lab = machine->apply_regression(subset_fea);
115  SGVector<float64_t> lab_raw = lab->get_labels();
116  std::copy(lab_raw.vector, lab_raw.vector + lab_raw.vlen, m_pred.get_column_vector(i));
117  SG_UNREF(machine);
118  SG_UNREF(lab);
119  }
120  SG_UNREF(subset_fea);
121 }
122 
123 void CShareBoost::compute_pred(const float64_t *W)
124 {
125  int32_t w_len = m_activeset.vlen;
126 
127  for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
128  {
129  CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
130  SGVector<float64_t> w(w_len);
131  std::copy(W + i*w_len, W + (i+1)*w_len, w.vector);
132  machine->set_w(w);
133  SG_UNREF(machine);
134  }
135  compute_pred();
136 }
137 
138 void CShareBoost::compute_rho()
139 {
140  CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
141  for (int32_t i=0; i < m_rho.num_rows; ++i)
142  { // i loop classes
143  for (int32_t j=0; j < m_rho.num_cols; ++j)
144  { // j loop samples
145  int32_t label = lab->get_int_label(j);
146 
147  m_rho(i,j) = CMath::exp((label == i) - m_pred(j, label) + m_pred(j, i));
148  }
149  }
150 
151  // normalize
152  for (int32_t j=0; j < m_rho.num_cols; ++j)
153  {
154  m_rho_norm[j] = 0;
155  for (int32_t i=0; i < m_rho.num_rows; ++i)
156  m_rho_norm[j] += m_rho(i,j);
157  }
158 }
159 
160 int32_t CShareBoost::choose_feature()
161 {
162  SGVector<float64_t> l1norm(m_fea.num_rows);
163  for (int32_t j=0; j < m_fea.num_rows; ++j)
164  {
165  if (std::find(&m_activeset[0], &m_activeset[m_activeset.vlen], j) !=
166  &m_activeset[m_activeset.vlen])
167  {
168  l1norm[j] = 0;
169  }
170  else
171  {
172  l1norm[j] = 0;
173  CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
174  for (int32_t k=0; k < m_multiclass_strategy->get_num_classes(); ++k)
175  {
176  float64_t abssum = 0;
177  for (int32_t ii=0; ii < m_fea.num_cols; ++ii)
178  {
179  abssum += m_fea(j, ii)*(m_rho(k, ii)/m_rho_norm[ii] -
180  (j == lab->get_int_label(ii)));
181  }
182  l1norm[j] += CMath::abs(abssum);
183  }
184  l1norm[j] /= m_fea.num_cols;
185  }
186  }
187 
188  return CMath::arg_max(l1norm.vector, 1, l1norm.vlen);
189 }
190 
191 void CShareBoost::optimize_coefficients()
192 {
193  ShareBoostOptimizer optimizer(this, false);
194  optimizer.optimize();
195 }
196 
198 {
199  CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(f);
200  if (fea == NULL)
201  SG_ERROR("Require DenseFeatures<float64_t>\n")
203 }

SHOGUN Machine Learning Toolbox - Documentation