docstr: update the Q function (self.model) with DQN algorithm
          
code: def learn(self, obs, action, reward, next_obs, terminal):
      """update the Q function (self.model) with DQN algorithm"""
      # Q
      pred_values = self.model(obs)
      action_dim = pred_values.shape[-1]
      action = paddle.squeeze(action, axis=-1)
      action_onehot = paddle.nn.functional.one_hot(
          action, num_classes=action_dim
      )
      pred_value = pred_values * action_onehot
      pred_value = paddle.sum(pred_value, axis=1, keepdim=True)
  
      # target Q
      with paddle.no_grad():
          max_v = self.target_model(next_obs).max(1, keepdim=True)
          target = reward + (1 - terminal) * self.gamma * max_v
      loss = self.mse_loss(pred_value, target)
  
      # optimize
      self.optimizer.clear_grad()
      loss.backward()
      self.optimizer.step()
      return loss
  
file_path: PARL/parl/algorithms/paddle/dqn.py
imports: import copy
  import parl
  import paddle
  from parl.utils.utils import check_model_method
label_desc: Use image node_id 3 for calling the DQN obj's underlying member method code with example usage: obj.learn(obs, action, reward, next_obs, terminal) and returns: loss