class_docstr: Stop training when a monitored metric has stopped improving.
  
  The earlystopping callback will be triggered each time validation ends.
  It will examine the metrics produced in validation,
  and get the metric with name ``monitor` (``monitor`` is ``reward`` by default),
  to check whether it's no longer increasing / decreasing.
  It takes ``min_delta`` and ``patience`` if applicable.
  If it's found to be not increasing / decreasing any more.
  ``trainer.should_stop`` will be set to true,
  and the training terminates.
  
  Implementation reference: https://github.com/keras-team/keras/blob/v2.9.0/keras/callbacks.py#L1744-L1893
class_docstr_tok: ["Stop","training","when","a","monitored","metric","has","stopped","improving",".","The","earlystopping","callback","will","be","triggered","each","time","validation","ends",".","It","will","examine","the","metrics","produced","in","validation",",","and","get","the","metric","with","name","``","monitor","`","(","``","monitor","``","is","``","reward","``","by","default",")",",","to","check","whether","it","'s","no","longer","increasing","\/","decreasing",".","It","takes","``","min_delta","``","and","``","patience","``","if","applicable",".","If","it","'s","found","to","be","not","increasing","\/","decreasing","any","more",".","``","trainer.should_stop","``","will","be","set","to","true",",","and","the","training","terminates",".","Implementation","reference",":","https",":","\/\/github.com\/keras-team\/keras\/blob\/v2.9.0\/keras\/callbacks.py","#","L1744-L1893"]
code: def on_validate_end(
      self, trainer: Trainer, vessel: TrainingVesselBase
  ) -> None:
      current = self.get_monitor_value(trainer)
      if current is None:
          return
      if self.restore_best_weights and self.best_weights is None:
          # Restore the weights after first iteration if no progress is ever made.
          self.best_weights = copy.deepcopy(vessel.state_dict())
  
      self.wait += 1
      if self._is_improvement(current, self.best):
          self.best = current
          self.best_iter = trainer.current_iter
          if self.restore_best_weights:
              self.best_weights = copy.deepcopy(vessel.state_dict())
          # Only restart wait if we beat both the baseline and our previous best.
          if self.baseline is None or self._is_improvement(
              current, self.baseline
          ):
              self.wait = 0
  
      msg = f"#{trainer.current_iter} current reward: {current:.4f}, best reward: {self.best:.4f} in #{self.best_iter}"
      _logger.info(msg)
  
      # Only check after the first epoch.
      if self.wait >= self.patience and trainer.current_iter > 0:
          trainer.should_stop = True
          _logger.info(
              f"On iteration %d: early stopping",
              trainer.current_iter + 1,
          )
          if (
              self.restore_best_weights
              and self.best_weights is not None
          ):
              _logger.info(
                  "Restoring model weights from the end of the best iteration: %d",
                  self.best_iter + 1,
              )
              vessel.load_state_dict(self.best_weights)
  
imports: from __future__ import annotations
  import copy
  import os
  import shutil
  import time
  from datetime import datetime
  from pathlib import Path
  from typing import Any, List, TYPE_CHECKING
  import numpy
  import pandas
  import torch
  from qlib.log import get_module_logger
  from qlib.typehint import Literal
label_desc: Use image node_id 5 for calling the EarlyStopping obj's underlying member method code with example usage: obj.on_validate_end(trainer, vessel) without return types