class_docstr: A DQN Agent.
  
  Implements the DQN algorithm from
  
  "Human level control through deep reinforcement learning"
    Mnih et al., 2015
    https://deepmind.com/research/dqn/
  
  This agent also implements n-step updates. See "Rainbow: Combining
  Improvements in Deep Reinforcement Learning" by Hessel et al., 2017, for a
  discussion on its benefits: https://arxiv.org/abs/1710.02298
class_docstr_tok: ["A","DQN","Agent",".","Implements","the","DQN","algorithm","from","''","Human","level","control","through","deep","reinforcement","learning","''","Mnih","et","al.",",","2015","https",":","\/\/deepmind.com\/research\/dqn\/","This","agent","also","implements","n-step","updates",".","See","``","Rainbow",":","Combining","Improvements","in","Deep","Reinforcement","Learning","''","by","Hessel","et","al.",",","2017",",","for","a","discussion","on","its","benefits",":","https",":","\/\/arxiv.org\/abs\/1710.02298"]
code: def _train(self, experience, weights):
      with tf.GradientTape() as tape:
          loss_info = self._loss(
              experience,
              td_errors_loss_fn=self._td_errors_loss_fn,
              gamma=self._gamma,
              reward_scale_factor=self._reward_scale_factor,
              weights=weights,
              training=True,
          )
      tf.debugging.check_numerics(loss_info.loss, "Loss is inf or nan")
      variables_to_train = self._q_network.trainable_weights
      non_trainable_weights = self._q_network.non_trainable_weights
      assert list(
          variables_to_train
      ), "No variables in the agent's q_network."
      grads = tape.gradient(loss_info.loss, variables_to_train)
      # Tuple is used for py3, where zip is a generator producing values once.
      grads_and_vars = list(zip(grads, variables_to_train))
      if self._gradient_clipping is not None:
          grads_and_vars = eager_utils.clip_gradient_norms(
              grads_and_vars, self._gradient_clipping
          )
  
      if self._summarize_grads_and_vars:
          grads_and_vars_with_non_trainable = grads_and_vars + [
              (None, v) for v in non_trainable_weights
          ]
          eager_utils.add_variables_summaries(
              grads_and_vars_with_non_trainable, self.train_step_counter
          )
          eager_utils.add_gradients_summaries(
              grads_and_vars, self.train_step_counter
          )
      self._optimizer.apply_gradients(grads_and_vars)
      self.train_step_counter.assign_add(1)
  
      self._update_target()
  
      return loss_info
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import collections
  from typing import Optional, Text, cast
  import gin
  import tensorflow
  from tf_agents.agents import data_converter
  from tf_agents.agents import tf_agent
  from tf_agents.networks import network
  from tf_agents.networks import utils
  from tf_agents.policies import boltzmann_policy
  from tf_agents.policies import epsilon_greedy_policy
  from tf_agents.policies import greedy_policy
  from tf_agents.policies import q_policy
  from tf_agents.specs import tensor_spec
  from tf_agents.trajectories import time_step
  from tf_agents.typing import types
  from tf_agents.utils import common
  from tf_agents.utils import eager_utils
  from tf_agents.utils import nest_utils
label_desc: Use image node_id 7 for calling the DqnAgent obj's underlying member method code with example usage: obj._train(experience, weights) and returns: loss_info