SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MulticlassOCAS.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) 2009-2012 Vojtech Franc and Soeren Sonnenburg
8  * Written (W) 2012 Sergey Lisitsyn
9  * Copyright (C) 2009-2012 Vojtech Franc and Soeren Sonnenburg
10  */
11 
16 
17 using namespace shogun;
18 
19 struct mocas_data
20 {
27  uint32_t nY;
28  uint32_t nData;
29  uint32_t nDim;
31 };
32 
35 {
36  register_parameters();
37  set_C(1.0);
38  set_epsilon(1e-2);
39  set_max_iter(1000000);
40  set_method(1);
41  set_buf_size(5000);
42 }
43 
44 CMulticlassOCAS::CMulticlassOCAS(float64_t C, CDotFeatures* train_features, CLabels* train_labels) :
45  CLinearMulticlassMachine(new CMulticlassOneVsRestStrategy(), train_features, NULL, train_labels), m_C(C)
46 {
47  register_parameters();
48  set_epsilon(1e-2);
49  set_max_iter(1000000);
50  set_method(1);
51  set_buf_size(5000);
52 }
53 
54 void CMulticlassOCAS::register_parameters()
55 {
56  SG_ADD(&m_C, "m_C", "regularization constant", MS_AVAILABLE);
57  SG_ADD(&m_epsilon, "m_epsilon", "solver relative tolerance", MS_NOT_AVAILABLE);
58  SG_ADD(&m_max_iter, "m_max_iter", "max number of iterations", MS_NOT_AVAILABLE);
59  SG_ADD(&m_method, "m_method", "used solver method", MS_NOT_AVAILABLE);
60  SG_ADD(&m_buf_size, "m_buf_size", "buffer size", MS_NOT_AVAILABLE);
61 }
62 
64 {
65 }
66 
68 {
69  if (data)
70  set_features((CDotFeatures*)data);
71 
75 
76  int32_t num_vectors = m_features->get_num_vectors();
77  int32_t num_classes = m_multiclass_strategy->get_num_classes();
78  int32_t num_features = m_features->get_dim_feature_space();
79 
80  float64_t C = m_C;
81  SGVector<float64_t> labels = ((CMulticlassLabels*) m_labels)->get_labels();
82  uint32_t nY = num_classes;
83  uint32_t nData = num_vectors;
84  float64_t TolRel = m_epsilon;
85  float64_t TolAbs = 0.0;
86  float64_t QPBound = 0.0;
87  float64_t MaxTime = m_max_train_time;
88  uint32_t BufSize = m_buf_size;
89  uint8_t Method = m_method;
90 
91  mocas_data user_data;
92  user_data.features = m_features;
93  user_data.W = SG_MALLOC(float64_t, (int64_t)num_features*num_classes);
94  user_data.oldW = SG_MALLOC(float64_t, (int64_t)num_features*num_classes);
95  user_data.new_a = SG_MALLOC(float64_t, (int64_t)num_features*num_classes);
96  user_data.full_A = SG_MALLOC(float64_t, (int64_t)num_features*num_classes*m_buf_size);
97  user_data.output_values = SG_MALLOC(float64_t, num_vectors);
98  user_data.data_y = labels.vector;
99  user_data.nY = num_classes;
100  user_data.nDim = num_features;
101  user_data.nData = num_vectors;
102 
103  ocas_return_value_T value =
104  msvm_ocas_solver(C, labels.vector, nY, nData, TolRel, TolAbs,
105  QPBound, MaxTime, BufSize, Method,
112  &user_data);
113 
114  SG_DEBUG("Number of iterations [nIter] = %d \n",value.nIter)
115  SG_DEBUG("Number of cutting planes [nCutPlanes] = %d \n",value.nCutPlanes)
116  SG_DEBUG("Number of non-zero alphas [nNZAlpha] = %d \n",value.nNZAlpha)
117  SG_DEBUG("Number of training errors [trn_err] = %d \n",value.trn_err)
118  SG_DEBUG("Primal objective value [Q_P] = %f \n",value.Q_P)
119  SG_DEBUG("Dual objective value [Q_D] = %f \n",value.Q_D)
120  SG_DEBUG("Output time [output_time] = %f \n",value.output_time)
121  SG_DEBUG("Sort time [sort_time] = %f \n",value.sort_time)
122  SG_DEBUG("Add time [add_time] = %f \n",value.add_time)
123  SG_DEBUG("W time [w_time] = %f \n",value.w_time)
124  SG_DEBUG("QP solver time [qp_solver_time] = %f \n",value.qp_solver_time)
125  SG_DEBUG("OCAS time [ocas_time] = %f \n",value.ocas_time)
126  SG_DEBUG("Print time [print_time] = %f \n",value.print_time)
127  SG_DEBUG("QP exit flag [qp_exitflag] = %d \n",value.qp_exitflag)
128  SG_DEBUG("Exit flag [exitflag] = %d \n",value.exitflag)
129 
131  for (int32_t i=0; i<num_classes; i++)
132  {
133  CLinearMachine* machine = new CLinearMachine();
134  machine->set_w(SGVector<float64_t>(&user_data.W[i*num_features],num_features,false).clone());
135 
136  m_machines->push_back(machine);
137  }
138 
139  SG_FREE(user_data.W);
140  SG_FREE(user_data.oldW);
141  SG_FREE(user_data.new_a);
142  SG_FREE(user_data.full_A);
143  SG_FREE(user_data.output_values);
144 
145  return true;
146 }
147 
149 {
150  float64_t* W = ((mocas_data*)user_data)->W;
151  float64_t* oldW = ((mocas_data*)user_data)->oldW;
152  uint32_t nY = ((mocas_data*)user_data)->nY;
153  uint32_t nDim = ((mocas_data*)user_data)->nDim;
154 
155  for(uint32_t j=0; j < nY*nDim; j++)
156  W[j] = oldW[j]*(1-t) + t*W[j];
157 
158  float64_t sq_norm_W = SGVector<float64_t>::dot(W,W,nDim*nY);
159 
160  return sq_norm_W;
161 }
162 
164  float64_t *alpha, uint32_t nSel, void* user_data)
165 {
166  float64_t* W = ((mocas_data*)user_data)->W;
167  float64_t* oldW = ((mocas_data*)user_data)->oldW;
168  float64_t* full_A = ((mocas_data*)user_data)->full_A;
169  uint32_t nY = ((mocas_data*)user_data)->nY;
170  uint32_t nDim = ((mocas_data*)user_data)->nDim;
171 
172  uint32_t i,j;
173 
174  memcpy(oldW, W, sizeof(float64_t)*nDim*nY);
175  memset(W, 0, sizeof(float64_t)*nDim*nY);
176 
177  for(i=0; i<nSel; i++)
178  {
179  if(alpha[i] > 0)
180  {
181  for(j=0; j<nDim*nY; j++)
182  W[j] += alpha[i]*full_A[LIBOCAS_INDEX(j,i,nDim*nY)];
183  }
184  }
185 
186  *sq_norm_W = SGVector<float64_t>::dot(W,W,nDim*nY);
187  *dp_WoldW = SGVector<float64_t>::dot(W,oldW,nDim*nY);
188 
189  return;
190 }
191 
192 int CMulticlassOCAS::msvm_full_add_new_cut(float64_t *new_col_H, uint32_t *new_cut,
193  uint32_t nSel, void* user_data)
194 {
195  float64_t* full_A = ((mocas_data*)user_data)->full_A;
196  float64_t* new_a = ((mocas_data*)user_data)->new_a;
197  float64_t* data_y = ((mocas_data*)user_data)->data_y;
198  uint32_t nY = ((mocas_data*)user_data)->nY;
199  uint32_t nDim = ((mocas_data*)user_data)->nDim;
200  uint32_t nData = ((mocas_data*)user_data)->nData;
201  CDotFeatures* features = ((mocas_data*)user_data)->features;
202 
203  float64_t sq_norm_a;
204  uint32_t i, j, y, y2;
205 
206  memset(new_a, 0, sizeof(float64_t)*nDim*nY);
207 
208  for(i=0; i < nData; i++)
209  {
210  y = (uint32_t)(data_y[i]);
211  y2 = (uint32_t)new_cut[i];
212  if(y2 != y)
213  {
214  features->add_to_dense_vec(1.0,i,&new_a[nDim*y],nDim);
215  features->add_to_dense_vec(-1.0,i,&new_a[nDim*y2],nDim);
216  }
217  }
218 
219  // compute new_a'*new_a and insert new_a to the last column of full_A
220  sq_norm_a = SGVector<float64_t>::dot(new_a,new_a,nDim*nY);
221  for(j=0; j < nDim*nY; j++ )
222  full_A[LIBOCAS_INDEX(j,nSel,nDim*nY)] = new_a[j];
223 
224  new_col_H[nSel] = sq_norm_a;
225  for(i=0; i < nSel; i++)
226  {
227  float64_t tmp = 0;
228 
229  for(j=0; j < nDim*nY; j++ )
230  tmp += new_a[j]*full_A[LIBOCAS_INDEX(j,i,nDim*nY)];
231 
232  new_col_H[i] = tmp;
233  }
234 
235  return 0;
236 }
237 
239 {
240  float64_t* W = ((mocas_data*)user_data)->W;
241  uint32_t nY = ((mocas_data*)user_data)->nY;
242  uint32_t nDim = ((mocas_data*)user_data)->nDim;
243  uint32_t nData = ((mocas_data*)user_data)->nData;
244  float64_t* output_values = ((mocas_data*)user_data)->output_values;
245  CDotFeatures* features = ((mocas_data*)user_data)->features;
246 
247  uint32_t i, y;
248 
249  for(y=0; y<nY; y++)
250  {
251  features->dense_dot_range(output_values,0,nData,NULL,&W[nDim*y],nDim,0.0);
252  for (i=0; i<nData; i++)
253  output[LIBOCAS_INDEX(y,i,nY)] = output_values[i];
254  }
255 
256  return 0;
257 }
258 
259 int CMulticlassOCAS::msvm_sort_data(float64_t* vals, float64_t* data, uint32_t size)
260 {
261  CMath::qsort_index(vals, data, size);
262  return 0;
263 }
264 
265 void CMulticlassOCAS::msvm_print(ocas_return_value_T value)
266 {
267 }

SHOGUN Machine Learning Toolbox - Documentation