def _target_update(self):
        '''
        Perform update on target model networks.  This update is either 'soft', meaning the target model drifts towards
        the current model at a rate tau, or 'hard', meaning the target model performs a hard copy operation on the
        current model every target_update_interval steps.
        '''
        if self.target_update_type == 'soft':
            self.model_target.actor.soft_update(self.model.actor, self.target_update_tau)
            self.model_target.critic.soft_update(self.model.critic, self.target_update_tau)
            if self.use_double_critic:
                self.model_target2.critic.soft_update(self.model2.critic, self.target_update_tau)
                if self.is_pixel_input:
                    self.model_target2.perception.soft_update(self.model2.perception, self.target_update_tau)
            if self.is_pixel_input:
                self.model_target.perception.soft_update(self.model.perception, self.target_update_tau)
        elif self.target_update_type == 'hard':
            self.target_update_counter += 1
            if self.target_update_counter % self.target_update_interval == 0:
                self.model_target.actor.hard_update(self.model.actor)
                self.model_target.critic.hard_update(self.model.critic)
                if self.use_double_critic:
                    self.model_target2.critic.hard_update(self.model2.critic)
                    if self.is_pixel_input:
                        self.model_target2.perception.hard_update(self.model2.perception)
                if self.is_pixel_input:
                    self.model_target.perception.hard_update(self.model.perception)

        Perform update on target model networks.  This update is either 'soft', meaning the target model drifts towards
        the current model at a rate tau, or 'hard', meaning the target model performs a hard copy operation on the
        current model every target_update_interval steps.
        
surreal/learner/ddpg.py