Vowpal Wabbit
conditional_contextual_bandit.cc
Go to the documentation of this file.
2 #include "reductions.h"
3 #include "example.h"
4 #include "global_data.h"
5 #include "vw.h"
6 #include "interactions.h"
7 #include "label_dictionary.h"
8 #include "cb_adf.h"
9 #include "cb_algs.h"
10 #include "constant.h"
11 #include "v_array_pool.h"
12 
13 #include <numeric>
14 #include <algorithm>
15 #include <unordered_set>
16 #include <bitset>
17 
18 using namespace LEARNER;
19 using namespace VW;
20 using namespace VW::config;
21 
22 template <typename T>
24 {
25  array.clear();
26  pool.return_object(array);
27 }
28 
29 struct ccb
30 {
31  vw* all;
33  std::vector<example*> actions, slots;
34  std::vector<uint32_t> origin_index;
36  std::vector<bool> exclude_list, include_list;
37  std::vector<std::string> generated_interactions;
38  std::vector<std::string>* original_interactions;
39  std::vector<CCB::label> stored_labels;
41 
43 
44  // All of these hashes are with a hasher seeded with the below namespace hash.
45  std::vector<uint64_t> slot_id_hashes;
47  std::string id_namespace_str;
48 
50 
53 };
54 
55 namespace CCB
56 {
57 static constexpr uint32_t SHARED_EX_INDEX = 0;
58 static constexpr uint32_t TOP_ACTION_INDEX = 0;
59 
60 void clear_all(ccb& data)
61 {
62  // data.include_list and data.exclude_list aren't cleared here but are assigned in the predict/learn function
63  data.shared = nullptr;
64  data.actions.clear();
65  data.slots.clear();
66  data.action_with_label = 0;
67  data.stored_labels.clear();
68 }
69 
70 // split the slots, the actions and the shared example from the multiline example
72 {
73  for (auto ex : examples)
74  {
75  switch (ex->l.conditional_contextual_bandit.type)
76  {
78  data.shared = ex;
79  break;
81  data.actions.push_back(ex);
82  break;
83  case example_type::slot:
84  data.slots.push_back(ex);
85  break;
86  default:
87  std::cout << "ccb_adf_explore: badly formatted example - invalid example type";
88  return false;
89  }
90 
91  // Stash the CCB labels before rewriting them.
92  data.stored_labels.push_back({ex->l.conditional_contextual_bandit.type, ex->l.conditional_contextual_bandit.outcome,
93  ex->l.conditional_contextual_bandit.explicit_included_actions, 0.});
94  }
95 
96  return true;
97 }
98 
99 template <bool is_learn>
100 bool sanity_checks(ccb& data)
101 {
102  if (data.slots.size() > data.actions.size())
103  {
104  std::cerr << "ccb_adf_explore: badly formatted example - number of actions " << data.actions.size()
105  << " must be greater than the number of slots " << data.slots.size();
106  return false;
107  }
108 
109  if (is_learn)
110  {
111  for (auto slot : data.slots)
112  {
113  if (slot->l.conditional_contextual_bandit.outcome != nullptr &&
114  slot->l.conditional_contextual_bandit.outcome->probabilities.size() == 0)
115  {
116  std::cerr << "ccb_adf_explore: badly formatted example - missing label probability";
117  return false;
118  }
119  }
120  }
121  return true;
122 }
123 
124 // create empty/default cb labels
126 {
127  data.shared->l.cb.costs = data.cb_label_pool.get_object();
128  data.shared->l.cb.costs.push_back(data.default_cb_label);
129  for (example* action : data.actions)
130  {
131  action->l.cb.costs = data.cb_label_pool.get_object();
132  }
133  data.shared->l.cb.weight = 1.0;
134 }
135 
136 // the polylabel (union) must be manually cleaned up
138 {
140 
141  for (example* action : data.actions)
142  {
143  return_v_array(action->l.cb.costs, data.cb_label_pool);
144  }
145 }
146 
148  uint32_t action_index_one_based, example* example, conditional_contextual_bandit_outcome* outcome, ccb& data)
149 {
150  // save the cb label
151  // Action is unused in cb
152  data.cb_label.action = action_index_one_based;
153  data.cb_label.probability = outcome->probabilities[0].score;
154  data.cb_label.cost = outcome->cost;
155 
156  example->l.cb.costs.push_back(data.cb_label);
157 }
158 
159 void save_action_scores(ccb& data, decision_scores_t& decision_scores)
160 {
161  auto& pred = data.shared->pred.a_s;
162  decision_scores.push_back(pred);
163 
164  // correct indices: we want index relative to the original ccb multi-example, with no actions filtered
165  for (auto& action_score : pred)
166  {
167  action_score.action = data.origin_index[action_score.action];
168  }
169 
170  // Exclude the chosen action from next slots.
171  auto original_index_of_chosen_action = pred[0].action;
172  data.exclude_list[original_index_of_chosen_action] = true;
173 }
174 
176 {
177  // Don't need to return to pool, as that will be done when the example is output.
178 
179  // This just needs to be cleared as it is reused.
180  data.actions[data.action_with_label]->l.cb.costs.clear();
181 }
182 
183 // true if there exists at least 1 action in the cb multi-example
184 bool has_action(multi_ex& cb_ex) { return !cb_ex.empty(); }
185 
186 // This function intentionally does not handle increasing the num_features of the example because
187 // the output_example function has special logic to ensure the number of feaures is correctly calculated.
188 // Copy anything in default namespace for slot to ccb_slot_namespace in shared
189 // Copy other slot namespaces to shared
191 {
192  for (auto index : slot->indices)
193  {
194  // constant namespace should be ignored, as it already exists and we don't want to double it up.
195  if (index == constant_namespace)
196  {
197  continue;
198  }
199  else if (index == default_namespace) // slot default namespace has a special namespace in shared
200  {
202  }
203  else
204  {
205  LabelDict::add_example_namespace(*shared, index, slot->feature_space[index]);
206  }
207  }
208 }
209 
210 template <bool audit>
211 void inject_slot_id(ccb& data, example* shared, size_t id)
212 {
213  // id is zero based, so the vector must be of size id + 1
214  if (id + 1 > data.slot_id_hashes.size())
215  {
216  data.slot_id_hashes.resize(id + 1, 0);
217  }
218 
219  uint64_t index;
220  if (data.slot_id_hashes[id] == 0)
221  {
222  auto current_index_str = "index" + std::to_string(id);
223  index = VW::hash_feature(*data.all, current_index_str, data.id_namespace_hash);
224 
225  // To maintain indicies consistent with what the parser does we must scale.
226  index *= static_cast<uint64_t>(data.all->wpp) << data.base_learner_stride_shift;
227  data.slot_id_hashes[id] = index;
228  }
229  else
230  {
231  index = data.slot_id_hashes[id];
232  }
233 
234  shared->feature_space[ccb_id_namespace].push_back(1., index);
236 
237  if (audit)
238  {
239  auto current_index_str = "index" + std::to_string(id);
240  shared->feature_space[ccb_id_namespace].space_names.push_back(
241  audit_strings_ptr(new audit_strings(data.id_namespace_str, current_index_str)));
242  }
243 }
244 
245 // Since the slot id is the only thing in this namespace, the popping the value off will work correctly.
246 template <bool audit>
248 {
249  shared->feature_space[ccb_id_namespace].indicies.pop();
250  shared->feature_space[ccb_id_namespace].values.pop();
251  shared->indices.pop();
252 
253  if (audit)
254  {
255  shared->feature_space[ccb_id_namespace].space_names.pop();
256  }
257 }
258 
260 {
261  for (auto index : slot->indices)
262  {
263  // constant namespace should be ignored, as it already exists and we don't want to double it up.
264  if (index == constant_namespace)
265  {
266  continue;
267  }
268 
269  else if (index == default_namespace) // slot default namespace has a special namespace in shared
270  {
272  }
273  else
274  {
275  LabelDict::del_example_namespace(*shared, index, slot->feature_space[index]);
276  }
277  }
278 }
279 
280 // Generates quadratics between each namespace and the slot id as well as appends slot id to every existing interaction.
282  example* shared, std::vector<example*> actions, std::vector<std::string>& generated_interactions)
283 {
284  std::bitset<INTERACTIONS::printable_ns_size> found_namespaces;
285 
286  const auto original_size = generated_interactions.size();
287  for (size_t i = 0; i < original_size; i++)
288  {
289  auto interaction_copy = generated_interactions[i];
290  interaction_copy.push_back((char)ccb_id_namespace);
291  generated_interactions.push_back(interaction_copy);
292  }
293 
294  for (const auto& action : actions)
295  {
296  for (const auto& action_index : action->indices)
297  {
298  if (INTERACTIONS::is_printable_namespace(action_index) &&
299  !found_namespaces[action_index - INTERACTIONS::printable_start])
300  {
301  found_namespaces[action_index - INTERACTIONS::printable_start] = true;
302  generated_interactions.push_back({(char)action_index, (char)ccb_id_namespace});
303  }
304  }
305  }
306 
307  for (const auto& shared_index : shared->indices)
308  {
309  if (INTERACTIONS::is_printable_namespace(shared_index) &&
310  !found_namespaces[shared_index - INTERACTIONS::printable_start])
311  {
312  found_namespaces[shared_index - INTERACTIONS::printable_start] = true;
313  generated_interactions.push_back({(char)shared_index, (char)ccb_id_namespace});
314  }
315  }
316 }
317 
318 // build a cb example from the ccb example
319 template <bool is_learn>
320 void build_cb_example(multi_ex& cb_ex, example* slot, ccb& data)
321 {
322  bool slot_has_label = slot->l.conditional_contextual_bandit.outcome != nullptr;
323 
324  // Merge the slot features with the shared example and set it in the cb multi-example
325  // TODO is it imporant for total_sum_feat_sq and num_features to be correct at this point?
326  inject_slot_features(data.shared, slot);
327  cb_ex.push_back(data.shared);
328 
329  // Retrieve the action index whitelist (if the list is empty, then all actions are white-listed)
330  auto& explicit_includes = slot->l.conditional_contextual_bandit.explicit_included_actions;
331  if (explicit_includes.size() != 0)
332  {
333  // First time seeing this, initialize the vector with falses so we can start setting each included action.
334  if (data.include_list.size() == 0)
335  {
336  data.include_list.assign(data.actions.size(), false);
337  }
338 
339  for (uint32_t included_action_id : explicit_includes)
340  {
341  data.include_list[included_action_id] = true;
342  }
343  }
344 
345  // set the available actions in the cb multi-example
346  uint32_t index = 0;
347  data.origin_index.clear();
348  data.origin_index.resize(data.actions.size(), 0);
349  for (size_t i = 0; i < data.actions.size(); i++)
350  {
351  // Filter actions that are not explicitly included. If the list is empty though, everything is included.
352  if (!data.include_list.empty() && !data.include_list[i])
353  continue;
354 
355  // Filter actions chosen by previous slots
356  if (data.exclude_list[i])
357  continue;
358 
359  // Select the action
360  cb_ex.push_back(data.actions[i]);
361 
362  // Save the original index from the root multi-example
363  data.origin_index[index++] = (uint32_t)i;
364 
365  // Remember the index of the chosen action
366  if (is_learn && slot_has_label && i == slot->l.conditional_contextual_bandit.outcome->probabilities[0].action)
367  {
368  // This is used to remove the label later.
369  data.action_with_label = (uint32_t)i;
371  }
372  }
373 
374  // Must provide a prediction that cb can write into, this will be saved into the decision scores object later.
375  data.shared->pred.a_s = data.action_score_pool.get_object();
376 
377  // Tag can be used for specifying the sampling seed per slot. For it to be used it must be inserted into the shared
378  // example.
379  std::swap(data.shared->tag, slot->tag);
380 }
381 
382 // iterate over slots contained in the multi-example, and for each slot, build a cb example and perform a
383 // cb_explore_adf call.
384 template <bool is_learn>
385 void learn_or_predict(ccb& data, multi_learner& base, multi_ex& examples)
386 {
387  clear_all(data);
388  if (!split_multi_example_and_stash_labels(examples, data)) // split shared, actions and slots
389  return;
390 
391 #ifndef NDEBUG
392  if (!sanity_checks<is_learn>(data))
393  return;
394 #endif
395 
396  // This will overwrite the labels with CB.
397  create_cb_labels(data);
398 
399  // Reset exclusion list for this example.
400  data.exclude_list.assign(data.actions.size(), false);
401 
402  auto decision_scores = examples[0]->pred.decision_scores;
403 
404  // for each slot, re-build the cb example and call cb_explore_adf
405  size_t slot_id = 0;
406  for (example* slot : data.slots)
407  {
408  // Namespace crossing for slot features.
409  data.generated_interactions.clear();
410  std::copy(data.original_interactions->begin(), data.original_interactions->end(),
411  std::back_inserter(data.generated_interactions));
414  for (auto ex : data.actions)
415  {
416  ex->interactions = &data.generated_interactions;
417  }
418 
419  data.include_list.clear();
420  build_cb_example<is_learn>(data.cb_ex, slot, data);
421 
422  if (data.all->audit)
423  inject_slot_id<true>(data, data.shared, slot_id);
424  else
425  inject_slot_id<false>(data, data.shared, slot_id);
426 
427  if (has_action(data.cb_ex))
428  {
429  // the cb example contains at least 1 action
430  multiline_learn_or_predict<is_learn>(base, data.cb_ex, examples[0]->ft_offset);
431  save_action_scores(data, decision_scores);
432  clear_pred_and_label(data);
433  }
434  else
435  {
436  // the cb example contains no action => cannot decide
437  decision_scores.push_back(data.action_score_pool.get_object());
438  }
439 
440  data.shared->interactions = data.original_interactions;
441  for (auto ex : data.actions)
442  {
443  ex->interactions = data.original_interactions;
444  }
445  remove_slot_features(data.shared, slot);
446 
447  if (data.all->audit)
448  remove_slot_id<true>(data.shared);
449  else
450  remove_slot_id<false>(data.shared);
451 
452  // Put back the original shared example tag.
453  std::swap(data.shared->tag, slot->tag);
454  slot_id++;
455  data.cb_ex.clear();
456  }
457 
458  delete_cb_labels(data);
459 
460  // Restore ccb labels to the example objects.
461  for (size_t i = 0; i < examples.size(); i++)
462  {
463  examples[i]->l.conditional_contextual_bandit = {
464  data.stored_labels[i].type, data.stored_labels[i].outcome, data.stored_labels[i].explicit_included_actions, 0.};
465  }
466 
467  // Save the predictions
468  examples[0]->pred.decision_scores = decision_scores;
469 }
470 
471 void print_decision_scores(int f, decision_scores_t& decision_scores)
472 {
473  if (f >= 0)
474  {
475  std::stringstream ss;
476  for (auto slot : decision_scores)
477  {
478  std::string delimiter = "";
479  for (auto action_score : slot)
480  {
481  ss << delimiter << action_score.action << ':' << action_score.score;
482  delimiter = ",";
483  }
484  ss << '\n';
485  }
486  ssize_t len = ss.str().size();
487  ssize_t t = io_buf::write_file_or_socket(f, ss.str().c_str(), (unsigned int)len);
488  if (t != len)
489  std::cerr << "write error: " << strerror(errno) << std::endl;
490  }
491 }
492 
493 void print_update(vw& all, std::vector<example*>& slots, decision_scores_t& decision_scores, size_t num_features)
494 {
495  if (all.sd->weighted_examples() >= all.sd->dump_interval && !all.quiet && !all.bfgs)
496  {
497  std::string label_str = "";
498  std::string delim = "";
499  int counter = 0;
500  for (auto slot : slots)
501  {
502  counter++;
503 
504  auto outcome = slot->l.conditional_contextual_bandit.outcome;
505  if (outcome == nullptr)
506  {
507  label_str += delim;
508  label_str += "?";
509  }
510  else
511  {
512  label_str += delim;
513  label_str += std::to_string(outcome->probabilities[0].action);
514  label_str += ":";
515  label_str += std::to_string(outcome->cost);
516  }
517 
518  delim = ",";
519 
520  // Stop after 2...
521  if (counter > 1 && slots.size() > 2)
522  {
523  label_str += delim;
524  label_str += "...";
525  break;
526  }
527  }
528  std::ostringstream label_buf;
529  label_buf << std::setw(all.sd->col_current_label) << std::right << std::setfill(' ') << label_str;
530 
531  std::string pred_str = "";
532  delim = "";
533  counter = 0;
534  for (auto slot : decision_scores)
535  {
536  counter++;
537  pred_str += delim;
538  pred_str += std::to_string(slot[0].action);
539  delim = ",";
540 
541  // Stop after 3...
542  if (counter > 2)
543  {
544  pred_str += delim;
545  pred_str += "...";
546  break;
547  }
548  }
549  std::ostringstream pred_buf;
550  pred_buf << std::setw(all.sd->col_current_predict) << std::right << std::setfill(' ') << pred_str;
551 
552  all.sd->print_update(all.holdout_set_off, all.current_pass, label_buf.str(), pred_buf.str(), num_features,
553  all.progress_add, all.progress_arg);
554  }
555 }
556 
557 void output_example(vw& all, ccb& /*c*/, multi_ex& ec_seq)
558 {
559  if (ec_seq.size() <= 0)
560  return;
561 
562  std::vector<example*> slots;
563  size_t num_features = 0;
564  float loss = 0.;
565 
566  // Should this be done for shared, action and slot?
567  for (auto ec : ec_seq)
568  {
569  num_features += ec->num_features;
570 
571  if (ec->l.conditional_contextual_bandit.type == CCB::example_type::slot)
572  {
573  slots.push_back(ec);
574  }
575  }
576 
577  // Is it hold out?
578  size_t num_labelled = 0;
579  auto preds = ec_seq[0]->pred.decision_scores;
580  for (size_t i = 0; i < slots.size(); i++)
581  {
582  auto outcome = slots[i]->l.conditional_contextual_bandit.outcome;
583  if (outcome != nullptr)
584  {
585  num_labelled++;
586  float l = CB_ALGS::get_cost_estimate(
587  outcome->probabilities[TOP_ACTION_INDEX], outcome->cost, preds[i][TOP_ACTION_INDEX].action);
588  loss += l * preds[i][TOP_ACTION_INDEX].score;
589  }
590  }
591 
592  if (num_labelled > 0 && num_labelled < slots.size())
593  {
594  std::cerr << "Warning: Unlabeled example in train set, was this intentional?\n";
595  }
596 
597  bool holdout_example = num_labelled > 0;
598  for (size_t i = 0; i < ec_seq.size(); i++) holdout_example &= ec_seq[i]->test_only;
599 
600  // TODO what does weight mean here?
601  all.sd->update(holdout_example, num_labelled > 0, loss, ec_seq[SHARED_EX_INDEX]->weight, num_features);
602 
603  for (auto sink : all.final_prediction_sink)
604  print_decision_scores(sink, ec_seq[SHARED_EX_INDEX]->pred.decision_scores);
605 
606  CCB::print_update(all, slots, preds, num_features);
607 }
608 
609 void finish_multiline_example(vw& all, ccb& data, multi_ex& ec_seq)
610 {
611  if (ec_seq.size() > 0)
612  {
613  output_example(all, data, ec_seq);
615  }
616 
617  for (auto& a_s : ec_seq[0]->pred.decision_scores)
618  {
620  }
621  ec_seq[0]->pred.decision_scores.clear();
622 
623  VW::finish_example(all, ec_seq);
624 }
625 
627 {
628  auto data = scoped_calloc_or_throw<ccb>();
629  bool ccb_explore_adf_option = false;
630  bool slate = false;
631  option_group_definition new_options(
632  "EXPERIMENTAL: Conditional Contextual Bandit Exploration with Action Dependent Features");
633  new_options.add(
634  make_option("ccb_explore_adf", ccb_explore_adf_option)
635  .keep()
636  .help("EXPERIMENTAL: Do Conditional Contextual Bandit learning with multiline action dependent features."));
637  new_options.add(make_option("slate", slate).keep().help("EXPERIMENTAL - MAY CHANGE: Enable slate mode in CCB."));
638  options.add_and_parse(new_options);
639 
640  if (!ccb_explore_adf_option)
641  return nullptr;
642 
643  if (!options.was_supplied("cb_explore_adf"))
644  {
645  options.insert("cb_explore_adf", "");
646  options.add_and_parse(new_options);
647  }
648 
649  if (options.was_supplied("cb_sample") && slate)
650  {
651  THROW("--slate and --cb_sample cannot be supplied together");
652  }
653 
654  if (!options.was_supplied("cb_sample") && !slate)
655  {
656  options.insert("cb_sample", "");
657  options.add_and_parse(new_options);
658  }
659 
660  auto base = as_multiline(setup_base(options, all));
661  all.p->lp = CCB::ccb_label_parser;
663 
664  // Stash the base learners stride_shift so we can properly add a feature later.
665  data->base_learner_stride_shift = all.weights.stride_shift();
666 
667  // Extract from lower level reductions
668  data->default_cb_label = {FLT_MAX, 0, -1.f, 0.f};
669  data->shared = nullptr;
670  data->original_interactions = &all.interactions;
671  data->all = &all;
672 
673  data->id_namespace_str.push_back((char)ccb_id_namespace);
674  data->id_namespace_str.append("_id");
675  data->id_namespace_hash = VW::hash_space(all, data->id_namespace_str);
676 
678  init_learner(data, base, learn_or_predict<true>, learn_or_predict<false>, 1, prediction_type::decision_probs);
679 
681 
683  return make_base(l);
684 }
685 
687 } // namespace CCB
void remove_slot_id(example *shared)
VW::v_array_pool< CB::cb_class > cb_label_pool
void return_v_array(v_array< T > &array, VW::v_array_pool< T > &pool)
CB::cb_class cb_label
v_array< char > tag
Definition: example.h:63
v_array< namespace_index > indices
ACTION_SCORE::action_scores a_s
Definition: example.h:47
parameters weights
Definition: global_data.h:537
void attach_label_to_example(uint32_t action_index_one_based, example *example, conditional_contextual_bandit_outcome *outcome, ccb &data)
void(* delete_prediction)(void *)
Definition: global_data.h:485
T pop()
Definition: v_array.h:58
CB::cb_class default_cb_label
float weight
Definition: cb.h:28
void clear_all(ccb &data)
constexpr unsigned char default_namespace
Definition: constant.h:19
static ssize_t write_file_or_socket(int f, const void *buf, size_t nbytes)
Definition: io_buf.cc:140
std::shared_ptr< audit_strings > audit_strings_ptr
Definition: feature_group.h:23
static constexpr int col_current_label
Definition: global_data.h:182
void finish_multiline_example(vw &all, cbify &, multi_ex &ec_seq)
Definition: cbify.cc:373
CB::label cb
Definition: example.h:31
VW::v_array_pool< ACTION_SCORE::action_score > action_score_pool
std::vector< std::string > * interactions
void print_decision_scores(int f, decision_scores_t &decision_scores)
label_type::label_type_t label_type
Definition: global_data.h:550
void del_example_namespace(example &ec, namespace_index ns, features &fs)
v_array< int > final_prediction_sink
Definition: global_data.h:518
constexpr unsigned char ccb_slot_namespace
Definition: constant.h:33
v_array< cb_class > costs
Definition: cb.h:27
std::vector< CCB::label > stored_labels
base_learner * make_base(learner< T, E > &base)
Definition: learner.h:462
std::vector< example * > actions
uint32_t action
Definition: search.h:19
bool quiet
Definition: global_data.h:487
virtual void add_and_parse(const option_group_definition &group)=0
std::vector< bool > exclude_list
float loss(cbify &data, uint32_t label, uint32_t final_prediction)
Definition: cbify.cc:60
constexpr bool is_printable_namespace(const unsigned char ns)
Definition: interactions.h:22
float get_cost_estimate(CB::cb_class *observation, uint32_t action, float offset=0.)
Definition: cb_algs.h:58
bool holdout_set_off
Definition: global_data.h:499
label_parser ccb_label_parser
Definition: ccb_label.cc:358
void print_update(vw &all, std::vector< example *> &slots, decision_scores_t &decision_scores, size_t num_features)
void learn_or_predict(cb_sample_data &data, multi_learner &base, multi_ex &examples)
Definition: cb_sample.cc:92
void return_object(T obj)
Definition: object_pool.h:141
bool progress_add
Definition: global_data.h:545
bool sanity_checks(ccb &data)
ACTION_SCORE::action_scores probabilities
Definition: ccb_label.h:19
std::vector< example * > slots
parser * p
Definition: global_data.h:377
std::array< features, NUM_NAMESPACES > feature_space
std::vector< uint32_t > origin_index
static constexpr uint32_t TOP_ACTION_INDEX
void set_finish_example(void(*f)(vw &all, T &, E &))
Definition: learner.h:307
uint32_t action
Definition: cb.h:18
learner< T, E > & init_learner(free_ptr< T > &dat, L *base, void(*learn)(T &, L &, E &), void(*predict)(T &, L &, E &), size_t ws, prediction_type::prediction_type_t pred_type)
Definition: learner.h:369
void delete_action_scores(void *v)
Definition: action_score.cc:29
bool ec_is_example_header(example const &ec)
void push_back(const T &new_ele)
Definition: v_array.h:107
shared_data * sd
Definition: global_data.h:375
bool split_multi_example_and_stash_labels(const multi_ex &examples, ccb &data)
float probability
Definition: cb.h:19
float id(float in)
Definition: scorer.cc:51
float progress_arg
Definition: global_data.h:546
void delete_cb_labels(ccb &data)
void clear()
Definition: v_array.h:88
void print_update(bool holdout_set_off, size_t current_pass, float label, float prediction, size_t num_features, bool progress_add, float progress_arg)
Definition: global_data.h:225
bool has_action(multi_ex &cb_ex)
bool bfgs
Definition: global_data.h:412
virtual bool was_supplied(const std::string &key)=0
void global_print_newline(const v_array< int > &final_prediction_sink)
Definition: cb_adf.cc:342
void build_cb_example(multi_ex &cb_ex, example *slot, ccb &data)
constexpr unsigned char printable_start
Definition: interactions.h:16
void clear_pred_and_label(ccb &data)
uint64_t current_pass
Definition: global_data.h:396
void finish_example(vw &, example &)
Definition: parser.cc:881
uint32_t wpp
Definition: global_data.h:432
virtual void insert(const std::string &key, const std::string &value)=0
void create_cb_labels(ccb &data)
void update(bool test_example, bool labeled_example, float loss, float weight, size_t num_features)
Definition: global_data.h:190
static constexpr uint32_t SHARED_EX_INDEX
Definition: ccb_label.cc:22
float weight
option_group_definition & add(T &&op)
Definition: options.h:90
example_type type
Definition: ccb_label.h:32
std::vector< example * > multi_ex
Definition: example.h:122
uint64_t id_namespace_hash
label_parser cb_label
Definition: cb.cc:167
polylabel l
Definition: example.h:57
size_t base_learner_stride_shift
base_learner * ccb_explore_adf_setup(options_i &options, vw &all)
typed_option< T > make_option(std::string name, T &location)
Definition: options.h:80
float cost
Definition: cb.h:17
v_array< uint32_t > explicit_included_actions
Definition: ccb_label.h:35
Definition: autolink.cc:11
void add_example_namespace(example &ec, namespace_index ns, features &fs)
void save_action_scores(ccb &data, decision_scores_t &decision_scores)
CCB::label conditional_contextual_bandit
Definition: example.h:32
std::vector< std::string > interactions
Definition: global_data.h:457
void inject_slot_features(example *shared, example *slot)
std::vector< bool > include_list
uint64_t hash_feature(vw &all, const std::string &s, uint64_t u)
Definition: vw.h:153
uint64_t hash_space(vw &all, const std::string &s)
Definition: vw.h:138
uint32_t stride_shift()
void inject_slot_id(ccb &data, example *shared, size_t id)
bool audit
Definition: global_data.h:486
LEARNER::base_learner * setup_base(options_i &options, vw &all)
Definition: parse_args.cc:1222
void output_example(vw &all, ccb &, multi_ex &ec_seq)
polyprediction pred
Definition: example.h:60
static constexpr int col_current_predict
Definition: global_data.h:184
std::vector< uint64_t > slot_id_hashes
constexpr unsigned char constant_namespace
Definition: constant.h:22
std::vector< std::string > * original_interactions
std::string id_namespace_str
double weighted_examples()
Definition: global_data.h:188
float dump_interval
Definition: global_data.h:147
#define THROW(args)
Definition: vw_exception.h:181
void remove_slot_features(example *shared, example *slot)
float f
Definition: cache.cc:40
conditional_contextual_bandit_outcome * outcome
Definition: ccb_label.h:34
std::vector< std::string > generated_interactions
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
constexpr unsigned char ccb_id_namespace
Definition: constant.h:34
label_parser lp
Definition: parser.h:102
void calculate_and_insert_interactions(example *shared, std::vector< example *> actions, std::vector< std::string > &generated_interactions)
std::pair< std::string, std::string > audit_strings
Definition: feature_group.h:22