aucurriculum 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. aucurriculum-0.1.0/LICENSE +21 -0
  2. aucurriculum-0.1.0/PKG-INFO +58 -0
  3. aucurriculum-0.1.0/README.md +34 -0
  4. aucurriculum-0.1.0/aucurriculum/__init__.py +36 -0
  5. aucurriculum-0.1.0/aucurriculum/cli/__init__.py +33 -0
  6. aucurriculum-0.1.0/aucurriculum/core/__init__.py +0 -0
  7. aucurriculum-0.1.0/aucurriculum/core/constants/__init__.py +4 -0
  8. aucurriculum-0.1.0/aucurriculum/core/constants/curriculum_constants.py +26 -0
  9. aucurriculum-0.1.0/aucurriculum/core/filters/__init__.py +4 -0
  10. aucurriculum-0.1.0/aucurriculum/core/filters/filters.py +45 -0
  11. aucurriculum-0.1.0/aucurriculum/core/plotting/__init__.py +4 -0
  12. aucurriculum-0.1.0/aucurriculum/core/plotting/plot_curriculum.py +274 -0
  13. aucurriculum-0.1.0/aucurriculum/core/scripts/__init__.py +28 -0
  14. aucurriculum-0.1.0/aucurriculum/core/scripts/cli.py +79 -0
  15. aucurriculum-0.1.0/aucurriculum/core/scripts/cli_wrapper.py +96 -0
  16. aucurriculum-0.1.0/aucurriculum/core/scripts/create_script.py +77 -0
  17. aucurriculum-0.1.0/aucurriculum/core/scripts/curriculum_script.py +88 -0
  18. aucurriculum-0.1.0/aucurriculum/core/scripts/group_script.py +69 -0
  19. aucurriculum-0.1.0/aucurriculum/core/scripts/list_script.py +50 -0
  20. aucurriculum-0.1.0/aucurriculum/core/scripts/postprocess_script.py +74 -0
  21. aucurriculum-0.1.0/aucurriculum/core/scripts/show_script.py +55 -0
  22. aucurriculum-0.1.0/aucurriculum/core/scripts/train_script.py +99 -0
  23. aucurriculum-0.1.0/aucurriculum/core/wrappers/__init__.py +4 -0
  24. aucurriculum-0.1.0/aucurriculum/core/wrappers/main.py +65 -0
  25. aucurriculum-0.1.0/aucurriculum/curricula/__init__.py +8 -0
  26. aucurriculum-0.1.0/aucurriculum/curricula/curriculum_pace_manager.py +232 -0
  27. aucurriculum-0.1.0/aucurriculum/curricula/curriculum_score_manager.py +168 -0
  28. aucurriculum-0.1.0/aucurriculum/curricula/pacing/__init__.py +17 -0
  29. aucurriculum-0.1.0/aucurriculum/curricula/pacing/abstract_pace.py +49 -0
  30. aucurriculum-0.1.0/aucurriculum/curricula/pacing/exponential.py +53 -0
  31. aucurriculum-0.1.0/aucurriculum/curricula/pacing/logarithmic.py +54 -0
  32. aucurriculum-0.1.0/aucurriculum/curricula/pacing/one_step.py +48 -0
  33. aucurriculum-0.1.0/aucurriculum/curricula/pacing/polynomial.py +149 -0
  34. aucurriculum-0.1.0/aucurriculum/curricula/scoring/__init__.py +22 -0
  35. aucurriculum-0.1.0/aucurriculum/curricula/scoring/abstract_score.py +455 -0
  36. aucurriculum-0.1.0/aucurriculum/curricula/scoring/ce_loss.py +79 -0
  37. aucurriculum-0.1.0/aucurriculum/curricula/scoring/cumulative_accuracy.py +186 -0
  38. aucurriculum-0.1.0/aucurriculum/curricula/scoring/cv_loss.py +293 -0
  39. aucurriculum-0.1.0/aucurriculum/curricula/scoring/first_iteration.py +176 -0
  40. aucurriculum-0.1.0/aucurriculum/curricula/scoring/predefined_score.py +82 -0
  41. aucurriculum-0.1.0/aucurriculum/curricula/scoring/prediction_depth.py +360 -0
  42. aucurriculum-0.1.0/aucurriculum/curricula/scoring/random_score.py +72 -0
  43. aucurriculum-0.1.0/aucurriculum/curricula/scoring/transfer_teacher.py +153 -0
  44. aucurriculum-0.1.0/aucurriculum/curricula/scoring/utils.py +179 -0
  45. aucurriculum-0.1.0/aucurriculum/postprocessing/__init__.py +10 -0
  46. aucurriculum-0.1.0/aucurriculum/postprocessing/aggregate.py +68 -0
  47. aucurriculum-0.1.0/aucurriculum/postprocessing/group.py +52 -0
  48. aucurriculum-0.1.0/aucurriculum/postprocessing/summarize_curriculum.py +127 -0
  49. aucurriculum-0.1.0/aucurriculum-configurations/_aucurriculum_score_.yaml +15 -0
  50. aucurriculum-0.1.0/aucurriculum-configurations/_aucurriculum_train_.yaml +46 -0
  51. aucurriculum-0.1.0/aucurriculum-configurations/config.yaml +23 -0
  52. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/AntiCurriculum.yaml +12 -0
  53. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/Curriculum.yaml +12 -0
  54. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/None.yaml +12 -0
  55. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/Exponential.yaml +4 -0
  56. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/Linear.yaml +4 -0
  57. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/Logarithmic.yaml +4 -0
  58. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/None.yaml +4 -0
  59. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/OneStep.yaml +4 -0
  60. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/Quadratic.yaml +4 -0
  61. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/pacing/Root.yaml +4 -0
  62. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/sampling/Balanced.yaml +2 -0
  63. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/sampling/None.yaml +2 -0
  64. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/sampling/Original.yaml +2 -0
  65. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/sampling/Unbalanced.yaml +2 -0
  66. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/CELoss.yaml +7 -0
  67. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/CVLoss.yaml +26 -0
  68. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/CumulativeAccuracy.yaml +6 -0
  69. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/FirstIteration.yaml +6 -0
  70. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/None.yaml +3 -0
  71. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/Predefined.yaml +8 -0
  72. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/PredictionDepth.yaml +9 -0
  73. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/Random.yaml +6 -0
  74. aucurriculum-0.1.0/aucurriculum-configurations/curriculum/scoring/TransferTeacher.yaml +6 -0
  75. aucurriculum-0.1.0/aucurriculum-configurations/curriculum.yaml +14 -0
  76. aucurriculum-0.1.0/aucurriculum-configurations/hydra/sweeper/aucurriculum_score_sweeper.yaml +6 -0
  77. aucurriculum-0.1.0/aucurriculum-configurations/hydra/sweeper/aucurriculum_train_sweeper.yaml +9 -0
  78. aucurriculum-0.1.0/pyproject.toml +94 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Simon Rampp, Manuel Milling, Andreas Triantafyllopoulos, Björn W. Schuller.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,58 @@
