class_docstr: Manages all the learning details needed when training an PPO.
  
  These include:
    * Using distribution strategies correctly
    * Summaries
    * Checkpoints
    * Minimizing entering/exiting TF context:
        Especially in the case of TPUs scheduling a single TPU program to
        perform multiple train steps is critical for performance.
    * Generalizes the train call to be done correctly across CPU, GPU, or TPU
      executions managed by DistributionStrategies. This uses `strategy.run` and
      then makes sure to do a reduce operation over the `LossInfo` returned by
      the agent.
class_docstr_tok: ["Manages","all","the","learning","details","needed","when","training","an","PPO",".","These","include",":","*","Using","distribution","strategies","correctly","*","Summaries","*","Checkpoints","*","Minimizing","entering\/exiting","TF","context",":","Especially","in","the","case","of","TPUs","scheduling","a","single","TPU","program","to","perform","multiple","train","steps","is","critical","for","performance",".","*","Generalizes","the","train","call","to","be","done","correctly","across","CPU",",","GPU",",","or","TPU","executions","managed","by","DistributionStrategies",".","This","uses","`","strategy.run","`","and","then","makes","sure","to","do","a","reduce","operation","over","the","`","LossInfo","`","returned","by","the","agent","."]
docstr: Update the normalizers and count the total number of frames.
docstr_tok: ["Update","the","normalizers","and","count","the","total","number","of","frames","."]
code: def _update_normalizers(self, iterator):
      """Update the normalizers and count the total number of frames."""
  
      reward_spec = tensor_spec.TensorSpec(shape=[], dtype=tf.float32)
  
      def _update(traj):
          self._agent.update_observation_normalizer(traj.observation)
          self._agent.update_reward_normalizer(traj.reward)
          if traj.reward.shape:
              outer_shape = nest_utils.get_outer_shape(
                  traj.reward, reward_spec
              )
              batch_size = outer_shape[0]
              if len(outer_shape) > 1:
                  batch_size *= outer_shape[1]
          else:
              batch_size = 1
          return batch_size
  
      num_frames = 0
      traj, _ = next(iterator)
      num_frames += _update(traj)
  
      for _ in tf.range(1, self._num_samples):
          traj, _ = next(iterator)
          num_frames += _update(traj)
  
      return num_frames
  
file_path: agents/tf_agents/train/ppo_learner.py
imports: from typing import Callable, Optional, Text
  import gin
  import tensorflow
  from tf_agents.agents import tf_agent
  from tf_agents.agents.ppo import ppo_agent
  from tf_agents.networks import utils
  from tf_agents.specs import tensor_spec
  from tf_agents.train import learner
  from tf_agents.typing import types
  from tf_agents.utils import common
  from tf_agents.utils import nest_utils
label_desc: Use image node_id 4 for calling the PPOLearner obj's underlying member method code with example usage: obj._update_normalizers(iterator) and returns: num_frames, batch_size