Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Documentation & Typos #1629

Draft
wants to merge 36 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9c9b8f9
typos
jneuendorf Mar 21, 2024
e2a3bd3
WIP: refactoring (_init_transform_groups -> TransformGroups.create)
jneuendorf Mar 25, 2024
f9936db
typo
jneuendorf Mar 25, 2024
471935b
revert e2a3bd35, enable transform groups kwargs for as_avalanche_data…
jneuendorf Mar 25, 2024
fb59bf3
Merge branch 'documentation' of github.com:jneuendorf/avalanche into …
jneuendorf Mar 25, 2024
f407b7a
typos, fix benchmark example code
jneuendorf May 12, 2024
d1f171c
export MNIST default transforms for composing to them
jneuendorf May 21, 2024
a5bb5bc
typos
jneuendorf May 25, 2024
f1a4d0f
[docs] replace dataset with experience for dynamic moduels
jneuendorf May 25, 2024
d7ad34b
defaults for _init_transform_groups (implementation covers these cases)
jneuendorf May 25, 2024
f7d1b4e
typos
jneuendorf May 27, 2024
6916ef0
typo
jneuendorf May 30, 2024
b062b96
split_validation_random: no default value for required 'dataset' argu…
jneuendorf May 30, 2024
46c98ec
Merge branch 'master' into documentation
jneuendorf May 30, 2024
4410aa6
Merge branch 'documentation' into documentation2
jneuendorf May 30, 2024
a6fcb39
typo
jneuendorf May 30, 2024
68cd80b
[typing] use Self instead TypeVar, organize imports
jneuendorf May 30, 2024
b94bed2
[benchmark] typing
jneuendorf May 31, 2024
3021e90
[benchmark] typo
jneuendorf May 31, 2024
8c819b7
[benchmark] enhance split_validation_random typing
jneuendorf May 31, 2024
393ba88
[models] fix incorrectly merged optimizer
jneuendorf Jun 1, 2024
13a33f5
[training] fix imports/exports, typo
jneuendorf Jun 2, 2024
ebc2aef
[notebooks] fix Avalanche dataset contructor
jneuendorf Jun 2, 2024
38173c1
[benchmarks] prefer make_avalanche_dataset over constructor for singl…
jneuendorf Jun 3, 2024
61f3253
Merge branch 'master' into documentation
jneuendorf Jun 3, 2024
15efc3c
[models] dynamic module typos
jneuendorf Jun 3, 2024
74d3aa3
Merge branch 'documentation2' of github.com:jneuendorf/avalanche into…
jneuendorf Jun 3, 2024
8b7b73e
Merge branch 'documentation2' into documentation
jneuendorf Jun 3, 2024
a8995fb
[benchmarks] typos, doc notes
jneuendorf Jun 6, 2024
1486573
[benchmarks] typing
jneuendorf Jun 6, 2024
7cc252f
[benchmarks] typing
jneuendorf Jun 7, 2024
65ba3d4
[training] fix typing and typo in SCR
jneuendorf Jun 11, 2024
c19558b
[evaluation] typo, [training] better error message
jneuendorf Jun 14, 2024
d08c642
[training] typing (optional evaluator, remove redundant generic + pro…
jneuendorf Jun 14, 2024
c5c635d
typo, documentation
jneuendorf Jun 20, 2024
f7a4934
[training] add debug prints to contrastive learning
jneuendorf Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions avalanche/benchmarks/classic/cmnist.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@
)
from avalanche.benchmarks.utils.data import make_avalanche_dataset

_default_mnist_train_transform = Compose([Normalize((0.1307,), (0.3081,))])

_default_mnist_eval_transform = Compose([Normalize((0.1307,), (0.3081,))])
default_mnist_train_transform = Compose([Normalize((0.1307,), (0.3081,))])
default_mnist_eval_transform = Compose([Normalize((0.1307,), (0.3081,))])


