class_docstr: # Arguments
      model__: A Keras model.
      policy__: A Keras-rl policy that are defined in [policy](https://github.com/keras-rl/keras-rl/blob/master/rl/policy.py).
      test_policy__: A Keras-rl policy.
      enable_double_dqn__: A boolean which enable target network as a second network proposed by van Hasselt et al. to decrease overfitting.
      enable_dueling_dqn__: A boolean which enable dueling architecture proposed by Mnih et al.
      dueling_type__: If `enable_dueling_dqn` is set to `True`, a type of dueling architecture must be chosen which calculate Q(s,a) from V(s) and A(s,a) differently. Note that `avg` is recommanded in the [paper](https://arxiv.org/abs/1511.06581).
          `avg`: Q(s,a;theta) = V(s;theta) + (A(s,a;theta)-Avg_a(A(s,a;theta)))
          `max`: Q(s,a;theta) = V(s;theta) + (A(s,a;theta)-max_a(A(s,a;theta)))
          `naive`: Q(s,a;theta) = V(s;theta) + A(s,a;theta)
code: def compile(self, optimizer, metrics=[]):
      metrics += [mean_q]  # register default metrics
  
      # We never train the target model, hence we can set the optimizer and loss arbitrarily.
      self.target_model = clone_model(
          self.model, self.custom_model_objects
      )
      self.target_model.compile(optimizer="sgd", loss="mse")
      self.model.compile(optimizer="sgd", loss="mse")
  
      # Compile model.
      if self.target_model_update < 1.0:
          # We use the `AdditionalUpdatesOptimizer` to efficiently soft-update the target model.
          updates = get_soft_target_model_updates(
              self.target_model, self.model, self.target_model_update
          )
          optimizer = AdditionalUpdatesOptimizer(optimizer, updates)
  
      def clipped_masked_error(args):
          y_true, y_pred, mask = args
          loss = huber_loss(y_true, y_pred, self.delta_clip)
          loss *= mask  # apply element-wise mask
          return K.sum(loss, axis=-1)
  
      # Create trainable model. The problem is that we need to mask the output since we only
      # ever want to update the Q values for a certain action. The way we achieve this is by
      # using a custom Lambda layer that computes the loss. This gives us the necessary flexibility
      # to mask out certain parameters by passing in multiple inputs to the Lambda layer.
      y_pred = self.model.output
      y_true = Input(name="y_true", shape=(self.nb_actions,))
      mask = Input(name="mask", shape=(self.nb_actions,))
      loss_out = Lambda(
          clipped_masked_error, output_shape=(1,), name="loss"
      )([y_true, y_pred, mask])
      ins = (
          [self.model.input]
          if type(self.model.input) is not list
          else self.model.input
      )
      trainable_model = Model(
          inputs=ins + [y_true, mask], outputs=[loss_out, y_pred]
      )
      assert len(trainable_model.output_names) == 2
      combined_metrics = {trainable_model.output_names[1]: metrics}
      losses = [
          lambda y_true, y_pred: y_pred,  # loss is computed in Lambda layer
          lambda y_true, y_pred: K.zeros_like(
              y_pred
          ),  # we only include this for the metrics
      ]
      trainable_model.compile(
          optimizer=optimizer, loss=losses, metrics=combined_metrics
      )
      self.trainable_model = trainable_model
  
      self.compiled = True
  
imports: from __future__ import division
  import warnings
  import keras.backend
  from keras.models import Model
  from keras.layers import Lambda, Input, Layer, Dense
  from rl.core import Agent
  from rl.policy import EpsGreedyQPolicy, GreedyQPolicy
  from rl.util import *
label_desc: Use image node_id 3 for calling the DQNAgent obj's underlying member method code with example usage: obj.compile(optimizer, metrics) and returns: K