<commit_before>#pragma once

#include "data/batch_generator.h"
#include "data/corpus.h"
#include "training/config.h"
#include "training/validator.h"

namespace marian {

class Reporter {
  public:
    Ptr<Config> options_;
    std::vector<Ptr<Validator>> validators_;

    float costSum{0};
    size_t epochs{1};

    size_t samples{0};
    size_t wordsDisp{0};
    size_t batches{0};

    boost::timer::cpu_timer timer;

  public:
    Reporter(Ptr<Config> options) : options_(options) {}

    bool keepGoing() {
      // stop if it reached the maximum number of epochs
      if(options_->get<size_t>("after-epochs") > 0
         && epochs > options_->get<size_t>("after-epochs"))
        return false;

      // stop if it reached the maximum number of batch updates
      if(options_->get<size_t>("after-batches") > 0
         && batches >= options_->get<size_t>("after-batches"))
        return false;

      // stop if the first validator did not improve for a given number of checks
      if(options_->get<size_t>("early-stopping") > 0
         && !validators_.empty()
         && validators_[0]->stalled() >= options_->get<size_t>("early-stopping"))
        return false;

      return true;
    }

    void increaseEpoch() {
      LOG(info, "Seen {} samples", samples);

      epochs++;
      samples = 0;

      LOG(info, "Starting epoch {}", epochs);
    }

    void finished() {
      LOG(info, "Training finshed");
    }

    void addValidator(Ptr<Validator> validator) {
      validators_.push_back(validator);
    }

    void validate(Ptr<ExpressionGraph> graph) {
      if(batches % options_->get<size_t>("valid-freq") == 0) {
        for(auto validator : validators_) {
          if(validator) {
            size_t stalledPrev = validator->stalled();
            float value = validator->validate(graph);
            std::stringstream ss;
            ss << batches << " : ";
            ss << validator->type() << " : " << value;
            if(validator->stalled() > 0)
              ss << " : stalled " << validator->stalled() << " times";
            else
              ss << " : new best";
            LOG(valid, ss.str());
          }
        }
      }
    }

    size_t stalled() {
      for(auto validator : validators_)
        if(validator)
          return validator->stalled();
      return 0;
    }

    void update(float cost, Ptr<data::CorpusBatch> batch) {
      costSum += cost;
      samples += batch->size();
      wordsDisp += batch->words();
      batches++;

      if(batches % options_->get<size_t>("disp-freq") == 0) {
        std::stringstream ss;
        ss << "Ep. " << epochs
           << " : Up. " << batches
           << " : Sen. " << samples
           << " : Cost " << std::fixed << std::setprecision(2)
                         << costSum / options_->get<size_t>("disp-freq")
           << " : Time " << timer.format(2, "%ws");

        float seconds = std::stof(timer.format(5, "%w"));
        float wps = wordsDisp /   (float)seconds;

        ss << " : " << std::fixed << std::setprecision(2)
           << wps << " words/s";

        LOG(info, ss.str());

        timer.start();
        costSum = 0;
        wordsDisp = 0;
      }
    }
};

template <class Model>
void Train(Ptr<Config> options) {
  using namespace data;
  using namespace keywords;<commit_msg>Take advantage of formatting options provided by spdlog.<commit_after>#pragma once

#include "data/batch_generator.h"
#include "data/corpus.h"
#include "training/config.h"
#include "training/validator.h"

namespace marian {

class Reporter {
  public:
    Ptr<Config> options_;
    std::vector<Ptr<Validator>> validators_;

    float costSum{0};
    size_t epochs{1};

    size_t samples{0};
    size_t wordsDisp{0};
    size_t batches{0};

    boost::timer::cpu_timer timer;

  public:
    Reporter(Ptr<Config> options) : options_(options) {}

    bool keepGoing() {
      // stop if it reached the maximum number of epochs
      if(options_->get<size_t>("after-epochs") > 0
         && epochs > options_->get<size_t>("after-epochs"))
        return false;

      // stop if it reached the maximum number of batch updates
      if(options_->get<size_t>("after-batches") > 0
         && batches >= options_->get<size_t>("after-batches"))
        return false;

      // stop if the first validator did not improve for a given number of checks
      if(options_->get<size_t>("early-stopping") > 0
         && !validators_.empty()
         && validators_[0]->stalled() >= options_->get<size_t>("early-stopping"))
        return false;

      return true;
    }

    void increaseEpoch() {
      LOG(info, "Seen {} samples", samples);

      epochs++;
      samples = 0;

      LOG(info, "Starting epoch {}", epochs);
    }

    void finished() {
      LOG(info, "Training finshed");
    }

    void addValidator(Ptr<Validator> validator) {
      validators_.push_back(validator);
    }

    void validate(Ptr<ExpressionGraph> graph) {
      if(batches % options_->get<size_t>("valid-freq") == 0) {
        for(auto validator : validators_) {
          if(validator) {
            size_t stalledPrev = validator->stalled();
            float value = validator->validate(graph);
            if(validator->stalled() > 0)
	      LOG(valid, "{} : {} : {} : stalled {} times", batches,
		  validator->type(), value, validator->stalled());
            else
	      LOG(valid, "{} : {} : {} : new best", batches,
		  validator->type(), value);
          }
        }
      }
    }

    size_t stalled() {
      for(auto validator : validators_)
        if(validator)
          return validator->stalled();
      return 0;
    }

    void update(float cost, Ptr<data::CorpusBatch> batch) {
      costSum += cost;
      samples += batch->size();
      wordsDisp += batch->words();
      batches++;

      if(batches % options_->get<size_t>("disp-freq") == 0) {
	LOG("Ep. {} : Up. {} : Sen. : Cost {.2f} : Time {} : {.2f} words/s",
	    epochs, batches, samples, costSum / options_->get<size_t>("disp-freq"),
	    timer.format(2), wordsDisp / std::stof(timer.format(5, "%w")));
	timer.start();
        costSum = 0;
        wordsDisp = 0;
      }
    }
};

template <class Model>
void Train(Ptr<Config> options) {
  using namespace data;
  using namespace keywords;
{'fraction_non_alphanumeric': 0.154079514609612, 'fraction_numerical': 0.006386715631486508, 'mean_word_length': 2.356913183279743, 'pattern_counts': {'":': 0, '<': 91, '<?xml version=': 0, '>': 90, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3708157', 'n_tokens_mistral': 1997, 'n_tokens_neox': 1923, 'n_words': 432}