| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- ################################################################################
- # Copyright (c) 2021 ContinualAI. #
- # Copyrights licensed under the MIT License. #
- # See the accompanying LICENSE file for terms. #
- # #
- # Date: 1-06-2020 #
- # Author(s): Andrea Cossu #
- # E-mail: contact@continualai.org #
- # Website: avalanche.continualai.org #
- ################################################################################
- import torch
- import unittest
- import os
- import sys
- from torch.optim import SGD
- from torch.nn import CrossEntropyLoss, Linear
- from avalanche.logging import TextLogger
- from avalanche.models import SimpleMLP
- from avalanche.training.plugins import EvaluationPlugin, StrategyPlugin, \
- LwFPlugin, ReplayPlugin
- from avalanche.training.strategies import Naive, Replay, CWRStar, \
- GDumb, LwF, AGEM, GEM, EWC, \
- SynapticIntelligence, JointTraining, CoPE, StreamingLDA, BaseStrategy
- from avalanche.training.strategies.cumulative import Cumulative
- from avalanche.training.strategies.joint_training import AlreadyTrainedError
- from avalanche.training.strategies.strategy_wrappers import PNNStrategy
- from avalanche.training.strategies.icarl import ICaRL
- from avalanche.training.utils import get_last_fc_layer
- from avalanche.evaluation.metrics import StreamAccuracy
- from tests.unit_tests_utils import get_fast_benchmark, get_device
- class BaseStrategyTest(unittest.TestCase):
- def test_periodic_eval(self):
- model = SimpleMLP(input_size=6, hidden_size=10)
- benchmark = get_fast_benchmark()
- optimizer = SGD(model.parameters(), lr=1e-3)
- criterion = CrossEntropyLoss()
- curve_key = 'Top1_Acc_Stream/eval_phase/train_stream/Task000'
- ###################
- # Case #1: No eval
- ###################
- # we use stream acc. because it emits a single value
- # for each eval loop.
- acc = StreamAccuracy()
- strategy = Naive(model, optimizer, criterion, train_epochs=2,
- eval_every=-1, evaluator=EvaluationPlugin(acc))
- strategy.train(benchmark.train_stream[0])
- # eval is not called in this case
- assert len(strategy.evaluator.get_all_metrics()) == 0
- ###################
- # Case #2: Eval at the end only and before training
- ###################
- acc = StreamAccuracy()
- strategy = Naive(model, optimizer, criterion, train_epochs=2,
- eval_every=0, evaluator=EvaluationPlugin(acc))
- strategy.train(benchmark.train_stream[0])
- # eval is called once at the end of the training loop
- curve = strategy.evaluator.get_all_metrics()[curve_key][1]
- assert len(curve) == 2
- ###################
- # Case #3: Eval after every epoch and before training
- ###################
- acc = StreamAccuracy()
- strategy = Naive(model, optimizer, criterion, train_epochs=2,
- eval_every=1, evaluator=EvaluationPlugin(acc))
- strategy.train(benchmark.train_stream[0])
- # eval is called after every epoch + the end of the training loop
- curve = strategy.evaluator.get_all_metrics()[curve_key][1]
- assert len(curve) == 4
- def test_forward_hooks(self):
- model = SimpleMLP(input_size=6, hidden_size=10)
- optimizer = SGD(model.parameters(), lr=1e-3)
- criterion = CrossEntropyLoss()
- strategy = Naive(model, optimizer, criterion,
- train_epochs=2, eval_every=0)
- was_hook_called = False
- def hook(a, b, c):
- nonlocal was_hook_called
- was_hook_called = True
- model.register_forward_hook(hook)
- mb_x = torch.randn(32, 6, device=strategy.device)
- strategy.mbatch = mb_x, None, None
- strategy.forward()
- assert was_hook_called
- def test_early_stop(self):
- class EarlyStopP(StrategyPlugin):
- def after_training_iteration(self, strategy: 'BaseStrategy',
- **kwargs):
- if strategy.mb_it == 10:
- strategy.stop_training()
- model = SimpleMLP(input_size=6, hidden_size=100)
- criterion = CrossEntropyLoss()
- optimizer = SGD(model.parameters(), lr=1)
- strategy = Cumulative(
- model, optimizer, criterion, train_mb_size=1, device=get_device(),
- eval_mb_size=512, train_epochs=1, evaluator=None,
- plugins=[EarlyStopP()])
- benchmark = get_fast_benchmark()
- for train_batch_info in benchmark.train_stream:
- strategy.train(train_batch_info)
- assert strategy.mb_it == 11
- class StrategyTest(unittest.TestCase):
- if "FAST_TEST" in os.environ:
- fast_test = os.environ['FAST_TEST'].lower() in ["true"]
- else:
- fast_test = False
- if "USE_GPU" in os.environ:
- use_gpu = os.environ['USE_GPU'].lower() in ["true"]
- else:
- use_gpu = False
- print("Fast Test:", fast_test)
- print("Test on GPU:", use_gpu)
- if use_gpu:
- device = "cuda"
- else:
- device = "cpu"
- def init_sit(self):
- model = self.get_model(fast_test=True)
- optimizer = SGD(model.parameters(), lr=1e-3)
- criterion = CrossEntropyLoss()
- benchmark = self.load_benchmark(use_task_labels=False)
- return model, optimizer, criterion, benchmark
- def test_naive(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = Naive(model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50, train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = Naive(model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50, train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_joint(self):
- class JointSTestPlugin(StrategyPlugin):
- def __init__(self, benchmark):
- super().__init__()
- self.benchmark = benchmark
- def after_train_dataset_adaptation(self, strategy: 'BaseStrategy',
- **kwargs):
- """
- Check that the dataset used for training contains the
- correct number of samples.
- """
- cum_len = sum([len(exp.dataset) for exp
- in self.benchmark.train_stream])
- assert len(strategy.adapted_dataset) == cum_len
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = JointTraining(model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50,
- train_epochs=2,
- plugins=[JointSTestPlugin(my_nc_benchmark)])
- strategy.evaluator.loggers = [TextLogger(sys.stdout)]
- strategy.train(my_nc_benchmark.train_stream)
- # MT scenario
- my_nc_benchmark = self.load_benchmark(use_task_labels=True)
- strategy = JointTraining(
- model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50, train_epochs=2,
- plugins=[JointSTestPlugin(my_nc_benchmark)])
- strategy.evaluator.loggers = [TextLogger(sys.stdout)]
- strategy.train(my_nc_benchmark.train_stream)
- # Raise error when retraining
- self.assertRaises(AlreadyTrainedError,
- lambda: strategy.train(my_nc_benchmark.train_stream))
- def test_cwrstar(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- last_fc_name, _ = get_last_fc_layer(model)
- strategy = CWRStar(model, optimizer, criterion, last_fc_name,
- train_mb_size=64, device=self.device)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = CWRStar(model, optimizer, criterion, last_fc_name,
- train_mb_size=64, device=self.device)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_replay(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = Replay(model, optimizer, criterion,
- mem_size=10, train_mb_size=64, device=self.device,
- eval_mb_size=50, train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = Replay(model, optimizer, criterion,
- mem_size=10, train_mb_size=64, device=self.device,
- eval_mb_size=50, train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_gdumb(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = GDumb(
- model, optimizer, criterion,
- mem_size=200, train_mb_size=64, device=self.device,
- eval_mb_size=50, train_epochs=2
- )
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = GDumb(
- model, optimizer, criterion,
- mem_size=200, train_mb_size=64, device=self.device,
- eval_mb_size=50, train_epochs=2
- )
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_cumulative(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = Cumulative(model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = Cumulative(model, optimizer, criterion, train_mb_size=64,
- device=self.device, eval_mb_size=50,
- train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_slda(self):
- model, _, criterion, my_nc_benchmark = self.init_sit()
- strategy = StreamingLDA(model, criterion, input_size=10,
- output_layer_name='features',
- num_classes=10, eval_mb_size=7,
- train_epochs=1, device=self.device,
- train_mb_size=7)
- self.run_strategy(my_nc_benchmark, strategy)
- def test_warning_slda_lwf(self):
- model, _, criterion, my_nc_benchmark = self.init_sit()
- with self.assertLogs('avalanche.training.strategies', "WARNING") as cm:
- StreamingLDA(model, criterion, input_size=10,
- output_layer_name='features', num_classes=10,
- plugins=[LwFPlugin(), ReplayPlugin()])
- self.assertEqual(1, len(cm.output))
- self.assertIn(
- "LwFPlugin seems to use the callback before_backward"
- " which is disabled by StreamingLDA",
- cm.output[0]
- )
- def test_lwf(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = LwF(model, optimizer, criterion,
- alpha=[0, 1 / 2, 2 * (2 / 3), 3 * (3 / 4), 4 * (4 / 5)],
- temperature=2, device=self.device,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = LwF(model, optimizer, criterion,
- alpha=[0, 1 / 2, 2 * (2 / 3), 3 * (3 / 4), 4 * (4 / 5)],
- temperature=2, device=self.device,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_agem(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = AGEM(model, optimizer, criterion,
- patterns_per_exp=250, sample_size=256,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = AGEM(model, optimizer, criterion,
- patterns_per_exp=250, sample_size=256,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_gem(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = GEM(model, optimizer, criterion,
- patterns_per_exp=256,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = GEM(model, optimizer, criterion,
- patterns_per_exp=256,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_ewc(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = EWC(model, optimizer, criterion, ewc_lambda=0.4,
- mode='separate',
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = EWC(model, optimizer, criterion, ewc_lambda=0.4,
- mode='separate',
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_ewc_online(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = EWC(model, optimizer, criterion, ewc_lambda=0.4,
- mode='online', decay_factor=0.1,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = EWC(model, optimizer, criterion, ewc_lambda=0.4,
- mode='online', decay_factor=0.1,
- train_mb_size=10, eval_mb_size=50,
- train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_synaptic_intelligence(self):
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = SynapticIntelligence(
- model, optimizer, criterion, si_lambda=0.0001,
- train_epochs=1, train_mb_size=10, eval_mb_size=10)
- benchmark = self.load_benchmark(use_task_labels=False)
- self.run_strategy(benchmark, strategy)
- # MT scenario
- strategy = SynapticIntelligence(
- model, optimizer, criterion, si_lambda=0.0001,
- train_epochs=1, train_mb_size=10, eval_mb_size=10)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_cope(self):
- # Fast benchmark (hardcoded)
- n_classes = 10
- emb_size = n_classes # Embedding size
- # SIT scenario
- model, optimizer, criterion, my_nc_benchmark = self.init_sit()
- strategy = CoPE(model, optimizer, criterion,
- mem_size=10, n_classes=n_classes, p_size=emb_size,
- train_mb_size=10, device=self.device,
- eval_mb_size=50, train_epochs=2)
- self.run_strategy(my_nc_benchmark, strategy)
- # MT scenario
- strategy = CoPE(model, optimizer, criterion,
- mem_size=10, n_classes=n_classes, p_size=emb_size,
- train_mb_size=10, device=self.device,
- eval_mb_size=50, train_epochs=2)
- benchmark = self.load_benchmark(use_task_labels=True)
- self.run_strategy(benchmark, strategy)
- def test_pnn(self):
- # only multi-task scenarios.
- # eval on future tasks is not allowed.
- strategy = PNNStrategy(
- num_layers=3, in_features=6, hidden_features_per_column=10,
- lr=0.1, train_mb_size=10, device=self.device, eval_mb_size=50,
- train_epochs=2)
- # train and test loop
- benchmark = self.load_benchmark(use_task_labels=True)
- for train_task in benchmark.train_stream:
- strategy.train(train_task)
- strategy.eval(benchmark.test_stream)
-
- def test_icarl(self):
- model, optimizer, criterion, benchmark = self.init_sit()
- strategy = ICaRL(
- model.features, model.classifier, optimizer, 20,
- buffer_transform=None, criterion=criterion,
- fixed_memory=True, train_mb_size=10,
- train_epochs=2, eval_mb_size=50,
- device=self.device,)
- self.run_strategy(benchmark, strategy)
- def load_benchmark(self, use_task_labels=False):
- """
- Returns a NC benchmark from a fake dataset of 10 classes, 5 experiences,
- 2 classes per experience.
- :param fast_test: if True loads fake data, MNIST otherwise.
- """
- return get_fast_benchmark(use_task_labels=use_task_labels)
- def get_model(self, fast_test=False):
- if fast_test:
- return SimpleMLP(input_size=6, hidden_size=10)
- else:
- return SimpleMLP()
- def run_strategy(self, benchmark, cl_strategy):
- print('Starting experiment...')
- cl_strategy.evaluator.loggers = [TextLogger(sys.stdout)]
- results = []
- for train_batch_info in benchmark.train_stream:
- print("Start of experience ", train_batch_info.current_experience)
- cl_strategy.train(train_batch_info)
- print('Training completed')
- print('Computing accuracy on the current test set')
- results.append(cl_strategy.eval(benchmark.test_stream[:]))
- if __name__ == '__main__':
- unittest.main()
|