In this below code, within the method 'select_action' within the class PPOAgent, I am getting the proper result of 'scaled_action' with in the bounds from the forward method within the class Actor, but my actual problem is that, I am not getting the result of 'scaled_action' with proper variation ranges with in the bounds(bound_low and bound_high). Here the scaled_action consists of 13 action space datas among the 13 variables, first 5 variables having very low range of distribution with in th bounds (low, high) as (0.18e-6, 0.2e-6) for these first 5 variables i am getting the result of 'scaled_action' as satisfactory, but for the remaining 8 action data the available bounds range of distributions are large, but i am not getting the results as much variations with in the bounds. The 'action_probs' from the forward method from the Class Actor provides proper scaled action space data with properly distributed action space with in bounds for each timesteps in the training loop, but the resultat scaled action from the method 'select_action' was not given wide range of variations in each timesteps in each episodes with in the RL training loop. how can i get the 'scaled_action' result with very wide distribution of values wiht in the specified bounds. i tried with the different epsilon values but nothing can be improved in the results. please address my issue and provide me the suggestion to rectify my problem and provide me the necessary updated code to solve my existing problem.

class Actor(torch.nn.Module):
    def __init__(self, gnn_model):
        super(Actor, self).__init__()
        self.gnn = gnn_model
        # Bounds are converted to tensors for ease of calculation
        self.bounds_low = torch.tensor([0.18e-6, 0.18e-6, 0.18e-6, 0.18e-6, 0.18e-6, 
                                        0.5e-6, 0.5e-6, 0.5e-6, 0.5e-6, 0.5e-6, 
                                        15e-6, 0.1e-12, 0.8], dtype=torch.float32)
                                        
        self.bounds_high = torch.tensor([0.2e-6, 0.2e-6, 0.2e-6, 0.2e-6, 0.2e-6, 
                                         50e-6, 50e-6, 50e-6, 50e-6, 50e-6, 
                                         30e-6, 10e-12, 1.4], dtype=torch.float32)

class PPOAgent:
    def __init__(self, gnn_model, state_dim, action_space, lr_actor, lr_critic, gamma, gae_lambda, epsilon, policy_clip, epochs, entropy_coef):
        self.gamma = gamma
        self.gae_lambda = gae_lambda
        self.epsilon = epsilon
        self.policy_clip = policy_clip
        self.epochs = epochs
        self.entropy_coef = entropy_coef  # Dynamic entropy coefficient
        
        self.actor = Actor(gnn_model)
        self.critic = Critic()
        self.optimizer_actor = optim.Adam(self.actor.parameters(), lr=lr_actor)
        self.optimizer_critic = optim.Adam(self.critic.parameters(), lr=lr_critic)
        self.action_space = action_space  # Assume continuous
        
    def select_action(self, state, performance_metrics):
        action_probs = self.actor(state)        
        
        # Ensure the variance is at least 1D
        epsilon = 1e-2
        variances = action_probs.var(dim=0, keepdim=True).expand(action_probs.shape[0]) + epsilon         

        cov_mat = torch.diag(variances)  # Form an [13, 13] covariance matrix with variances on the diagonal

        # Define the Multivariate Normal distribution
        dist = MultivariateNormal(action_probs, cov_mat)
        
        # Sample an action
        raw_action = dist.sample()         
        
        # Scale the raw sampled action to fit within the specified bounds
        min_values = self.actor.bounds_low
        max_values = self.actor.bounds_high
        scaled_action = min_values + ((torch.tanh(raw_action) + 1) / 2) * (max_values - min_values)        
        
        log_prob = dist.log_prob(raw_action) - torch.log(max_values - min_values).sum()  # Compute log probability with raw action
        
        return scaled_action.detach().numpy().squeeze(), log_prob.item(), performance_metrics