aucurriculum 0.1.0__py3-none-any.whl
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.
- aucurriculum/__init__.py +36 -0
- aucurriculum/cli/__init__.py +33 -0
- aucurriculum/core/__init__.py +0 -0
- aucurriculum/core/constants/__init__.py +4 -0
- aucurriculum/core/constants/curriculum_constants.py +26 -0
- aucurriculum/core/filters/__init__.py +4 -0
- aucurriculum/core/filters/filters.py +45 -0
- aucurriculum/core/plotting/__init__.py +4 -0
- aucurriculum/core/plotting/plot_curriculum.py +274 -0
- aucurriculum/core/scripts/__init__.py +28 -0
- aucurriculum/core/scripts/cli.py +79 -0
- aucurriculum/core/scripts/cli_wrapper.py +96 -0
- aucurriculum/core/scripts/create_script.py +77 -0
- aucurriculum/core/scripts/curriculum_script.py +88 -0
- aucurriculum/core/scripts/group_script.py +69 -0
- aucurriculum/core/scripts/list_script.py +50 -0
- aucurriculum/core/scripts/postprocess_script.py +74 -0
- aucurriculum/core/scripts/show_script.py +55 -0
- aucurriculum/core/scripts/train_script.py +99 -0
- aucurriculum/core/wrappers/__init__.py +4 -0
- aucurriculum/core/wrappers/main.py +65 -0
- aucurriculum/curricula/__init__.py +8 -0
- aucurriculum/curricula/curriculum_pace_manager.py +232 -0
- aucurriculum/curricula/curriculum_score_manager.py +168 -0
- aucurriculum/curricula/pacing/__init__.py +17 -0
- aucurriculum/curricula/pacing/abstract_pace.py +49 -0
- aucurriculum/curricula/pacing/exponential.py +53 -0
- aucurriculum/curricula/pacing/logarithmic.py +54 -0
- aucurriculum/curricula/pacing/one_step.py +48 -0
- aucurriculum/curricula/pacing/polynomial.py +149 -0
- aucurriculum/curricula/scoring/__init__.py +22 -0
- aucurriculum/curricula/scoring/abstract_score.py +455 -0
- aucurriculum/curricula/scoring/ce_loss.py +79 -0
- aucurriculum/curricula/scoring/cumulative_accuracy.py +186 -0
- aucurriculum/curricula/scoring/cv_loss.py +293 -0
- aucurriculum/curricula/scoring/first_iteration.py +176 -0
- aucurriculum/curricula/scoring/predefined_score.py +82 -0
- aucurriculum/curricula/scoring/prediction_depth.py +360 -0
- aucurriculum/curricula/scoring/random_score.py +72 -0
- aucurriculum/curricula/scoring/transfer_teacher.py +153 -0
- aucurriculum/curricula/scoring/utils.py +179 -0
- aucurriculum/postprocessing/__init__.py +10 -0
- aucurriculum/postprocessing/aggregate.py +68 -0
- aucurriculum/postprocessing/group.py +52 -0
- aucurriculum/postprocessing/summarize_curriculum.py +127 -0
- aucurriculum-0.1.0.dist-info/LICENSE +21 -0
- aucurriculum-0.1.0.dist-info/METADATA +58 -0
- aucurriculum-0.1.0.dist-info/RECORD +79 -0
- aucurriculum-0.1.0.dist-info/WHEEL +4 -0
- aucurriculum-0.1.0.dist-info/entry_points.txt +3 -0
- aucurriculum-configurations/_aucurriculum_score_.yaml +15 -0
- aucurriculum-configurations/_aucurriculum_train_.yaml +46 -0
- aucurriculum-configurations/config.yaml +23 -0
- aucurriculum-configurations/curriculum/AntiCurriculum.yaml +12 -0
- aucurriculum-configurations/curriculum/Curriculum.yaml +12 -0
- aucurriculum-configurations/curriculum/None.yaml +12 -0
- aucurriculum-configurations/curriculum/pacing/Exponential.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/Linear.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/Logarithmic.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/None.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/OneStep.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/Quadratic.yaml +4 -0
- aucurriculum-configurations/curriculum/pacing/Root.yaml +4 -0
- aucurriculum-configurations/curriculum/sampling/Balanced.yaml +2 -0
- aucurriculum-configurations/curriculum/sampling/None.yaml +2 -0
- aucurriculum-configurations/curriculum/sampling/Original.yaml +2 -0
- aucurriculum-configurations/curriculum/sampling/Unbalanced.yaml +2 -0
- aucurriculum-configurations/curriculum/scoring/CELoss.yaml +7 -0
- aucurriculum-configurations/curriculum/scoring/CVLoss.yaml +26 -0
- aucurriculum-configurations/curriculum/scoring/CumulativeAccuracy.yaml +6 -0
- aucurriculum-configurations/curriculum/scoring/FirstIteration.yaml +6 -0
- aucurriculum-configurations/curriculum/scoring/None.yaml +3 -0
- aucurriculum-configurations/curriculum/scoring/Predefined.yaml +8 -0
- aucurriculum-configurations/curriculum/scoring/PredictionDepth.yaml +9 -0
- aucurriculum-configurations/curriculum/scoring/Random.yaml +6 -0
- aucurriculum-configurations/curriculum/scoring/TransferTeacher.yaml +6 -0
- aucurriculum-configurations/curriculum.yaml +14 -0
- aucurriculum-configurations/hydra/sweeper/aucurriculum_score_sweeper.yaml +6 -0
- aucurriculum-configurations/hydra/sweeper/aucurriculum_train_sweeper.yaml +9 -0
aucurriculum/__init__.py
ADDED
|
@@ -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,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,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,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()
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from autrainer.core.scripts import FetchScript, PreprocessScript
|
|
4
|
+
from autrainer.core.scripts.abstract_script import MockParser
|
|
5
|
+
from autrainer.core.scripts.fetch_script import PreprocessArgs as FetchArgs
|
|
6
|
+
from autrainer.core.scripts.preprocess_script import PreprocessArgs
|
|
7
|
+
from autrainer.core.scripts.utils import (
|
|
8
|
+
add_hydra_args_to_sys,
|
|
9
|
+
catch_cli_errors,
|
|
10
|
+
run_hydra_cmd,
|
|
11
|
+
running_in_notebook,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@catch_cli_errors
|
|
16
|
+
def fetch(
|
|
17
|
+
override_kwargs: Optional[dict] = None,
|
|
18
|
+
cfg_launcher: bool = False,
|
|
19
|
+
config_name: str = "config",
|
|
20
|
+
config_path: Optional[str] = None,
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Fetch the datasets and models specified in a training configuration.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
override_kwargs: Additional Hydra override arguments to pass to the
|
|
26
|
+
train script.
|
|
27
|
+
cfg_launcher: Use the launcher specified in the configuration instead
|
|
28
|
+
of the Hydra basic launcher. Defaults to False.
|
|
29
|
+
config_name: The name of the config (usually the file name without the
|
|
30
|
+
.yaml extension). Defaults to "config".
|
|
31
|
+
config_path: The config path, a directory where Hydra will search for
|
|
32
|
+
config files. If config_path is None no directory is added to the
|
|
33
|
+
search path. Defaults to None.
|
|
34
|
+
"""
|
|
35
|
+
if running_in_notebook():
|
|
36
|
+
run_hydra_cmd(
|
|
37
|
+
"fetch -l" if cfg_launcher else "fetch",
|
|
38
|
+
override_kwargs,
|
|
39
|
+
config_name,
|
|
40
|
+
config_path,
|
|
41
|
+
cmd_prefix="aucurriculum",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
else:
|
|
45
|
+
add_hydra_args_to_sys(override_kwargs, config_name, config_path)
|
|
46
|
+
script = FetchScript()
|
|
47
|
+
script.parser = MockParser()
|
|
48
|
+
script.main(FetchArgs(cfg_launcher))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@catch_cli_errors
|
|
52
|
+
def preprocess(
|
|
53
|
+
override_kwargs: Optional[dict] = None,
|
|
54
|
+
num_workers: int = 1,
|
|
55
|
+
update_frequency: int = 1,
|
|
56
|
+
cfg_launcher: bool = False,
|
|
57
|
+
config_name: str = "config",
|
|
58
|
+
config_path: Optional[str] = None,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Launch a data preprocessing configuration.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
override_kwargs: Additional Hydra override arguments to pass to the
|
|
64
|
+
train script.
|
|
65
|
+
num_workers: Number of workers (threads) to use for preprocessing.
|
|
66
|
+
Defaults to 1.
|
|
67
|
+
update_frequency: Frequency of progress bar updates for each worker
|
|
68
|
+
(thread). If 0, the progress bar will be disabled. Defaults to 1.
|
|
69
|
+
cfg_launcher: Use the launcher specified in the configuration instead
|
|
70
|
+
of the Hydra basic launcher. Defaults to False.
|
|
71
|
+
config_name: The name of the config (usually the file name without the
|
|
72
|
+
.yaml extension). Defaults to "config".
|
|
73
|
+
config_path: The config path, a directory where Hydra will search for
|
|
74
|
+
config files. If config_path is None no directory is added to the
|
|
75
|
+
search path. Defaults to None.
|
|
76
|
+
"""
|
|
77
|
+
if running_in_notebook():
|
|
78
|
+
cmd = "preprocess"
|
|
79
|
+
if cfg_launcher:
|
|
80
|
+
cmd += " -l"
|
|
81
|
+
cmd += f" -n {num_workers} -u {update_frequency}"
|
|
82
|
+
run_hydra_cmd(
|
|
83
|
+
cmd,
|
|
84
|
+
override_kwargs,
|
|
85
|
+
config_name,
|
|
86
|
+
config_path,
|
|
87
|
+
cmd_prefix="aucurriculum",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
else:
|
|
91
|
+
add_hydra_args_to_sys(override_kwargs, config_name, config_path)
|
|
92
|
+
script = PreprocessScript()
|
|
93
|
+
script.parser = MockParser()
|
|
94
|
+
script.main(
|
|
95
|
+
PreprocessArgs(cfg_launcher, num_workers, update_frequency)
|
|
96
|
+
)
|