1
+ Metadata-Version: 2.1
2
+ Name: aucurriculum
3
+ Version: 0.1.0
4
+ Summary: A Curriculum Learning Toolkit for Deep Learning Tasks built on top of autrainer.
5
+ Home-page: https://github.com/autrainer/aucurriculum
6
+ License: MIT
7
+ Keywords: curriculum learning,autrainer,computer audition,deep learning,artificial intelligence,pytorch,hydra-core,command-line,yaml
8
+ Author: Simon Rampp
9
+ Author-email: simon.rampp@tum.de
10
+ Requires-Python: >=3.9,<4.0
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Dist: autrainer (==0.4.0)
20
+ Project-URL: Documentation, https://autrainer.github.io/aucurriculum/
21
+ Project-URL: Repository, https://github.com/autrainer/aucurriculum
22
+ Description-Content-Type: text/markdown
23
+
24
+ <div align="center">
25
+ <img src="https://autrainer.github.io/aucurriculum/_images/logo_banner.png" alt="aucurriculum — A Curriculum Learning Toolkit for Deep Learning Tasks built on top of autrainer">
26
+ </div>
27
+
28
+ # aucurriculum
29
+
30
+ [![aucurriculum PyPI Version](https://img.shields.io/pypi/v/aucurriculum?logo=pypi&logoColor=b4befe&color=b4befe)](https://pypi.org/project/aucurriculum/)
31
+ [![aucurriculum Python Versions](https://img.shields.io/pypi/pyversions/aucurriculum?logo=python&logoColor=b4befe&color=b4befe)](https://pypi.org/project/aucurriculum/)
32
+ [![aucurriculum GitHub License](https://img.shields.io/badge/license-MIT-b4befe?logo=c)](https://github.com/autrainer/aucurriculum/blob/main/LICENSE)
33
+
34
+ A Curriculum Learning Toolkit for Deep Learning Tasks built on top of [autrainer](https://github.com/autrainer/autrainer).
35
+
36
+ ## Installation
37
+
38
+ To install _aucurriculum_, first ensure that PyTorch (along with torchvision and torchaudio) version 2.0 or higher is installed.
39
+ For installation instructions, refer to the [PyTorch website](https://pytorch.org/get-started/locally/).
40
+
41
+ It is recommended to install _aucurriculum_ within a virtual environment.
42
+ To create a new virtual environment, refer to the [Python venv documentation](https://docs.python.org/3/library/venv.html).
43
+
44
+ Next, install _aucurriculum_ using _pip_.
45
+
46
+ ```bash
47
+ pip install aucurriculum
48
+ ```
49
+
50
+ To install _aucurriculum_ from source, refer to the [contribution guide](https://autrainer.github.io/aucurriculum/development/contributing.html).
51
+
52
+ ## Next Steps
53
+
54
+ To get started using _aucurriculum_, the [quickstart guide](https://autrainer.github.io/aucurriculum/usage/quickstart.html) outlines the creation of a simple training configuration
55
+ and [tutorials](https://autrainer.github.io/aucurriculum/usage/tutorials.html) provide examples for implementing custom scoring and pacing functions including their configurations.
56
+
57
+ For a complete list of available CLI commands, refer to the [CLI reference](https://autrainer.github.io/aucurriculum/usage/cli_reference.html) or the [CLI wrapper](https://autrainer.github.io/aucurriculum/usage/cli_wrapper.html).
58
+
@@ -0,0 +1,34 @@
1
+ <div align="center">
2
+ <img src="https://autrainer.github.io/aucurriculum/_images/logo_banner.png" alt="aucurriculum — A Curriculum Learning Toolkit for Deep Learning Tasks built on top of autrainer">
3
+ </div>
4
+
5
+ # aucurriculum
6
+
7
+ [![aucurriculum PyPI Version](https://img.shields.io/pypi/v/aucurriculum?logo=pypi&logoColor=b4befe&color=b4befe)](https://pypi.org/project/aucurriculum/)
8
+ [![aucurriculum Python Versions](https://img.shields.io/pypi/pyversions/aucurriculum?logo=python&logoColor=b4befe&color=b4befe)](https://pypi.org/project/aucurriculum/)
9
+ [![aucurriculum GitHub License](https://img.shields.io/badge/license-MIT-b4befe?logo=c)](https://github.com/autrainer/aucurriculum/blob/main/LICENSE)
10
+
11
+ A Curriculum Learning Toolkit for Deep Learning Tasks built on top of [autrainer](https://github.com/autrainer/autrainer).
12
+
13
+ ## Installation
14
+
15
+ To install _aucurriculum_, first ensure that PyTorch (along with torchvision and torchaudio) version 2.0 or higher is installed.
16
+ For installation instructions, refer to the [PyTorch website](https://pytorch.org/get-started/locally/).
17
+
18
+ It is recommended to install _aucurriculum_ within a virtual environment.
19
+ To create a new virtual environment, refer to the [Python venv documentation](https://docs.python.org/3/library/venv.html).
20
+
21
+ Next, install _aucurriculum_ using _pip_.
22
+
23
+ ```bash
24
+ pip install aucurriculum
25
+ ```
26
+
27
+ To install _aucurriculum_ from source, refer to the [contribution guide](https://autrainer.github.io/aucurriculum/development/contributing.html).
28
+
29
+ ## Next Steps
30
+
31
+ To get started using _aucurriculum_, the [quickstart guide](https://autrainer.github.io/aucurriculum/usage/quickstart.html) outlines the creation of a simple training configuration
32
+ and [tutorials](https://autrainer.github.io/aucurriculum/usage/tutorials.html) provide examples for implementing custom scoring and pacing functions including their configurations.
33
+
34
+ For a complete list of available CLI commands, refer to the [CLI reference](https://autrainer.github.io/aucurriculum/usage/cli_reference.html) or the [CLI wrapper](https://autrainer.github.io/aucurriculum/usage/cli_wrapper.html).
@@ -0,0 +1,36 @@
1
+ from autrainer.core.constants import (
2
+ ExportConstants,
3
+ NamingConstants,
4
+ )
5
+
6
+ from aucurriculum.core.constants import CurriculumConstants
7
+ from aucurriculum.core.wrappers import main
8
+
9
+
10
+ # always overlay the autrainer constants
11
+ NamingConstants().CONFIG_DIRS = (
12
+ NamingConstants().CONFIG_DIRS + CurriculumConstants().CONFIG_DIRS
13
+ )
14
+ NamingConstants().NAMING_CONVENTION = NamingConstants().NAMING_CONVENTION[
15
+ :-1
16
+ ] + [
17
+ "curriculum",
18
+ "curriculum.sampling",
19
+ "curriculum.scoring",
20
+ "curriculum.pacing",
21
+ "curriculum.pacing.initial_size",
22
+ "curriculum.pacing.final_iteration",
23
+ "seed",
24
+ ]
25
+ NamingConstants().VALID_AGGREGATIONS = list(
26
+ set(NamingConstants().NAMING_CONVENTION)
27
+ - set(NamingConstants().INVALID_AGGREGATIONS)
28
+ )
29
+ ExportConstants().LOGGING_DEPTH = 3
30
+ ExportConstants().IGNORE_PARAMS = ExportConstants().IGNORE_PARAMS + [
31
+ "curriculum.short",
32
+ "curriculum.sampling.short",
33
+ ]
34
+
35
+ __version__ = "0.1.0"
36
+ __all__ = ["main"]
@@ -0,0 +1,33 @@
1
+ from autrainer.core.scripts import (
2
+ inference,
3
+ rm_failed,
4
+ rm_states,
5
+ )
6
+
7
+ from aucurriculum.core.scripts import (
8
+ create,
9
+ curriculum,
10
+ fetch,
11
+ group,
12
+ postprocess,
13
+ preprocess,
14
+ show,
15
+ train,
16
+ )
17
+ from aucurriculum.core.scripts import list_configs as list
18
+
19
+
20
+ __all__ = [
21
+ "create",
22
+ "curriculum",
23
+ "fetch",
24
+ "group",
25
+ "inference",
26
+ "list",
27
+ "postprocess",
28
+ "preprocess",
29
+ "rm_failed",
30
+ "rm_states",
31
+ "show",
32
+ "train",
33
+ ]
File without changes
@@ -0,0 +1,4 @@
1
+ from .curriculum_constants import CurriculumConstants
2
+
3
+
4
+ __all__ = ["CurriculumConstants"]
@@ -0,0 +1,26 @@
1
+ from typing import List
2
+
3
+ from autrainer.core.constants import AbstractConstants
4
+
5
+
6
+ class CurriculumConstants(AbstractConstants):
7
+ """Singleton for managing the curriculum configurations of
8
+ `aucurriculum`."""
9
+
10
+ _config_dirs = [
11
+ "curriculum",
12
+ "curriculum/pacing",
13
+ "curriculum/sampling",
14
+ "curriculum/scoring",
15
+ ]
16
+
17
+ @property
18
+ def CONFIG_DIRS(self) -> List[str]:
19
+ """Get the curriculum configuration directories for Hydra
20
+ configurations. Defaults to :attr:`["curriculum", "curriculum/pacing",
21
+ "curriculum/sampling", "curriculum/scoring"]`.
22
+
23
+ Returns:
24
+ Curriculum configuration directories for Hydra configurations.
25
+ """
26
+ return self._config_dirs
@@ -0,0 +1,4 @@
1
+ from .filters import FilterPartialCurriculum, FilterPlaceholderScoringFunction
2
+
3
+
4
+ __all__ = ["FilterPartialCurriculum", "FilterPlaceholderScoringFunction"]
@@ -0,0 +1,45 @@
1
+ from hydra_filter_sweeper import AbstractFilter
2
+ from omegaconf import DictConfig
3
+
4
+
5
+ class FilterPlaceholderScoringFunction(AbstractFilter): # pragma: no cover
6
+ def filter(self, config: DictConfig, directory: str) -> bool:
7
+ """Filter out run configurations with placeholder (None) scoring
8
+ functions.
9
+
10
+ Args:
11
+ config: Run configuration.
12
+ directory: Directory where the run configuration is stored.
13
+
14
+ Returns:
15
+ Whether to filter out the run configuration.
16
+ """
17
+ return config.curriculum.scoring.id == "None"
18
+
19
+
20
+ class FilterPartialCurriculum(AbstractFilter): # pragma: no cover
21
+ def filter(self, config: DictConfig, directory: str) -> bool:
22
+ """Filter out run configurations with partial curricula.
23
+ A partial curriculum is one where the id is not "None" but one or more
24
+ of the sampling, scoring, and pacing ids are "None".
25
+
26
+ Args:
27
+ config: Run configuration.
28
+ directory: Directory where the run configuration is stored.
29
+
30
+ Returns:
31
+ Whether to filter out the run configuration.
32
+ """
33
+ c = config.curriculum
34
+ if c.id == "None":
35
+ if any(
36
+ id != "None"
37
+ for id in [c.sampling.id, c.scoring.id, c.pacing.id]
38
+ ):
39
+ return True
40
+ return False
41
+ if any(
42
+ id == "None" for id in [c.sampling.id, c.scoring.id, c.pacing.id]
43
+ ):
44
+ return True
45
+ return False
@@ -0,0 +1,4 @@
1
+ from .plot_curriculum import CurriculumPlots
2
+
3
+
4
+ __all__ = ["CurriculumPlots"]
@@ -0,0 +1,274 @@
1
+ import os
2
+ import warnings
3
+
4
+ from autrainer.core.plotting import PlotBase
5
+ import matplotlib.pyplot as plt
6
+ import numpy as np
7
+ import pandas as pd
8
+ import seaborn as sns
9
+
10
+
11
+ class CurriculumPlots(PlotBase):
12
+ def __init__(
13
+ self,
14
+ output_directory: str,
15
+ training_type: str,
16
+ figsize: tuple,
17
+ latex: bool,
18
+ filetypes: list,
19
+ pickle: bool,
20
+ context: str,
21
+ palette: str,
22
+ replace_none: bool,
23
+ add_titles: bool,
24
+ add_xlabels: bool,
25
+ add_ylabels: bool,
26
+ rcParams: dict,
27
+ ) -> None:
28
+ """Plot the sample difficulty scores and pace of curricula.
29
+
30
+ Args:
31
+ output_directory: Output directory to save plots to.
32
+ training_type: Type of training in ["Epoch", "Step"].
33
+ figsize: Figure size in inches.
34
+ latex: Whether to use LaTeX in plots. Requires the `latex` package.
35
+ To install all necessary dependencies, run:
36
+ `pip install autrainer[latex]`.
37
+ filetypes: Filetypes to save plots as.
38
+ pickle: Whether to save additional pickle files of the plots.
39
+ context: Context for seaborn plots.
40
+ palette: Color palette for seaborn plots.
41
+ replace_none: Whether to replace "None" in labels with "~".
42
+ add_titles: Whether to add titles to plots.
43
+ add_xlabels: Whether to add x-labels to plots.
44
+ add_ylabels: Whether to add y-labels to plots.
45
+ rcParams: Additional Matplotlib rcParams to set.
46
+ """
47
+ super().__init__(
48
+ output_directory,
49
+ training_type,
50
+ figsize,
51
+ latex,
52
+ filetypes,
53
+ pickle,
54
+ context,
55
+ palette,
56
+ replace_none,
57
+ add_titles,
58
+ add_xlabels,
59
+ add_ylabels,
60
+ rcParams,
61
+ )
62
+
63
+ def plot_score(self, df: pd.DataFrame, score_id: str, num_bins=20) -> None:
64
+ """Plot the sample difficulty scores by creating histograms,
65
+ facet grids, and ridge plots visualizing the global and per class
66
+ sample difficulty distributions.
67
+
68
+ Args:
69
+ df: DataFrame containing the sample difficulty scores ("mean",
70
+ "ranks") and corresponding labels ("decoded").
71
+ score_id: ID of the scoring function.
72
+ num_bins: Number of bins for the histogram. Defaults to 20.
73
+ """
74
+ df["decoded"] = df["decoded"].astype(str)
75
+ order = sorted(df["decoded"].unique())
76
+ sample_counts = df["decoded"].value_counts().sort_index().values
77
+
78
+ self._plot_fn(
79
+ df=df,
80
+ score_id=score_id,
81
+ name="histogram",
82
+ x="mean",
83
+ y_label="count",
84
+ fn=sns.histplot,
85
+ fn_kargs={"bins": num_bins},
86
+ )
87
+ self._plot_facet_grid(
88
+ df=df,
89
+ score_id=score_id,
90
+ name="Count per Class",
91
+ y_label="count",
92
+ fn_map=sns.histplot,
93
+ fn_kargs={
94
+ "bins": np.arange(0, 1 + (1 / num_bins), 1 / num_bins),
95
+ "stat": "count",
96
+ },
97
+ col_order=order,
98
+ )
99
+ percent_char = "\\%" if self.latex else "%"
100
+ self._plot_facet_grid(
101
+ df=df,
102
+ score_id=score_id,
103
+ name="Percent per Class",
104
+ y_label=f"ratio [{percent_char}]",
105
+ fn_map=sns.histplot,
106
+ fn_kargs={
107
+ "bins": np.arange(0, 1 + (1 / num_bins), 1 / num_bins),
108
+ "stat": "percent",
109
+ },
110
+ col_order=order,
111
+ sample_counts=sample_counts,
112
+ )
113
+ self._plot_ridge(
114
+ df=df, score_id=score_id, name="Ridge per Class", row_order=order
115
+ )
116
+
117
+ def _plot_facet_grid(
118
+ self,
119
+ df: pd.DataFrame,
120
+ score_id: str,
121
+ name: str,
122
+ y_label: str,
123
+ fn_map: callable,
124
+ fn_kargs: dict,
125
+ col_order: list = None,
126
+ sample_counts: list = None,
127
+ ) -> None:
128
+ fg = sns.FacetGrid(
129
+ df,
130
+ col="decoded",
131
+ col_order=col_order,
132
+ hue="decoded",
133
+ col_wrap=5,
134
+ height=self.figsize[1] / 2,
135
+ aspect=self.figsize[0] / (self.figsize[1] * 2),
136
+ )
137
+ fg.set_titles(col_template="{col_name}")
138
+ if sample_counts is not None:
139
+ for ax, ct in zip(fg.axes.flat, sample_counts):
140
+ ax.set_title(f"{ax.get_title()} ({ct} samples)")
141
+ fg.map_dataframe(fn_map, x="ranks", **fn_kargs)
142
+ if self.add_xlabels:
143
+ fg.set_xlabels("ranks")
144
+ else:
145
+ fg.set_xlabels("")
146
+ if self.add_ylabels:
147
+ fg.set_ylabels(y_label)
148
+ else:
149
+ fg.set_ylabels("")
150
+ if self.add_titles:
151
+ fg.figure.suptitle(f"{score_id} {name}", y=0.975)
152
+ else:
153
+ fg.figure.suptitle("")
154
+ path = os.path.join("_plots", score_id)
155
+ self.save_plot(fg.figure, name.lower().replace(" ", "_"), path)
156
+
157
+ def _plot_fn(
158
+ self,
159
+ df: pd.DataFrame,
160
+ score_id: str,
161
+ name: str,
162
+ x: str,
163
+ y_label: str,
164
+ fn: callable,
165
+ fn_kargs: dict,
166
+ ) -> None:
167
+ fig = plt.figure(figsize=self.figsize)
168
+ fn(data=df, x=x, **fn_kargs)
169
+ self._add_label(fig.gca(), x, y_label)
170
+ path = os.path.join("_plots", score_id)
171
+ self.save_plot(fig, name.lower().replace(" ", "_"), path)
172
+
173
+ def _plot_ridge(
174
+ self, df: pd.DataFrame, score_id: str, name: str, row_order: list
175
+ ) -> None:
176
+ _old_warn = warnings.filters[:]
177
+ warnings.filterwarnings("ignore", category=UserWarning)
178
+ height = (self.figsize[1] / 10) * 1.25
179
+ fg = sns.FacetGrid(
180
+ df,
181
+ row="decoded",
182
+ row_order=row_order,
183
+ hue="decoded",
184
+ height=height,
185
+ aspect=(self.figsize[0] * 1.25) / height,
186
+ )
187
+ fg.map_dataframe(
188
+ sns.kdeplot,
189
+ x="ranks",
190
+ bw_adjust=0.5,
191
+ fill=True,
192
+ )
193
+ for ax in fg.axes.flat:
194
+ ax.patch.set_facecolor("none")
195
+ ax.xaxis.grid(False)
196
+ fg.set_titles("")
197
+ fg.set(yticks=[], ylabel="")
198
+
199
+ def label(x, color, label):
200
+ ax = plt.gca()
201
+ ax.text(
202
+ x=0.04,
203
+ y=0,
204
+ s=label,
205
+ ha="right",
206
+ va="bottom",
207
+ transform=ax.transAxes,
208
+ )
209
+
210
+ fg.map(label, "ranks")
211
+ fg.despine(left=True)
212
+ if self.add_titles:
213
+ fg.figure.suptitle(f"{score_id} {name}", y=0.975)
214
+ else:
215
+ fg.figure.suptitle("")
216
+
217
+ path = os.path.join("_plots", score_id)
218
+ self.save_plot(fg.figure, name.lower().replace(" ", "_"), path)
219
+ warnings.filters = _old_warn
220
+
221
+ def plot_correlation_matrix(self, df: pd.DataFrame, name: str) -> None:
222
+ """Create and plot the correlation matrix of the scoring functions.
223
+
224
+ Args:
225
+ df: DataFrame containing multiple scoring functions per column.
226
+ name: Name of the correlation matrix plot.
227
+ """
228
+ df.sort_index(axis="columns", inplace=True)
229
+ fig_height = int(1 + len(df.columns))
230
+ fig = plt.figure(
231
+ figsize=(max(self.figsize[0], fig_height), fig_height)
232
+ )
233
+ correlation_matrix = df.corr(method="spearman")
234
+ correlation_matrix.to_csv(
235
+ os.path.join(self.output_directory, f"{name}.csv")
236
+ )
237
+ percent_char = "\\%" if self.latex else "%"
238
+
239
+ def escape_percent(x):
240
+ return f"{(x*100):.2f}{percent_char}"
241
+
242
+ sns.heatmap(
243
+ correlation_matrix,
244
+ annot=correlation_matrix.map(escape_percent),
245
+ fmt="",
246
+ cbar=False,
247
+ cmap="crest",
248
+ )
249
+ fig.gca().set_xticklabels(df.columns, rotation=25)
250
+ self.save_plot(fig, name)
251
+
252
+ def plot_run(self, df: pd.DataFrame) -> None:
253
+ """Plot the dynamic dataset size determined by the curriculum.
254
+
255
+ Args:
256
+ df: DataFrame containing the run metrics and dataset sizes.
257
+ """
258
+ fig = plt.figure(figsize=self.figsize)
259
+ sns.lineplot(
260
+ data=df["dataset_size"], dashes=False, drawstyle="steps-post"
261
+ )
262
+ self._add_label(fig.gca(), self.training_type, "dataset size")
263
+ self.save_plot(fig, "pace")
264
+
265
+ def plot_pace(self, df: pd.DataFrame) -> None:
266
+ """Plot the dynamic dataset size of multiple runs.
267
+
268
+ Args:
269
+ df: DataFrame containing multiple runs and their dataset sizes.
270
+ """
271
+ fig = plt.figure(figsize=self.figsize)
272
+ sns.lineplot(data=df, dashes=False, drawstyle="steps-post")
273
+ self._add_label(fig.gca(), self.training_type, "dataset size")
274
+ self.save_plot(fig, "pace")
@@ -0,0 +1,28 @@
1
+ from .cli_wrapper import fetch, preprocess
2
+ from .create_script import CreateCurriculumScript, create
3
+ from .curriculum_script import CurriculumScript, curriculum
4
+ from .group_script import GroupCurriculumScript, group
5
+ from .list_script import ListCurriculumScript, list_configs
6
+ from .postprocess_script import PostprocessCurriculumScript, postprocess
7
+ from .show_script import ShowCurriculumScript, show
8
+ from .train_script import TrainCurriculumScript, train
9
+
10
+
11
+ __all__ = [
12
+ "create",
13
+ "CreateCurriculumScript",
14
+ "curriculum",
15
+ "CurriculumScript",
16
+ "fetch",
17
+ "group",
18
+ "GroupCurriculumScript",
19
+ "list_configs",
20
+ "ListCurriculumScript",
21
+ "postprocess",
22
+ "PostprocessCurriculumScript",
23
+ "preprocess",
24
+ "show",
25
+ "ShowCurriculumScript",
26
+ "train",
27
+ "TrainCurriculumScript",
28
+ ]
@@ -0,0 +1,79 @@
1
+ import argparse
2
+ from typing import List
3
+
4
+ from autrainer.core.scripts import (
5
+ AbstractScript,
6
+ CommandLineError,
7
+ DeleteFailedScript,
8
+ DeleteStatesScript,
9
+ FetchScript,
10
+ InferenceScript,
11
+ PreprocessScript,
12
+ )
13
+ from autrainer.core.scripts.cli import CLI as AutrainerCLI
14
+
15
+ import aucurriculum
16
+ from aucurriculum.core.scripts import (
17
+ CreateCurriculumScript,
18
+ CurriculumScript,
19
+ GroupCurriculumScript,
20
+ ListCurriculumScript,
21
+ PostprocessCurriculumScript,
22
+ ShowCurriculumScript,
23
+ TrainCurriculumScript,
24
+ )
25
+
26
+
27
+ class CLI(AutrainerCLI):
28
+ def __init__(self) -> None:
29
+ super().__init__()
30
+ self._update_metadata()
31
+
32
+ def _init_scripts(self) -> List[AbstractScript]:
33
+ return [
34
+ # configuration management
35
+ CreateCurriculumScript(),
36
+ ListCurriculumScript(),
37
+ ShowCurriculumScript(),
38
+ # preprocessing
39
+ FetchScript(),
40
+ PreprocessScript(),
41
+ # training
42
+ TrainCurriculumScript(),
43
+ # inference
44
+ InferenceScript(),
45
+ # postprocessing
46
+ PostprocessCurriculumScript(),
47
+ DeleteFailedScript(),
48
+ DeleteStatesScript(),
49
+ GroupCurriculumScript(),
50
+ # curriculum learning
51
+ CurriculumScript(),
52
+ ]
53
+
54
+ def _update_metadata(self) -> None:
55
+ self.parser.prog = "aucurriculum"
56
+ self.parser.description = (
57
+ "A Curriculum Learning Toolkit for Deep Learning Tasks "
58
+ "built on top of autrainer."
59
+ )
60
+ for action in self.parser._actions:
61
+ if isinstance(action, argparse._VersionAction):
62
+ action.version = f"%(prog)s {aucurriculum.__version__}"
63
+
64
+
65
+ def main() -> None:
66
+ cli = CLI()
67
+ try:
68
+ cli.main()
69
+ except CommandLineError as e:
70
+ e.handle()
71
+
72
+
73
+ def get_parser() -> argparse.ArgumentParser:
74
+ cli = CLI() # pragma: no cover
75
+ return cli.parser # pragma: no cover
76
+
77
+
78
+ if __name__ == "__main__":
79
+ main()