stable-baselines3 icon indicating copy to clipboard operation
stable-baselines3 copied to clipboard

[Question] Multiple Callbacks For callback_on_new_best

Open EitanGronich opened this issue 1 year ago • 3 comments

❓ Question

I have a simple use case that I have found no answer to in the documentation. (v. 2.2.1) I want to pass two chained callbacks as a callback_on_new_best for EvalCallback. (A custom one for drawing a figure and a library one - StopTrainingOnRewardThreshold) Passing a CallbackList doesn't seem to work, since the parent attribute of the callbacks is None, and the code throws an AssertionError because it asserts their parent is the EvalCallback. There seem to be no other options except building a custom callback that does them both, but this doesn't seem like good practice given that CallbackList does exist. Am I missing something? Minimal reproducible:

import gymnasium as gym
from stable_baselines3 import PPO
from stable_baselines3.common.callbacks import BaseCallback, EvalCallback, StopTrainingOnRewardThreshold, CallbackList

class CustomCallback(BaseCallback):

    def __init__(self, verbose=0):
        super().__init__(verbose)
    
    def _on_step(self):
        # Draw a figure
        return True


eval_env = gym.make("Pendulum-v1")

stop_on_threshold_callback = StopTrainingOnRewardThreshold(reward_threshold=-200, verbose=1)

eval_callback = EvalCallback(eval_env, best_model_save_path="./logs/",
                             log_path="./logs/", eval_freq=500,
                             deterministic=True, render=False,
                             callback_on_new_best=CallbackList([CustomCallback(), stop_on_threshold_callback])
                             )

model = PPO("MlpPolicy", "Pendulum-v1")
model.learn(5000, callback=eval_callback)

Thanks a lot!

Checklist

EitanGronich avatar Dec 20 '23 14:12 EitanGronich

Hello, thanks for reporting the issue, I think we need to give access to the common parent when using a CallbackList.

araffin avatar Jan 12 '24 11:01 araffin

Running into the same issue! Is there really no work around?

icheered avatar Jan 14 '24 20:01 icheered

Is there really no work around?

a quick workaround is to redefine StopTrainingOnRewardThreshold, combine the two callbacks in one

a better workaround is to fix the code and I would appreciate to receive a PR that solves this issue ;)

araffin avatar Jan 15 '24 09:01 araffin

I'm happy to work on implementing this one

will-maclean avatar May 27 '24 09:05 will-maclean