ContinualAI / avalanche

Avalanche: an End-to-End Library for Continual Learning based on PyTorch.
http://avalanche.continualai.org
MIT License
1.74k stars 285 forks source link

feature request: support gradually changing distributions #1306

Open murphyk opened 1 year ago

murphyk commented 1 year ago

It would be very helpful to support smoothly changing distributions, as illustrated below (from FOO-VB paper, which uses permuted mnist).

Screenshot 2023-02-24 at 5 47 30 PM
AntonioCarta commented 1 year ago

Avalanche benchmarks already support this use case. We are missing some examples of benchmarks with blurry tasks and a high-level generator. We will definitely add them in the future since this setting is becoming quite popular.

murphyk commented 1 year ago

Can you point me to any examples of your existing functionality? We are hoping to submit a paper to COLLAS (https://lifelong-ml.cc/Conferences/2023/call) on March 6th, so would like to try this ASAP. Thx.

HamedHemati commented 1 year ago

Hi @murphyk ,

AFAIK we currently don't have an example that creates streams with smooth transitions, but one way to do this is to use OnlineCLScenario from avalanche.benchmarks.scenarios.online_scenario to convert the list of experiences in a continual learning stream to a sequence of sub-experiences.

For example, if we have a continual learning stream with five experiences $S = [e_1, e_2, ..., e_5]$, we can convert it to a stream of smaller experiences i.e. an online stream as below:

ocl_benchmark = OnlineCLScenario(
        original_streams=benchmark.streams.values(),
        experiences=benchmark.train_stream,
        experience_size=10,
        access_task_boundaries=True
    )

by setting the size of each "sub-experience".

By default, the transition between the original experiences is "abrupt" since OnlineCLScenario creates generators for each experience in the original stream in a sequential order and goes through them one by one and outputs sub-experiences, so the final stream will look like this: $S = [e{1}^{(1)}, e{1}^{(2)}, ..., e{1}^{(L)}, e{2}^{(1)}, ..., e{2}^{(L)}, e{e}^{(1)}, ..., e_{5}^{(L)}]$

For smooth transitions, the exps_iter() function in avalanche.benchmarks.scenarios.online_scenario (here) needs to be changed. This function defines how and in which order the sub-experience generators should be iterated through :

    def exps_iter():
        for exp in original_stream:
            for sub_exp in split_foo(exp, experience_size):
                yield sub_exp

the split_foo function is the default generator that creates sub-experiences for a given experience. As a naive example, I modified the source code and tried a completely random sampler that first samples a random iterator from one of the experiences in the original stream and then returns a sub-experience from it (next(exp_iter)).

def exps_iter():
    exp_iterators = [split_foo(exp, experience_size) for exp in original_stream]

    for i in range(100000):
        exp_iter = random.choice(exp_iterators)
        try:
            yield next(exp_iter)
        except StopIteration:
            continue

It should be possible to replace the random sampler with another sampler for an arbitrary smooth transition to create streams like: $S = [e{1}^{(1)}, e{1}^{(2)}, ..., e{1}^{(L-8)}, e{1}^{(L-9)}, e{2}^{(1)}, e{2}^{(2)}, e{1}^{(L-8)}, e{2}^{(3)}..., ]$

@AntonioCarta, perhaps we can make exp_iter() an optional input argument to OnlineCLScneario?

AntonioCarta commented 1 year ago

@AntonioCarta, perhaps we can make exp_iter() an optional input argument to OnlineCLScneario?

I think it's better to add a separate stream generator for it since they are different scenarios.

Just a minor comment: your last exps_iter function is choosing a single empirical distribution for each minibatch, while I think in smooth scenarios you draw samples independently so you can have different tasks in the same minibatch (but it's easy to adapt your code).

@murphyk we are also working on a CoLLAs submission so it's unlikely that we can push this before the CoLLAs deadline but I think @HamedHemati comment should be a good starting point.

murphyk commented 1 year ago

ok, thanks.