class_docstr: Base class for Contextual Bandit Offline Evaluation algorithms. All algorihtms support evaluation of non-stationary
      policies, as required for exploration-exploitation.
class_docstr_tok: ["Base","class","for","Contextual","Bandit","Offline","Evaluation","algorithms",".","All","algorihtms","support","evaluation","of","non-stationary","policies",",","as","required","for","exploration-exploitation","."]
docstr: Initialize the evaluator. The evaluated model is passed in as an input and copied to freeze its state.
  The state of the model remains frozen until method update_eval_model() is called.
docstr_tok: ["Initialize","the","evaluator",".","The","evaluated","model","is","passed","in","as","an","input","and","copied","to","freeze","its","state",".","The","state","of","the","model","remains","frozen","until","method","update_eval_model","(",")","is","called","."]
code: def __init__(
      self,
      eval_model: torch.nn.Module,
      logger: Optional[LightningLoggerBase] = None,
      max_importance_weight: Optional[float] = None,
  ):
      """
      Initialize the evaluator. The evaluated model is passed in as an input and copied to freeze its state.
      The state of the model remains frozen until method update_eval_model() is called.
      """
      super().__init__()
      self.eval_model = copy.deepcopy(eval_model)
      self.logger = logger
      self.max_importance_weight = max_importance_weight
  
      # below we register the buffers used to maintain the state of Offline Eval
      # Buffers ending in "_local" track per-instance values. Buffers without "_local" track global values aggregated across all instances.
      # At each step we update only the local buffers. The global values are updated periodically and local values are reset to zero at that time.
      # "accepted" means the same as "used"
  
      # total weight for accepted observations
      self.register_buffer(
          "sum_weight_accepted", torch.zeros(1, dtype=torch.float)
      )
      self.register_buffer(
          "sum_weight_accepted_local", torch.zeros(1, dtype=torch.float)
      )
  
      # total importance weight for accepted observations
      self.register_buffer(
          "sum_importance_weight_accepted",
          torch.zeros(1, dtype=torch.float),
      )
      self.register_buffer(
          "sum_importance_weight_accepted_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # total weight for all observaions (accepted + rejected)
      self.register_buffer(
          "sum_weight_all_data", torch.zeros(1, dtype=torch.float)
      )
      self.register_buffer(
          "sum_weight_all_data_local", torch.zeros(1, dtype=torch.float)
      )
  
      # total weight processed since last model update and local buffer aggregation
      self.register_buffer(
          "sum_weight_since_update_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # number of times the evaluated model was updated, local metrics aggregated and global metrics logged
      self.register_buffer(
          "num_eval_model_updates", torch.zeros(1, dtype=torch.int)
      )
  
      # sum of reward*weight for accepted observations
      self.register_buffer(
          "sum_reward_weighted_accepted",
          torch.zeros(1, dtype=torch.float),
      )
      self.register_buffer(
          "sum_reward_weighted_accepted_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # sum of reward*weight*importance_weight for accepted observations
      self.register_buffer(
          "sum_reward_importance_weighted_accepted",
          torch.zeros(1, dtype=torch.float),
      )
      self.register_buffer(
          "sum_reward_importance_weighted_accepted_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # sum of reward*weight for all observations
      self.register_buffer(
          "sum_reward_weighted_all_data_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # sum of slate_size*weight for accepted observations
      self.register_buffer(
          "sum_size_weighted_accepted_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # sum of slate_size*weight for all observations
      self.register_buffer(
          "sum_size_weighted_all_data_local",
          torch.zeros(1, dtype=torch.float),
      )
  
      # fraction of data points which were accepted
      self.register_buffer(
          "frac_accepted", torch.zeros(1, dtype=torch.float)
      )
  
      # average reward for accepted observations
      self.register_buffer(
          "avg_reward_accepted", torch.zeros(1, dtype=torch.float)
      )
  
      # average reward for rejected observations
      self.register_buffer(
          "avg_reward_rejected", torch.zeros(1, dtype=torch.float)
      )
  
      # average slate size for accepted observations
      self.register_buffer(
          "avg_size_accepted", torch.zeros(1, dtype=torch.float)
      )
  
      # average slate size for rejected observations
      self.register_buffer(
          "avg_size_rejected", torch.zeros(1, dtype=torch.float)
      )
  
      # ratio of accepted and rejected average rewards
      self.register_buffer(
          "accepted_rejected_reward_ratio",
          torch.zeros(1, dtype=torch.float),
      )
  
      # average reward of all data (accepted and rejected)
      self.register_buffer(
          "avg_reward_all_data", torch.zeros(1, dtype=torch.float)
      )
  
imports: import copy
  import logging
  from abc import ABC, abstractmethod
  from typing import Optional
  import torch
  from pytorch_lightning.loggers import LightningLoggerBase
  from reagent.core.types import CBInput
  from reagent.core.utils import get_rank
  from reagent.evaluation.cb.utils import add_importance_weights
label_desc: Use image node_id 1 to create a new BaseOfflineEval object from inherited base classes: torch.nn, ABC with example: obj = BaseOfflineEval(eval_model, logger, max_importance_weight)