class PixelsPermutation(object):
Expand Down Expand Up @@ -83,8 +82,8 @@ def SplitMNIST(
shuffle: bool = True,
class_ids_from_zero_in_each_exp: bool = False,
class_ids_from_zero_from_first_exp: bool = False,
train_transform: Optional[Any] = _default_mnist_train_transform,
eval_transform: Optional[Any] = _default_mnist_eval_transform,
train_transform: Optional[Any] = default_mnist_train_transform,
eval_transform: Optional[Any] = default_mnist_eval_transform,
dataset_root: Optional[Union[str, Path]] = None
):
"""
Expand Down Expand Up @@ -170,8 +169,8 @@ def PermutedMNIST(
*,
return_task_id=False,
seed: Optional[int] = None,
train_transform: Optional[Any] = _default_mnist_train_transform,
eval_transform: Optional[Any] = _default_mnist_eval_transform,
train_transform: Optional[Any] = default_mnist_train_transform,
eval_transform: Optional[Any] = default_mnist_eval_transform,
dataset_root: Optional[Union[str, Path]] = None
) -> NCScenario:
"""
Expand Down Expand Up @@ -268,8 +267,8 @@ def RotatedMNIST(
return_task_id: bool = False,
seed: Optional[int] = None,
rotations_list: Optional[Sequence[int]] = None,
train_transform: Optional[Any] = _default_mnist_train_transform,
eval_transform: Optional[Any] = _default_mnist_eval_transform,
train_transform: Optional[Any] = default_mnist_train_transform,
eval_transform: Optional[Any] = default_mnist_eval_transform,
dataset_root: Optional[Union[str, Path]] = None
) -> NCScenario:
"""Creates a Rotated MNIST benchmark.
Expand Down Expand Up @@ -379,7 +378,13 @@ def RotatedMNIST(
)


__all__ = ["SplitMNIST", "PermutedMNIST", "RotatedMNIST"]
__all__ = [
"SplitMNIST",
"PermutedMNIST",
"RotatedMNIST",
"default_mnist_train_transform",
"default_mnist_eval_transform",
]


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion avalanche/benchmarks/datasets/dataset_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def load_config_file():


def maybe_init_config_file():
"""Initialize Avalanche user's config file, if it does not exists yet.
"""Initialize Avalanche user's config file, if it does not exist yet.

The file is located in `~/.avalanche/config.json`
"""
Expand Down
1 change: 1 addition & 0 deletions avalanche/benchmarks/scenarios/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .generic_scenario import *
from .deprecated.dataset_scenario import *
from .deprecated.classification_scenario import *
from .deprecated.generic_benchmark_creation import *
from .deprecated.new_classes import *
from .deprecated.new_instances import *

Expand Down
16 changes: 7 additions & 9 deletions avalanche/benchmarks/scenarios/dataset_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,12 @@ def __init__(
self, *, dataset: TCLDataset, current_experience: Optional[int] = None
):
super().__init__(current_experience=current_experience, origin_stream=None)
self._dataset: AvalancheDataset = dataset
self._dataset = dataset

@property
def dataset(self) -> AvalancheDataset:
def dataset(self) -> TCLDataset:
# dataset is a read-only property
data = self._dataset
return data
return self._dataset


