123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- ################################################################################
- # Copyright (c) 2021 ContinualAI. #
- # Copyrights licensed under the MIT License. #
- # See the accompanying LICENSE file for terms. #
- # #
- # Date: 20-04-2020 #
- # Author(s): Matthias De Lange #
- # E-mail: contact@continualai.org #
- # Website: avalanche.continualai.org #
- ################################################################################
- """
- This is a simple example on how to use the CoPE plugin.
- It's an example in the online data incremental setting, where both learning and
- evaluation is completely task-agnostic.
- Original implementation:
- https://github.com/Mattdl/ContinualPrototypeEvolution
- Reference:
- De Lange, Matthias, et al. "Continual prototype evolution: Learning online from
- non-stationary data streams." ICCV. 2021.
- """
- from __future__ import absolute_import
- from __future__ import division
- from __future__ import print_function
- import argparse
- import torch
- import torch.optim.lr_scheduler
- from avalanche.benchmarks import SplitMNIST
- from avalanche.models import SimpleMLP
- from avalanche.training.strategies import Naive
- from avalanche.training.plugins import CoPEPlugin
- from avalanche.evaluation.metrics import StreamForgetting, \
- accuracy_metrics, loss_metrics
- from avalanche.logging import TextLogger
- from avalanche.training.plugins import EvaluationPlugin
- from avalanche.benchmarks.generators.benchmark_generators import \
- data_incremental_benchmark
- def main(args):
- """
- Last Avalanche version reference performance (online = 1 epoch):
- Class-incremental (online):
- Top1_Acc_Stream/eval_phase/test_stream = 0.9421
- Data-incremental (online:
- Top1_Acc_Stream/eval_phase/test_stream = 0.9309
- These are reference results for a single run.
- """
- # --- DEFAULT PARAMS ONLINE DATA INCREMENTAL LEARNING
- nb_tasks = 5 # Can still design the data stream based on tasks
- batch_size = 10 # Learning agent only has small amount of data available
- epochs = 1 # How many times to process each mini-batch
- return_task_id = False # Data incremental (task-agnostic/task-free)
- # --- CONFIG
- device = torch.device(
- f"cuda:{args.cuda}" if torch.cuda.is_available() and args.cuda >= 0
- else "cpu")
- # ---------
- # --- SCENARIO CREATION
- n_classes = 10
- task_scenario = SplitMNIST(nb_tasks, return_task_id=return_task_id,
- fixed_class_order=[i for i in range(n_classes)])
- # Make data incremental (one batch = one experience)
- scenario = data_incremental_benchmark(task_scenario,
- experience_size=batch_size)
- print(f"{scenario.n_experiences} batches in online data incremental setup.")
- # 6002 batches for SplitMNIST with batch size 10
- # ---------
- # MODEL CREATION
- model = SimpleMLP(num_classes=args.featsize,
- hidden_size=400, hidden_layers=2, drop_rate=0)
- # choose some metrics and evaluation method
- logger = TextLogger()
- eval_plugin = EvaluationPlugin(
- accuracy_metrics(experience=True, stream=True),
- loss_metrics(experience=False, stream=True),
- StreamForgetting(),
- loggers=[logger],
- benchmark=scenario)
- # CoPE PLUGIN
- cope = CoPEPlugin(mem_size=2000, alpha=0.99,
- p_size=args.featsize, n_classes=n_classes)
- # CREATE THE STRATEGY INSTANCE (NAIVE) WITH CoPE PLUGIN
- cl_strategy = Naive(model, torch.optim.SGD(model.parameters(), lr=0.01),
- cope.ppp_loss, # CoPE PPP-Loss
- train_mb_size=batch_size, train_epochs=epochs,
- eval_mb_size=100, device=device,
- plugins=[cope],
- evaluator=eval_plugin
- )
- # TRAINING LOOP
- print('Starting experiment...')
- results = []
- cl_strategy.train(scenario.train_stream)
- print('Computing accuracy on the whole test set')
- results.append(cl_strategy.eval(scenario.test_stream))
- if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- parser.add_argument('--cuda', type=int, default=0,
- help='Select zero-indexed cuda device. -1 to use CPU.')
- parser.add_argument('--featsize', type=int, default=32,
- help='Feature size for the embedding.')
- args = parser.parse_args()
- main(args)
|