Repository: ContinualAI/avalanche

Issue:
update Cumulative and GDumb strategies
Currently in `training.old_strategies`.


Discussion:

Resolving patch:
diff --git a/avalanche/training/plugins.py b/avalanche/training/plugins.py
--- a/avalanche/training/plugins.py
+++ b/avalanche/training/plugins.py
@@ -1,6 +1,6 @@
 import copy
 from collections import defaultdict
-from typing import Optional, Dict, Any
+from typing import Dict, Any
 
 import numpy as np
 import torch
@@ -180,12 +180,6 @@ def adapt_train_dataset(self, strategy, **kwargs):
             GDumb approach and updating the dataset accordingly.
         """
 
-        # helper memory to store new patterns when memory is not full
-        # this is necessary since it is not possible to concatenate
-        # patterns into an existing TensorDataset
-        # (dataset.tensors[0] does not support item assignment)
-        ext_mem = [[], []]
-
         # for each pattern, add it to the memory or not
         for i, (pattern, target) in enumerate(strategy.current_data):
             target_value = target.item()
@@ -228,6 +222,8 @@ def adapt_train_dataset(self, strategy, **kwargs):
 
                 self.counter[target_value] += 1
 
+        strategy.current_data = self.ext_mem
+
 
 class EvaluationPlugin(StrategyPlugin):
     """
diff --git a/avalanche/training/strategies.py b/avalanche/training/strategies.py
--- a/avalanche/training/strategies.py
+++ b/avalanche/training/strategies.py
@@ -3,10 +3,12 @@
 from torch.nn import Module
 from torch.optim import Optimizer
 
+from torch.utils.data import ConcatDataset
+
 from avalanche.evaluation import EvalProtocol
 from avalanche.training.base_strategy import BaseStrategy
 from avalanche.training.plugins import StrategyPlugin, \
-    CWRStarPlugin, ReplayPlugin
+    CWRStarPlugin, ReplayPlugin, GDumbPlugin
 
 
 class Naive(BaseStrategy):
@@ -111,4 +113,79 @@ def __init__(self, model: Module, optimizer: Optimizer, criterion,
             test_mb_size=test_mb_size, device=device, plugins=plugins)
 
 
-__all__ = ['Naive', 'CWRStar', 'Replay']
+class GDumb(BaseStrategy):
+
+    def __init__(self, model: Module, optimizer: Optimizer, criterion,
+                 mem_size: int = 200,
+                 evaluation_protocol: Optional[EvalProtocol] = None,
+                 train_mb_size: int = 1, train_epochs: int = 1,
+                 test_mb_size: int = None, device=None,
+                 plugins: Optional[List[StrategyPlugin]] = None,
+                 ):
+        """ GDumb strategy. See GDumbPlugin for more details.
+
+        :param model: The model.
+        :param optimizer: The optimizer to use.
+        :param criterion: The loss criterion to use.
+        :param mem_size: replay buffer size.
+        :param evaluation_protocol: The evaluation plugin.
+        :param train_mb_size: The train minibatch size. Defaults to 1.
+        :param train_epochs: The number of training epochs. Defaults to 1.
+        :param test_mb_size: The test minibatch size. Defaults to 1.
+        :param device: The device to use. Defaults to None (cpu).
+        :param plugins: Plugins to be added. Defaults to None.
+        """
+
+        gdumb = GDumbPlugin(mem_size)
+        if plugins is None:
+            plugins = [gdumb]
+        else:
+            plugins.append(gdumb)
+
+        super().__init__(
+            model, optimizer, criterion, evaluation_protocol,
+            train_mb_size=train_mb_size, train_epochs=train_epochs,
+            test_mb_size=test_mb_size, device=device, plugins=plugins)
+
+
+class Cumulative(BaseStrategy):
+
+    def __init__(self, model: Module, optimizer: Optimizer, criterion,
+                 evaluation_protocol: Optional[EvalProtocol] = None,
+                 train_mb_size: int = 1, train_epochs: int = 1,
+                 test_mb_size: int = None, device=None,
+                 plugins: Optional[List[StrategyPlugin]] = None,
+                 ):
+        """ Cumulative strategy. At each step,
+            train model with data from all previous steps and current step.
+
+        :param model: The model.
+        :param optimizer: The optimizer to use.
+        :param criterion: The loss criterion to use.
+        :param evaluation_protocol: The evaluation plugin.
+        :param train_mb_size: The train minibatch size. Defaults to 1.
+        :param train_epochs: The number of training epochs. Defaults to 1.
+        :param test_mb_size: The test minibatch size. Defaults to 1.
+        :param device: The device to use. Defaults to None (cpu).
+        :param plugins: Plugins to be added. Defaults to None.
+        """
+
+        super().__init__(
+            model, optimizer, criterion, evaluation_protocol,
+            train_mb_size=train_mb_size, train_epochs=train_epochs,
+            test_mb_size=test_mb_size, device=device, plugins=plugins)
+
+        self.dataset = None  # cumulative dataset
+
+    def adapt_train_dataset(self, **kwargs):
+
+        super().adapt_train_dataset(**kwargs)
+
+        if self.dataset is None:
+            self.dataset = self.current_data
+        else:
+            self.dataset = ConcatDataset([self.dataset, self.current_data])
+            self.current_data = self.dataset
+
+
+__all__ = ['Naive', 'CWRStar', 'Replay', 'GDumb', 'Cumulative']


Test patch:
diff --git a/tests/test_strategies.py b/tests/test_strategies.py
--- a/tests/test_strategies.py
+++ b/tests/test_strategies.py
@@ -22,7 +22,8 @@
 from torch.nn import CrossEntropyLoss
 
 from avalanche.extras.models import SimpleMLP
-from avalanche.training.strategies import Naive, Replay, CWRStar
+from avalanche.training.strategies import Naive, Replay, CWRStar, \
+    GDumb, Cumulative
 from avalanche.benchmarks import nc_scenario, NCStepInfo
 
 
@@ -91,6 +92,30 @@ def test_replay(self):
         strategy = Replay(model, optimizer, criterion,
                           mem_size=200, train_mb_size=64)
         self.run_strategy(my_nc_scenario, strategy)
+    
+    def test_gdumb(self):
+        model = SimpleMLP()
+        optimizer = SGD(model.parameters(), lr=1e-3)
+        criterion = CrossEntropyLoss()
+        mnist_train, mnist_test = self.load_dataset()
+        my_nc_scenario = nc_scenario(
+            mnist_train, mnist_test, 5, task_labels=False, seed=1234)
+
+        strategy = GDumb(
+                model, optimizer, criterion,
+                mem_size=200, train_mb_size=64)
+        self.run_strategy(my_nc_scenario, strategy)
+
+    def test_cumulative(self):
+        model = SimpleMLP()
+        optimizer = SGD(model.parameters(), lr=1e-3)
+        criterion = CrossEntropyLoss()
+        mnist_train, mnist_test = self.load_dataset()
+        my_nc_scenario = nc_scenario(
+            mnist_train, mnist_test, 5, task_labels=False, seed=1234)
+
+        strategy = Cumulative(model, optimizer, criterion, train_mb_size=64)
+        self.run_strategy(my_nc_scenario, strategy)
 
     def load_dataset(self):
         mnist_train = MNIST(