def _split_dataset_by_attribute(
Expand All @@ -101,9 +100,9 @@ def _split_dataset_by_attribute(
def split_validation_random(
validation_size: Union[int, float],
shuffle: bool,
dataset: TCLDataset,
seed: Optional[int] = None,
dataset: Optional[AvalancheDataset] = None,
) -> Tuple[AvalancheDataset, AvalancheDataset]:
) -> Tuple[TCLDataset, TCLDataset]:
"""Splits an `AvalancheDataset` in two splits.

The default splitting strategy used by
Expand All @@ -119,7 +118,7 @@ def split_validation_random(
a single parameter: the experience. Consider wrapping your custom
splitting strategy with `partial` if more parameters are needed.

You can use this split strategy with methdos that require a custom
You can use this split strategy with methods that require a custom
split strategy such as :func:`benchmark_with_validation_stream`to split
a benchmark with::

Expand All @@ -133,11 +132,10 @@ def split_validation_random(
Otherwise, the first instances will be allocated to the training
dataset by leaving the last ones to the validation dataset.
:param dataset: The dataset to split.
:param seed: The random seed for shuffling the dataset.
:return: A tuple containing 2 elements: the new training and validation
datasets.
"""
if dataset is None:
raise ValueError("dataset must be provided")
exp_indices = list(range(len(dataset)))

if seed is None:
Expand Down
1 change: 1 addition & 0 deletions avalanche/benchmarks/scenarios/deprecated/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
TCLDataset = TypeVar("TCLDataset", bound="AvalancheDataset")


# TODO: Nomenclature: experience vs task
def nc_benchmark(
train_dataset: Union[Sequence[SupportedDataset], SupportedDataset],
test_dataset: Union[Sequence[SupportedDataset], SupportedDataset],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

from avalanche.benchmarks.utils.classification_dataset import (
_make_taskaware_tensor_classification_dataset,
_make_taskaware_classification_dataset,
_make_taskaware_classification_dataset, ClassificationDataset,
)

from avalanche.benchmarks.utils import (
Expand Down Expand Up @@ -197,7 +197,7 @@ class LazyStreamDefinition(NamedTuple):
This class is a named tuple containing the fields required for defining
a lazily-created benchmark.

- exps_generator: The experiences generator. Can be a "yield"-based
- exps_generator: The experience's generator. Can be a "yield"-based
generator, a custom sequence, a standard list or any kind of
iterable returning :class:`AvalancheDataset`.
- stream_length: The number of experiences in the stream. Must match the
Expand All @@ -207,7 +207,7 @@ class LazyStreamDefinition(NamedTuple):
can be used.
"""

exps_generator: Iterable[TaskAwareClassificationDataset]
exps_generator: Iterable[ClassificationDataset]
"""
The experiences generator. Can be a "yield"-based generator, a custom
sequence, a standard list or any kind of iterable returning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ class NCExperience(ClassificationExperience[TaskAwareSupervisedClassificationDat
def __init__(self, origin_stream: NCStream, current_experience: int):
"""
Creates a ``NCExperience`` instance given the stream from this
experience was taken and and the current experience ID.
experience was taken and the current experience ID.

:param origin_stream: The stream from which this experience was
obtained.
Expand Down
15 changes: 11 additions & 4 deletions avalanche/benchmarks/scenarios/generic_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
slice_alike_object_to_indices,
)


# Typing
T = TypeVar("T")
TCov = TypeVar("TCov", covariant=True)
Expand Down Expand Up @@ -275,6 +274,7 @@ def _check_unset_attribute(attribute_name: str, attribute_value: Any):
)


# TODO: itertools.cycle?
class GeneratorMemo(Generic[T]):
def __init__(self, generator: Generator[T, None, None]):
self._generator: Optional[Generator[T, None, None]] = generator
Expand Down Expand Up @@ -386,7 +386,7 @@ def __len__(self) -> int:

:return: The number of experiences in this stream.
"""
pass
...


class SequenceCLStream(SizedCLStream[TCLExperience], Sequence[TCLExperience], ABC):
Expand Down Expand Up @@ -590,6 +590,13 @@ class CLScenario(Generic[TCLStream]):
provide access to past, current, and future data.
"""

# Define usual empty streams for typing
# TODO: If regarded unnecessary, the constructor magic should be removed
# and `scenario.streams['train']` yields the correct type
train_stream = CLStream('train', [])
test_stream = CLStream('test', [])
valid_stream = CLStream('valid', [])

def __init__(self, streams: Iterable[TCLStream]):
"""Creates an instance of a Continual Learning benchmark.

Expand All @@ -603,7 +610,7 @@ def __init__(self, streams: Iterable[TCLStream]):

@property
def streams(self):
# we don't want in-place modifications so we return a copy
# we don't want in-place modifications, so we return a copy
return copy(self._streams)


Expand All @@ -612,7 +619,7 @@ def make_stream(name: str, exps: Iterable[CLExperience]) -> CLStream:

Uses the correct class for generators, sized generators, and lists.

:param new_name: The name of the new stream.
:param name: The name of the new stream.
:param exps: sequence of experiences.
"""
s_wrapped: CLStream
Expand Down
1 change: 1 addition & 0 deletions avalanche/benchmarks/scenarios/online.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class CyclicSampler(Sampler):
"""Samples elements from [0,..,len(dataset)-1] in a cyclic manner."""

def __init__(self, n_samples, shuffle=True, rng=None):
super().__init__()
self.n_samples = n_samples
self.rng = rng
self.shuffle = shuffle
Expand Down
24 changes: 10 additions & 14 deletions avalanche/benchmarks/scenarios/supervised.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

"""High-level benchmark generators for supervised scenarios such as class-incremental."""
import warnings
from collections.abc import Collection
from copy import copy
from typing import (
Iterable,
Expand All @@ -22,6 +23,7 @@
)

import torch
from typing_extensions import Self

from avalanche.benchmarks.utils.classification_dataset import (
ClassificationDataset,
Expand All @@ -30,7 +32,7 @@
from avalanche.benchmarks.utils.data import AvalancheDataset
from avalanche.benchmarks.utils.data_attribute import DataAttribute
from .dataset_scenario import _split_dataset_by_attribute, DatasetExperience
from .generic_scenario import CLScenario, CLStream, EagerCLStream
from .generic_scenario import CLScenario, CLStream, EagerCLStream, CLExperience


def class_incremental_benchmark(
Expand All @@ -40,7 +42,7 @@ def class_incremental_benchmark(
num_experiences: Optional[int] = None,
num_classes_per_exp: Optional[Sequence[int]] = None,
seed: Optional[int] = None,
) -> CLScenario:
) -> CLScenario[EagerCLStream[DatasetExperience[ClassificationDataset]]]:
"""Splits datasets according to a class-incremental scenario.

Each dataset will create a stream with the same class order.
Expand Down Expand Up @@ -103,14 +105,14 @@ def class_incremental_benchmark(
classes_exp_assignment = []
if num_experiences is not None:
assert num_classes_per_exp is None, "BUG: num_classes_per_exp must be None"
curr_classess_per_exp: int = num_classes // num_experiences
curr_classes_per_exp: int = num_classes // num_experiences
for eid in range(num_experiences):
if eid == 0:
classes_exp_assignment.append(class_order[:curr_classess_per_exp])
classes_exp_assignment.append(class_order[:curr_classes_per_exp])
else:
# final exp will take reminder of classes if they don't divide equally
start_idx = curr_classess_per_exp * eid
end_idx = start_idx + curr_classess_per_exp
start_idx = curr_classes_per_exp * eid
end_idx = start_idx + curr_classes_per_exp
classes_exp_assignment.append(class_order[start_idx:end_idx])
elif num_classes_per_exp is not None:
num_curr = 0
Expand All @@ -120,7 +122,7 @@ def class_incremental_benchmark(
num_curr += num_classes

# create the streams using class_order to split the data
streams = []
streams: List[EagerCLStream[DatasetExperience[ClassificationDataset]]] = []
for name, dd in datasets_dict.items():
curr_stream = []
data_by_class = _split_dataset_by_attribute(dd, "targets")
Expand Down Expand Up @@ -339,12 +341,6 @@ def new_instances_benchmark(
return CLScenario(streams=[train_stream, test_stream])


__all__ = [
"class_incremental_benchmark",
"new_instances_benchmark",
]


class ClassesTimeline(Protocol):
"""Experience decorator that provides info about classes occurrence over time."""

Expand Down Expand Up @@ -381,7 +377,7 @@ def _decorate_benchmark(obj: CLScenario):
new_streams.append(_decorate_stream(s))
return CLScenario(new_streams)

def _decorate_stream(obj: CLStream):
def _decorate_stream(obj: CLStream[DatasetExperience[ClassificationDataset]]):
# TODO: support stream generators. Should return a new generators which applies
# foo_decorate_exp every time a new experience is generated.
new_stream = []
Expand Down
2 changes: 1 addition & 1 deletion avalanche/benchmarks/scenarios/task_aware.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def task_incremental_benchmark(bm: CLScenario, reset_task_labels=False) -> CLSce

with_task_labels(benchmark_from_datasets(**dataset_streams)

:param **dataset_streams: keys are stream names, values are list of datasets.
:param dataset_streams: keys are stream names, values are list of datasets.
:param reset_task_labels: whether existing task labels should be ignored.
If False (default) if any dataset has task labels the function will raise
a ValueError. If `True`, it will reset task labels.
Expand Down
2 changes: 1 addition & 1 deletion avalanche/benchmarks/scenarios/validation_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def benchmark_with_validation_stream(
# functools.partial is a more compact option
# However, MyPy does not understand what a partial is -_-
def random_validation_split_strategy_wrapper(data):
return split_validation_random(validation_size, shuffle, seed, data)
return split_validation_random(validation_size, shuffle, data, seed)

split_strategy = random_validation_split_strategy_wrapper
else:
Expand Down
Loading