SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
StochasticSOSVM.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) 2013 Shell Hu
8  * Copyright (C) 2013 Shell Hu
9  */
10 
14 #include <shogun/lib/SGVector.h>
15 
16 using namespace shogun;
17 
20 {
21  init();
22 }
23 
25  CStructuredModel* model,
26  CStructuredLabels* labs,
27  bool do_weighted_averaging,
28  bool verbose)
29 : CLinearStructuredOutputMachine(model, labs)
30 {
31  REQUIRE(model != NULL && labs != NULL,
32  "%s::CStochasticSOSVM(): model and labels cannot be NULL!\n", get_name());
33 
34  REQUIRE(labs->get_num_labels() > 0,
35  "%s::CStochasticSOSVM(): number of labels should be greater than 0!\n", get_name());
36 
37  init();
38  m_lambda = 1.0 / labs->get_num_labels();
39  m_do_weighted_averaging = do_weighted_averaging;
40  m_verbose = verbose;
41 }
42 
43 void CStochasticSOSVM::init()
44 {
45  SG_ADD(&m_lambda, "lambda", "Regularization constant", MS_NOT_AVAILABLE);
46  SG_ADD(&m_num_iter, "num_iter", "Number of iterations", MS_NOT_AVAILABLE);
47  SG_ADD(&m_do_weighted_averaging, "do_weighted_averaging", "Do weighted averaging", MS_NOT_AVAILABLE);
48  SG_ADD(&m_debug_multiplier, "debug_multiplier", "Debug multiplier", MS_NOT_AVAILABLE);
49  SG_ADD(&m_rand_seed, "rand_seed", "Random seed", MS_NOT_AVAILABLE);
50 
51  m_lambda = 1.0;
52  m_num_iter = 50;
53  m_do_weighted_averaging = true;
54  m_debug_multiplier = 0;
55  m_rand_seed = 1;
56 }
57 
59 {
60 }
61 
63 {
64  return CT_STOCHASTICSOSVM;
65 }
66 
68 {
69  SG_DEBUG("Entering CStochasticSOSVM::train_machine.\n");
70  if (data)
71  set_features(data);
72 
73  // Initialize the model for training
75  // Check that the scenary is correct to start with training
77  SG_DEBUG("The training setup is correct.\n");
78 
79  // Dimensionality of the joint feature space
80  int32_t M = m_model->get_dim();
81  // Number of training examples
83 
84  SG_DEBUG("M=%d, N =%d.\n", M, N);
85 
86  // Initialize the weight vector
88  m_w.zero();
89 
90  SGVector<float64_t> w_avg;
91  if (m_do_weighted_averaging)
92  w_avg = m_w.clone();
93 
94  // logging
95  if (m_verbose)
96  {
97  if (m_helper != NULL)
99 
100  m_helper = new CSOSVMHelper();
101  SG_REF(m_helper);
102  }
103 
104  int32_t debug_iter = 1;
105  if (m_debug_multiplier == 0)
106  {
107  debug_iter = N;
108  m_debug_multiplier = 100;
109  }
110 
111  CMath::init_random(m_rand_seed);
112 
113  // Main loop
114  int32_t k = 0;
115  for (int32_t pi = 0; pi < m_num_iter; ++pi)
116  {
117  for (int32_t si = 0; si < N; ++si)
118  {
119  // 1) Picking random example
120  int32_t i = CMath::random(0, N-1);
121 
122  // 2) solve the loss-augmented inference for point i
123  CResultSet* result = m_model->argmax(m_w, i);
124 
125  // 3) get the subgradient
126  // psi_i(y) := phi(x_i,y_i) - phi(x_i, y)
127  SGVector<float64_t> psi_i(M);
128  SGVector<float64_t> w_s(M);
129 
130  if (result->psi_computed)
131  {
133  1.0, result->psi_truth.vector, -1.0, result->psi_pred.vector,
134  psi_i.vlen);
135  }
136  else if(result->psi_computed_sparse)
137  {
138  psi_i.zero();
139  result->psi_pred_sparse.add_to_dense(1.0, psi_i.vector, psi_i.vlen);
140  result->psi_truth_sparse.add_to_dense(-1.0, psi_i.vector, psi_i.vlen);
141  }
142  else
143  {
144  SG_ERROR("model(%s) should have either of psi_computed or psi_computed_sparse"
145  "to be set true\n", m_model->get_name());
146  }
147 
148  w_s = psi_i.clone();
149  w_s.scale(1.0 / (N*m_lambda));
150 
151  // 4) step-size gamma
152  float64_t gamma = 1.0 / (k+1.0);
153 
154  // 5) finally update the weights
156  1.0-gamma, m_w.vector, gamma*N, w_s.vector, m_w.vlen);
157 
158  // 6) Optionally, update the weighted average
159  if (m_do_weighted_averaging)
160  {
161  float64_t rho = 2.0 / (k+2.0);
163  1.0-rho, w_avg.vector, rho, m_w.vector, w_avg.vlen);
164  }
165 
166  k += 1;
167  SG_UNREF(result);
168 
169  // Debug: compute objective and training error
170  if (m_verbose && k == debug_iter)
171  {
172  SGVector<float64_t> w_debug;
173  if (m_do_weighted_averaging)
174  w_debug = w_avg.clone();
175  else
176  w_debug = m_w.clone();
177 
178  float64_t primal = CSOSVMHelper::primal_objective(w_debug, m_model, m_lambda);
179  float64_t train_error = CSOSVMHelper::average_loss(w_debug, m_model);
180 
181  SG_DEBUG("pass %d (iteration %d), SVM primal = %f, train_error = %f \n",
182  pi, k, primal, train_error);
183 
184  m_helper->add_debug_info(primal, (1.0*k) / N, train_error);
185 
186  debug_iter = CMath::min(debug_iter+N, debug_iter*(1+m_debug_multiplier/100));
187  }
188  }
189  }
190 
191  if (m_do_weighted_averaging)
192  m_w = w_avg.clone();
193 
194  if (m_verbose)
195  m_helper->terminate();
196 
197  SG_DEBUG("Leaving CStochasticSOSVM::train_machine.\n");
198  return true;
199 }
200 
202 {
203  return m_lambda;
204 }
205 
207 {
208  m_lambda = lbda;
209 }
210 
212 {
213  return m_num_iter;
214 }
215 
216 void CStochasticSOSVM::set_num_iter(int32_t num_iter)
217 {
218  m_num_iter = num_iter;
219 }
220 
222 {
223  return m_debug_multiplier;
224 }
225 
227 {
228  m_debug_multiplier = multiplier;
229 }
230 
232 {
233  return m_rand_seed;
234 }
235 
236 void CStochasticSOSVM::set_rand_seed(uint32_t rand_seed)
237 {
238  m_rand_seed = rand_seed;
239 }
240 

SHOGUN Machine Learning Toolbox - Documentation