docstr: Define the sampling process. This function returns the action according to action distribution.
  
  Args:
      obs (torch tensor): observation, shape([batch_size] + obs_shape)
  Returns:
      value (torch tensor): value, shape([batch_size, 1])
      action (torch tensor): action, shape([batch_size] + action_shape)
      action_log_probs (torch tensor): action log probs, shape([batch_size])
      action_entropy (torch tensor): action entropy, shape([batch_size])
docstr_tok: ["Define","the","sampling","process",".","This","function","returns","the","action","according","to","action","distribution",".","Args",":","obs","(","torch","tensor",")",":","observation",",","shape","(","[","batch_size","]","+","obs_shape",")","Returns",":","value","(","torch","tensor",")",":","value",",","shape","(","[","batch_size",",","1","]",")","action","(","torch","tensor",")",":","action",",","shape","(","[","batch_size","]","+","action_shape",")","action_log_probs","(","torch","tensor",")",":","action","log","probs",",","shape","(","[","batch_size","]",")","action_entropy","(","torch","tensor",")",":","action","entropy",",","shape","(","[","batch_size","]",")"]
code: def sample(self, obs):
      """Define the sampling process. This function returns the action according to action distribution.
  
      Args:
          obs (torch tensor): observation, shape([batch_size] + obs_shape)
      Returns:
          value (torch tensor): value, shape([batch_size, 1])
          action (torch tensor): action, shape([batch_size] + action_shape)
          action_log_probs (torch tensor): action log probs, shape([batch_size])
          action_entropy (torch tensor): action entropy, shape([batch_size])
      """
      value = self.model.value(obs)
  
      if self.continuous_action:
          mean, std = self.model.policy(obs)
          dist = Normal(mean, std)
          action = dist.sample([1])
  
          action_log_probs = dist.log_prob(action).sum(-1)
          action_entropy = dist.entropy().sum(-1).mean()
      else:
          logits = self.model.policy(obs)
          dist = Categorical(logits=logits)
          action = dist.sample([1])
  
          act_dim = logits.shape[-1]
          actions_onehot = F.one_hot(action, act_dim)
          action_log_probs = paddle.sum(
              F.log_softmax(logits) * actions_onehot, axis=-1
          )
          action_entropy = dist.entropy()
  
      return value, action, action_log_probs, action_entropy
  
file_path: PARL/parl/algorithms/paddle/ppo.py
imports: import parl
  import paddle
  import paddle.nn
  import paddle.nn.functional
  import paddle.optimizer
  from paddle.distribution import Normal, Categorical
  from parl.utils.utils import check_model_method
label_desc: Use image node_id 3 for calling the PPO obj's underlying member method code with example usage: obj.sample(obs) and returns: value,  action,  action_log_probs,  action_entropy