code: def _reader(self):
      while True:
          sample_data = self.sample_data_queue.get()
          self.sample_total_steps += sample_data["obs"].shape[0]
          self.batch_buffer.append(sample_data)
  
          buffer_size = sum(
              [data["obs"].shape[0] for data in self.batch_buffer]
          )
          if buffer_size >= self.config["train_batch_size"]:
              batch = {}
              for key in self.batch_buffer[0].keys():
                  batch[key] = np.concatenate(
                      [data[key] for data in self.batch_buffer]
                  )
              self.batch_buffer = []
  
              obs_np = batch["obs"].astype("float32")
              actions_np = batch["actions"].astype("int64")
              behaviour_logits_np = batch["behaviour_logits"].astype(
                  "float32"
              )
              rewards_np = batch["rewards"].astype("float32")
              dones_np = batch["dones"].astype("bool")
  
              self.lr = self.lr_scheduler.step()
              self.entropy_coeff = self.entropy_coeff_scheduler.step()
  
              yield [
                  obs_np,
                  actions_np,
                  behaviour_logits_np,
                  rewards_np,
                  dones_np,
              ]
  
imports: import gym
  import numpy
  import os
  from six.moves import queue
  import time
  import threading
  import parl
  import paddle
  from atari_model import AtariModel
  from atari_agent import AtariAgent
  from parl.env.atari_wrappers import wrap_deepmind
  from parl.utils import logger, summary
  from parl.utils.scheduler import PiecewiseScheduler
  from parl.utils.time_stat import TimeStat
  from parl.utils.window_stat import WindowStat
  from actor import Actor
label_desc: Use image node_id 2 for calling the Learner obj's underlying member method code with example usage: obj._reader() without return types