13#if !defined(ULTRA_SRC_EVALUATOR_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(ULTRA_SRC_EVALUATOR_TCC)
18#define ULTRA_SRC_EVALUATOR_TCC
25template<EvaluationDataset D>
26evaluator<D>::evaluator(D &d) noexcept : dat_(&d)
38template<EvaluationDataset D>
39const auto &evaluator<D>::data() const noexcept
41 if constexpr (is_multi_dataset_v<D>)
42 return dat_->selected();
57template<EvaluationDataset D>
58bool evaluator<D>::set_parallel_evaluation(
unsigned helpers,
59 std::size_t min_samples)
noexcept
62 min_samples_ = !min_samples ? default_min_samples_per_thread : min_samples;
71template<EvaluationDataset D>
72unsigned evaluator<D>::parallel_helpers() const noexcept
83template<EvaluationDataset D>
84std::size_t evaluator<D>::min_samples_per_thread() const noexcept
94template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
95requires ExampleEvaluator<F, D, P>
96aggregate_evaluator<P, F, D, A, M>::aggregate_evaluator(D &d) noexcept
111template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
112requires ExampleEvaluator<F, D, P>
113bool aggregate_evaluator<P, F, D, A, M>::set_parallel_evaluation(
114 unsigned n, std::size_t min_samples)
noexcept
115 requires parallel_safe_example_evaluator<F>
117 return evaluator<D>::set_parallel_evaluation(n, min_samples);
126template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
127requires ExampleEvaluator<F, D, P>
128double aggregate_evaluator<P, F, D, A, M>::operator()(
const P &prg)
const
130 return eval_impl(prg, 1);
149template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
150requires ExampleEvaluator<F, D, P>
151double aggregate_evaluator<P, F, D, A, M>::fast(
const P &prg)
const
153 const auto n(std::ranges::distance(this->data()));
154 return eval_impl(prg, n >= fast_min_examples ? fast_step : 1);
169template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
170requires ExampleEvaluator<F, D, P>
171auto aggregate_evaluator<P, F, D, A, M>::predictor(
const P &prg)
const
174 return reg_oracle<P>(prg);
196template<Indiv
idual P,
class F,
class D, aggregation_mode A, evaluation_mode M>
197requires ExampleEvaluator<F, D, P>
198double aggregate_evaluator<P, F, D, A, M>::eval_impl(
const P &prg,
199 std::ptrdiff_t step)
const
201 const auto &dat(this->data());
202 const auto examples(std::ranges::distance(dat));
203 Expects(0 < step && step <= examples);
205 const auto end(std::end(dat));
206 const auto sampled_count(
static_cast<std::size_t
>((examples - 1) / step + 1));
208 std::size_t workers(1);
209 if constexpr (std::ranges::forward_range<
decltype(dat)>
210 && parallel_safe_example_evaluator<F>)
211 if (this->parallel_helpers())
212 workers = std::clamp(sampled_count / this->min_samples_per_thread(),
213 1uz, this->parallel_helpers() + 1uz);
215 const auto stride(step *
static_cast<std::ptrdiff_t
>(workers));
220 std::size_t sampled {0};
221 std::size_t valid {0};
223 void merge(
const partial &part)
225 sampled += part.sampled;
230 mean += (part.mean - mean)
231 * (
static_cast<double>(part.valid)
232 /
static_cast<double>(valid + part.valid));
240 const auto evaluate_strip([&](std::size_t strip)
245 for (
auto it(std::ranges::next(std::begin(dat),
246 static_cast<std::ptrdiff_t
>(strip) * step, end));
248 std::ranges::advance(it, stride, end))
252 if (
const std::optional<double> value(f(*it)); value)
253 result.mean += (*value - result.mean)
254 /
static_cast<double>(++result.valid);
260 std::vector<std::future<partial>> futures;
261 futures.reserve(workers - 1);
263 for (std::size_t strip(1); strip < workers; ++strip)
264 futures.push_back(std::async(std::launch::async, evaluate_strip, strip));
266 partial total(evaluate_strip(0));
268 for (
auto &future : futures)
269 total.merge(future.get());
271 Ensures(0 < total.sampled
272 && total.sampled <=
static_cast<std::size_t
>(examples));
275 return std::numeric_limits<double>::lowest();
277 double acc(total.mean);
279 if (total.valid < total.sampled)
281 const auto missing_per_valid(
static_cast<double>(total.sampled - total.valid)
282 /
static_cast<double>(total.valid));
284 if constexpr (M == evaluation_mode::error)
285 acc += missing_per_valid * (acc + 1.0);
287 acc -= missing_per_valid * (std::fabs(acc) + 1.0);
290 if constexpr (A == aggregation_mode::sum)
291 acc *=
static_cast<double>(examples);
293 if constexpr (M == evaluation_mode::error)
304template<Indiv
idual P>
305mae_error_functor<P>::mae_error_functor(
const P &prg) : oracle_(prg)
314template<Indiv
idual P>
316mae_error_functor<P>::operator()(
const example &example)
const
318 if (
const auto foreseen(oracle_(example.input));
has_value(foreseen))
319 return std::fabs(lexical_cast<D_DOUBLE>(foreseen)
320 - label_as<D_DOUBLE>(example));
330template<Indiv
idual P>
331rmae_error_functor<P>::rmae_error_functor(
const P &prg) : oracle_(prg)
341template<Indiv
idual P>
343rmae_error_functor<P>::operator()(
const example &example)
const
345 if (
const auto foreseen(oracle_(example.input));
has_value(foreseen))
347 const auto approx(lexical_cast<D_DOUBLE>(foreseen));
348 const auto target(label_as<D_DOUBLE>(example));
350 const auto delta(std::fabs(target - approx));
358 return delta / (std::fabs(approx) + std::fabs(target));
375template<Indiv
idual P>
376mse_error_functor<P>::mse_error_functor(
const P &prg) : oracle_(prg)
386template<Indiv
idual P>
388mse_error_functor<P>::operator()(
const example &example)
const
390 if (
const auto foreseen(oracle_(example.input));
has_value(foreseen))
392 const double err(lexical_cast<D_DOUBLE>(foreseen)
393 - label_as<D_DOUBLE>(example));
405template<Indiv
idual P>
406count_error_functor<P>::count_error_functor(
const P &prg) : oracle_(prg)
416template<Indiv
idual P>
417double count_error_functor<P>::operator()(
const example &example)
const
419 const auto foreseen(oracle_(example.input));
424 if (!issmall(lexical_cast<D_DOUBLE>(foreseen) - label_as<D_DOUBLE>(example)))
435template<Indiv
idual P>
436gaussian_evaluator<P>::gaussian_evaluator(multi_dataset<dataframe> &d)
447template<Indiv
idual P>
448double gaussian_evaluator<P>::operator()(
const P &prg)
const
450 const auto &dat(this->data());
451 Expects(dat.classes() >= 2);
452 basic_gaussian_oracle<P, false> oracle(prg, dat);
455 for (
auto &example : dat)
456 if (
const auto res(oracle.tag(example.input)); res.label ==
label(example))
458 const auto scale(
static_cast<double>(dat.classes() - 1));
463 d += (res.sureness - 1.0) / scale;
483template<Indiv
idual P>
484auto gaussian_evaluator<P>::predictor(
const P &prg)
const
486 return gaussian_oracle<P>(prg, this->data());
494template<Indiv
idual P>
495binary_evaluator<P>::binary_evaluator(multi_dataset<dataframe> &d)
508template<Indiv
idual P>
509double binary_evaluator<P>::operator()(
const P &prg)
const
511 const auto &dat(this->data());
512 Expects(dat.classes() == 2);
513 basic_binary_oracle<P, false> oracle(prg, dat);
517 for (
auto &example : dat)
518 if (
const auto res(oracle.tag(example.input)); res.label !=
label(example))
519 err += 1.0 + res.sureness;
530template<Indiv
idual P>
531auto binary_evaluator<P>::predictor(
const P &prg)
const
533 return binary_oracle<P>(prg, this->data());
class_t label(const example &e)
Definition dataframe.cc:87
constexpr bool has_regression_predictor_v
Convenience variable template for has_regression_predictor.
Definition evaluator_internal.tcc:54
bool has_value(const value_t &v) noexcept
Definition value.cc:31