class_docstr: DQN learner.
  
  This is the learning component of a DQN agent. It takes a dataset as input
  and implements update functionality to learn from this dataset. Optionally
  it takes a replay client as well to allow for updating of priorities.
docstr: Do a step of SGD and update the priorities.
docstr_tok: ["Do","a","step","of","SGD","and","update","the","priorities","."]
code: def _step(self) -> Dict[str, tf.Tensor]:
      """Do a step of SGD and update the priorities."""
  
      # Pull out the data needed for updates/priorities.
      inputs = next(self._iterator)
      transitions: types.Transition = inputs.data
      keys, probs = inputs.info[:2]
  
      with tf.GradientTape() as tape:
          # Evaluate our networks.
          q_tm1 = self._network(transitions.observation)
          q_t_value = self._target_network(transitions.next_observation)
          q_t_selector = self._network(transitions.next_observation)
  
          # The rewards and discounts have to have the same type as network values.
          r_t = tf.cast(transitions.reward, q_tm1.dtype)
          if self._max_abs_reward:
              r_t = tf.clip_by_value(
                  r_t, -self._max_abs_reward, self._max_abs_reward
              )
          d_t = tf.cast(transitions.discount, q_tm1.dtype) * tf.cast(
              self._discount, q_tm1.dtype
          )
  
          # Compute the loss.
          _, extra = trfl.double_qlearning(
              q_tm1,
              transitions.action,
              r_t,
              d_t,
              q_t_value,
              q_t_selector,
          )
          loss = losses.huber(
              extra.td_error, self._huber_loss_parameter
          )
  
          # Get the importance weights.
          importance_weights = 1.0 / probs  # [B]
          importance_weights **= self._importance_sampling_exponent
          importance_weights /= tf.reduce_max(importance_weights)
  
          # Reweight.
          loss *= tf.cast(importance_weights, loss.dtype)  # [B]
          loss = tf.reduce_mean(loss, axis=[0])  # []
  
      # Do a step of SGD.
      gradients = tape.gradient(loss, self._network.trainable_variables)
      gradients, _ = tf.clip_by_global_norm(
          gradients, self._max_gradient_norm
      )
      self._optimizer.apply(
          gradients, self._network.trainable_variables
      )
  
      # Get the priorities that we'll use to update.
      priorities = tf.abs(extra.td_error)
  
      # Periodically update the target network.
      if tf.math.mod(self._num_steps, self._target_update_period) == 0:
          for src, dest in zip(
              self._network.variables, self._target_network.variables
          ):
              dest.assign(src)
      self._num_steps.assign_add(1)
  
      # Report loss & statistics for logging.
      fetches = {
          "loss": loss,
          "keys": keys,
          "priorities": priorities,
      }
  
      return fetches
  
imports: import time
  from typing import Dict, List, Optional, Union
  import acme
  from acme import types
  from acme.adders import reverb
  from acme.tf import losses
  from acme.tf import savers
  from acme.tf import utils
  from acme.utils import counting
  from acme.utils import loggers
  import numpy
  import reverb
  import sonnet
  import tensorflow
  import trfl
label_desc: Use image node_id 2 for calling the DQNLearner obj's underlying member method code with example usage: obj._step() and returns: fetches