Vowpal Wabbit
learner.cc
Go to the documentation of this file.
1 #include "parser.h"
2 #include "vw.h"
3 #include "parse_regressor.h"
4 #include "parse_dispatch_loop.h"
5 
6 namespace prediction_type
7 {
8 #define CASE(type) \
9  case type: \
10  return #type;
11 
13 {
14  switch (prediction_type)
15  {
16  CASE(scalar)
17  CASE(scalars)
22  CASE(prob)
24  default:
25  return "<unsupported>";
26  }
27 }
28 } // namespace prediction_type
29 
30 namespace LEARNER
31 {
32 void learn_ex(example& ec, vw& all)
33 {
34  all.learn(ec);
35  as_singleline(all.l)->finish_example(all, ec);
36 }
37 
38 void learn_multi_ex(multi_ex& ec_seq, vw& all)
39 {
40  all.learn(ec_seq);
41  as_multiline(all.l)->finish_example(all, ec_seq);
42 }
43 
44 void end_pass(example& ec, vw& all)
45 {
46  all.current_pass++;
47  all.l->end_pass();
48 
49  VW::finish_example(all, ec);
50 }
51 
52 void save(example& ec, vw& all)
53 {
54  // save state command
55  std::string final_regressor_name = all.final_regressor_name;
56 
57  if ((ec.tag).size() >= 6 && (ec.tag)[4] == '_')
58  final_regressor_name = std::string(ec.tag.begin() + 5, (ec.tag).size() - 5);
59 
60  if (!all.quiet)
61  all.trace_message << "saving regressor to " << final_regressor_name << std::endl;
62  save_predictor(all, final_regressor_name, 0);
63 
64  VW::finish_example(all, ec);
65 }
66 
67 /* is this just a newline */
69 {
70  // If we are using CCB, test against CCB implementation otherwise fallback to previous behavior.
71  bool is_header = false;
72  if (all.label_type == label_type::ccb)
73  {
74  is_header = CCB::ec_is_example_header(ec);
75  }
76  else
77  {
78  is_header = CB::ec_is_example_header(ec);
79  }
80 
81  return example_is_newline(ec) && !is_header;
82 }
83 
84 bool inline is_save_cmd(example* ec)
85 {
86  return (ec->tag.size() >= 4) && (0 == strncmp((const char*)ec->tag.begin(), "save", 4));
87 }
88 
89 void drain_examples(vw& all)
90 {
91  if (all.early_terminate)
92  { // drain any extra examples from parser.
93  example* ec = nullptr;
94  while ((ec = VW::get_example(all.p)) != nullptr) VW::finish_example(all, *ec);
95  }
96  all.l->end_examples();
97 }
98 
99 // single_instance_context / multi_instance_context - classes incapsulating single/multiinstance example processing
100 // get_master - returns main vw instance for owner's example manipulations (i.e. finish)
101 // process<process_impl> - call process_impl for all vw instances
103 {
104  public:
105  single_instance_context(vw& all) : _all(all) {}
106 
107  vw& get_master() const { return _all; }
108 
109  template <class T, void (*process_impl)(T&, vw&)>
110  void process(T& ec)
111  {
112  process_impl(ec, _all);
113  }
114 
115  private:
117 };
118 
120 {
121  public:
122  multi_instance_context(const std::vector<vw*>& all) : _all(all) {}
123 
124  vw& get_master() const { return *_all.front(); }
125 
126  template <class T, void (*process_impl)(T&, vw&)>
127  void process(T& ec)
128  {
129  // start with last as the first instance will free the example as it is the owner
130  for (auto it = _all.rbegin(); it != _all.rend(); ++it) process_impl(ec, **it);
131  }
132 
133  private:
134  std::vector<vw*> _all;
135 };
136 
137 // single_example_handler / multi_example_handler - consumer classes with on_example handle method, incapsulating
138 // creation of example / multi_ex and passing it to context.process
139 template <typename context_type>
141 {
142  public:
143  single_example_handler(const context_type& context) : _context(context) {}
144 
145  void on_example(example* ec)
146  {
147  if (ec->indices.size() > 1) // 1+ nonconstant feature. (most common case first)
148  _context.template process<example, learn_ex>(*ec);
149  else if (ec->end_pass)
150  _context.template process<example, end_pass>(*ec);
151  else if (is_save_cmd(ec))
152  _context.template process<example, save>(*ec);
153  else
154  _context.template process<example, learn_ex>(*ec);
155  }
156 
157  private:
158  context_type _context;
159 };
160 
161 template <typename context_type>
163 {
164  private:
166  {
167  auto& master = _context.get_master();
168  const bool is_test_ec = master.p->lp.test_label(&ec->l);
169  const bool is_newline = (example_is_newline_not_header(*ec, master) && is_test_ec);
170  if (!is_newline)
171  {
172  ec_seq.push_back(ec);
173  }
174  else
175  {
176  VW::finish_example(master, *ec);
177  }
178  return is_newline;
179  }
180 
182  {
183  if (ec->indices.size() > 1) // 1+ nonconstant feature. (most common case first)
184  return complete_multi_ex(ec);
185  else if (ec->end_pass)
186  _context.template process<example, end_pass>(*ec);
187  else if (is_save_cmd(ec))
188  _context.template process<example, save>(*ec);
189  else
190  return complete_multi_ex(ec);
191  return false;
192  }
193 
194  public:
195  multi_example_handler(const context_type context) : _context(context) {}
196 
198  {
199  if (!ec_seq.empty())
200  {
201  _context.template process<multi_ex, learn_multi_ex>(ec_seq);
202  }
203  }
204 
205  void on_example(example* ec)
206  {
207  if (try_complete_multi_ex(ec))
208  {
209  _context.template process<multi_ex, learn_multi_ex>(ec_seq);
210  ec_seq.clear();
211  }
212  }
213 
214  private:
215  context_type _context;
217 };
218 
219 // ready_examples_queue / custom_examples_queue - adapters for connecting example handler to parser produce-consume loop
220 // for single- and multi-threaded scenarios
222 {
223  public:
224  ready_examples_queue(vw& master) : _master(master) {}
225 
226  example* pop() { return !_master.early_terminate ? VW::get_example(_master.p) : nullptr; }
227 
228  private:
230 };
231 
233 {
234  public:
235  custom_examples_queue(v_array<example*> examples) : _examples(examples) {}
236 
237  example* pop() { return _index < _examples.size() ? _examples[_index++] : nullptr; }
238 
239  private:
241  size_t _index{0};
242 };
243 
244 template <typename queue_type, typename handler_type>
245 void process_examples(queue_type& examples, handler_type& handler)
246 {
247  example* ec;
248 
249  while ((ec = examples.pop()) != nullptr) handler.on_example(ec);
250 }
251 
252 template <typename context_type>
253 void generic_driver(ready_examples_queue& examples, context_type& context)
254 {
255  if (context.get_master().l->is_multiline)
256  {
257  using handler_type = multi_example_handler<context_type>;
258  handler_type handler(context);
259  process_examples(examples, handler);
260  }
261  else
262  {
263  using handler_type = single_example_handler<context_type>;
264  handler_type handler(context);
265  process_examples(examples, handler);
266  }
267  drain_examples(context.get_master());
268 }
269 
270 void generic_driver(vw& all)
271 {
272  single_instance_context context(all);
273  ready_examples_queue examples(all);
274  generic_driver(examples, context);
275 }
276 
277 void generic_driver(const std::vector<vw*>& all)
278 {
279  multi_instance_context context(all);
280  ready_examples_queue examples(context.get_master());
281  generic_driver(examples, context);
282 }
283 
284 template <typename handler_type>
286 {
287  single_instance_context context(all);
288  handler_type handler(context);
289  auto multi_ex_fptr = [&handler](vw& all, v_array<example*> examples) {
290  all.p->end_parsed_examples += examples.size(); // divergence: lock & signal
291  custom_examples_queue examples_queue(examples);
292  process_examples(examples_queue, handler);
293  };
294  parse_dispatch(all, multi_ex_fptr);
295  all.l->end_examples();
296 }
297 
298 void generic_driver_onethread(vw& all)
299 {
300  if (all.l->is_multiline)
301  generic_driver_onethread<multi_example_handler<single_instance_context>>(all);
302  else
303  generic_driver_onethread<single_example_handler<single_instance_context>>(all);
304 }
305 
306 float recur_sensitivity(void*, base_learner& base, example& ec) { return base.sensitivity(ec); }
307 
308 } // namespace LEARNER
void finish_example(vw &all, E &ec)
Definition: learner.h:302
v_array< char > tag
Definition: example.h:63
void learn(example &)
Definition: global_data.cc:137
v_array< namespace_index > indices
void end_examples()
Definition: learner.h:289
bool ec_is_example_header(example const &ec)
Definition: cb.cc:170
std::vector< vw * > _all
Definition: learner.cc:134
custom_examples_queue(v_array< example *> examples)
Definition: learner.cc:235
multi_instance_context(const std::vector< vw *> &all)
Definition: learner.cc:122
example * get_example(parser *p)
Definition: parser.cc:909
label_type::label_type_t label_type
Definition: global_data.h:550
#define CASE(type)
Definition: learner.cc:8
void on_example(example *ec)
Definition: learner.cc:205
bool quiet
Definition: global_data.h:487
int example_is_newline(example const &ec)
Definition: example.h:104
float recur_sensitivity(void *, base_learner &base, example &ec)
Definition: learner.cc:306
T *& begin()
Definition: v_array.h:42
void parse_dispatch(vw &all, dispatch_fptr dispatch)
size_t size() const
Definition: v_array.h:68
void save_predictor(vw &all, std::string reg_name, size_t current_pass)
parser * p
Definition: global_data.h:377
single_learner * as_singleline(learner< T, E > *l)
Definition: learner.h:476
void process_examples(queue_type &examples, handler_type &handler)
Definition: learner.cc:245
bool is_save_cmd(example *ec)
Definition: learner.cc:84
void on_example(example *ec)
Definition: learner.cc:145
void save(example &ec, vw &all)
Definition: learner.cc:52
bool ec_is_example_header(example const &ec)
multi_example_handler(const context_type context)
Definition: learner.cc:195
void end_pass(example &ec, vw &all)
Definition: learner.cc:44
void generic_driver(const std::vector< vw *> &all)
Definition: learner.cc:277
vw_ostream trace_message
Definition: global_data.h:424
void learn_multi_ex(multi_ex &ec_seq, vw &all)
Definition: learner.cc:38
v_array< example * > _examples
Definition: learner.cc:240
uint64_t current_pass
Definition: global_data.h:396
bool is_multiline
Definition: learner.h:154
void finish_example(vw &, example &)
Definition: parser.cc:881
void generic_driver_onethread(vw &all)
Definition: learner.cc:285
float sensitivity(example &ec, size_t i=0)
Definition: learner.h:242
std::vector< example * > multi_ex
Definition: example.h:122
polylabel l
Definition: example.h:57
void end_pass()
Definition: learner.h:280
void learn_ex(example &ec, vw &all)
Definition: learner.cc:32
bool example_is_newline_not_header(example &ec, vw &all)
Definition: learner.cc:68
uint64_t end_parsed_examples
Definition: parser.h:82
bool complete_multi_ex(example *ec)
Definition: learner.cc:165
LEARNER::base_learner * l
Definition: global_data.h:383
single_example_handler(const context_type &context)
Definition: learner.cc:143
bool early_terminate
Definition: global_data.h:500
ready_examples_queue(vw &master)
Definition: learner.cc:224
std::string final_regressor_name
Definition: global_data.h:535
bool end_pass
Definition: example.h:77
bool try_complete_multi_ex(example *ec)
Definition: learner.cc:181
multi_learner * as_multiline(learner< T, E > *l)
Definition: learner.h:468
const char * to_string(prediction_type_t prediction_type)
Definition: learner.cc:12
void drain_examples(vw &all)
Definition: learner.cc:89