class_docstr: ## Trainer
class_docstr_tok: ["#","#","Trainer"]
docstr: ### Train the model based on samples
docstr_tok: ["#","#","#","Train","the","model","based","on","samples"]
code: def train(self, samples: Dict[str, torch.Tensor]):
      """
      ### Train the model based on samples
      """
  
      # It learns faster with a higher number of epochs,
      #  but becomes a little unstable; that is,
      #  the average episode reward does not monotonically increase
      #  over time.
      # May be reducing the clipping range might solve it.
      for _ in range(self.epochs()):
          # shuffle for each epoch
          indexes = torch.randperm(self.batch_size)
  
          # for each mini batch
          for start in range(0, self.batch_size, self.mini_batch_size):
              # get mini batch
              end = start + self.mini_batch_size
              mini_batch_indexes = indexes[start:end]
              mini_batch = {}
              for k, v in samples.items():
                  mini_batch[k] = v[mini_batch_indexes]
  
              # train
              loss = self._calc_loss(mini_batch)
  
              # Set learning rate
              for pg in self.optimizer.param_groups:
                  pg["lr"] = self.learning_rate()
              # Zero out the previously calculated gradients
              self.optimizer.zero_grad()
              # Calculate gradients
              loss.backward()
              # Clip gradients
              torch.nn.utils.clip_grad_norm_(
                  self.model.parameters(), max_norm=0.5
              )
              # Update parameters based on gradients
              self.optimizer.step()
  
imports: from typing import Dict
  import numpy
  import torch
  from torch import nn
  from torch import optim
  from torch.distributions import Categorical
  from labml import monit, tracker, logger, experiment
  from labml.configs import FloatDynamicHyperParam, IntDynamicHyperParam
  from labml_helpers.module import Module
  from labml_nn.rl.game import Worker
  from labml_nn.rl.ppo import ClippedPPOLoss, ClippedValueFunctionLoss
  from labml_nn.rl.ppo.gae import GAE
label_desc: Use image node_id 3 for calling the Trainer obj's underlying member method code with example usage: obj.train(samples) without return types