autoencodix 0.2.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.
Potentially problematic release.
This version of autoencodix might be problematic. Click here for more details.
- autoencodix/__init__.py +27 -0
- autoencodix/base/.ipynb_checkpoints/_base_pipeline-checkpoint.py +1274 -0
- autoencodix/base/.ipynb_checkpoints/_base_trainer-checkpoint.py +247 -0
- autoencodix/base/__init__.py +21 -0
- autoencodix/base/_base_autoencoder.py +138 -0
- autoencodix/base/_base_dataset.py +103 -0
- autoencodix/base/_base_evaluator.py +34 -0
- autoencodix/base/_base_loss.py +311 -0
- autoencodix/base/_base_pipeline.py +1355 -0
- autoencodix/base/_base_predictor.py +6 -0
- autoencodix/base/_base_preprocessor.py +1033 -0
- autoencodix/base/_base_trainer.py +259 -0
- autoencodix/base/_base_visualizer.py +578 -0
- autoencodix/base/sampleconfig.yaml +132 -0
- autoencodix/configs/__init__.py +21 -0
- autoencodix/configs/default_config.py +652 -0
- autoencodix/configs/disentanglix_config.py +15 -0
- autoencodix/configs/maskix_config.py +39 -0
- autoencodix/configs/ontix_config.py +35 -0
- autoencodix/configs/stackix_config.py +33 -0
- autoencodix/configs/vanillix_config.py +18 -0
- autoencodix/configs/varix_config.py +15 -0
- autoencodix/configs/xmodalix_config.py +43 -0
- autoencodix/disentanglix.py +72 -0
- autoencodix/evaluate/.ipynb_checkpoints/evaluate-checkpoint.py +532 -0
- autoencodix/evaluate/__init__.py +4 -0
- autoencodix/evaluate/_general_evaluator.py +730 -0
- autoencodix/evaluate/_xmodalix_evaluator.py +376 -0
- autoencodix/imagix.py +76 -0
- autoencodix/losses/disentanglix_loss.py +215 -0
- autoencodix/losses/maskix_loss.py +94 -0
- autoencodix/losses/vanillix_loss.py +28 -0
- autoencodix/losses/varix_loss.py +102 -0
- autoencodix/losses/xmodal_loss.py +304 -0
- autoencodix/maskix.py +108 -0
- autoencodix/modeling/.ipynb_checkpoints/__init__-checkpoint.py +16 -0
- autoencodix/modeling/.ipynb_checkpoints/_captum_forward-checkpoint.py +16 -0
- autoencodix/modeling/__init__.py +20 -0
- autoencodix/modeling/_captum_forward.py +20 -0
- autoencodix/modeling/_classifier.py +45 -0
- autoencodix/modeling/_imagevae_architecture.py +296 -0
- autoencodix/modeling/_imgfast_architecture.py +288 -0
- autoencodix/modeling/_layer_factory.py +71 -0
- autoencodix/modeling/_maskix_architecture.py +190 -0
- autoencodix/modeling/_ontix_architecture.py +305 -0
- autoencodix/modeling/_vanillix_architecture.py +136 -0
- autoencodix/modeling/_varix_architecture.py +192 -0
- autoencodix/notebooks/__init__.py +0 -0
- autoencodix/ontix.py +136 -0
- autoencodix/py.typed +0 -0
- autoencodix/stackix.py +122 -0
- autoencodix/trainers/__init__.py +6 -0
- autoencodix/trainers/_general_trainer.py +525 -0
- autoencodix/trainers/_maskix_trainer.py +116 -0
- autoencodix/trainers/_ontix_trainer.py +77 -0
- autoencodix/trainers/_stackix_orchestrator.py +522 -0
- autoencodix/trainers/_stackix_trainer.py +209 -0
- autoencodix/trainers/_xmodal_trainer.py +1006 -0
- autoencodix/utils/.ipynb_checkpoints/_explainer-checkpoint.py +118 -0
- autoencodix/utils/.ipynb_checkpoints/_model_output-checkpoint.py +30 -0
- autoencodix/utils/.ipynb_checkpoints/_utils-checkpoint.py +626 -0
- autoencodix/utils/.ipynb_checkpoints/adata_converter-checkpoint.py +99 -0
- autoencodix/utils/.ipynb_checkpoints/feature_importance-checkpoint.py +823 -0
- autoencodix/utils/__init__.py +22 -0
- autoencodix/utils/_annealer.py +193 -0
- autoencodix/utils/_bulkreader.py +232 -0
- autoencodix/utils/_explainer.py +246 -0
- autoencodix/utils/_imgreader.py +404 -0
- autoencodix/utils/_internals.py +23 -0
- autoencodix/utils/_llm_explainer.py +318 -0
- autoencodix/utils/_losses.py +20 -0
- autoencodix/utils/_model_output.py +30 -0
- autoencodix/utils/_result.py +393 -0
- autoencodix/utils/_screader.py +76 -0
- autoencodix/utils/_traindynamics.py +187 -0
- autoencodix/utils/_utils.py +690 -0
- autoencodix/utils/adata_converter.py +111 -0
- autoencodix/utils/example_data.py +398 -0
- autoencodix/utils/feature_importance.py +829 -0
- autoencodix/utils/prompts.py +21 -0
- autoencodix/vanillix.py +141 -0
- autoencodix/varix.py +80 -0
- autoencodix/visualize/__init__.py +5 -0
- autoencodix/visualize/_general_visualizer.py +913 -0
- autoencodix/visualize/_imagix_visualizer.py +111 -0
- autoencodix/visualize/_xmodal_visualizer.py +841 -0
- autoencodix/visualize/visualize.py +1214 -0
- autoencodix/xmodalix.py +318 -0
- autoencodix-0.2.0.dist-info/METADATA +143 -0
- autoencodix-0.2.0.dist-info/RECORD +91 -0
- autoencodix-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from packaging.version import Version
|
|
3
|
+
import random
|
|
4
|
+
import numpy as np
|
|
5
|
+
import os
|
|
6
|
+
import warnings
|
|
7
|
+
from typing import Optional, Type, List, cast, Tuple, Union
|
|
8
|
+
|
|
9
|
+
import torch
|
|
10
|
+
from lightning_fabric import Fabric
|
|
11
|
+
from torch.utils.data import DataLoader
|
|
12
|
+
|
|
13
|
+
from autoencodix.base._base_dataset import BaseDataset
|
|
14
|
+
from autoencodix.base._base_loss import BaseLoss
|
|
15
|
+
from autoencodix.base._base_autoencoder import BaseAutoencoder
|
|
16
|
+
from autoencodix.utils._result import Result
|
|
17
|
+
from autoencodix.configs.default_config import DefaultConfig
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BaseTrainer(abc.ABC):
|
|
21
|
+
"""General training logic for all autoencoder models.
|
|
22
|
+
|
|
23
|
+
This class sets up the model, optimizer, and data loaders. It also handles
|
|
24
|
+
reproducibility and model-specific configurations. Subclasses must implement
|
|
25
|
+
model training and prediction logic.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
_trainset: The dataset used for training.
|
|
29
|
+
_validset: The dataset used for validation, if provided.
|
|
30
|
+
_result: An object to store and manage training results.
|
|
31
|
+
_config: Configuration object containing training hyperparameters and settings.
|
|
32
|
+
_model_type: The autoencoder model class to be trained.
|
|
33
|
+
_loss_fn: Instantiated loss function specific to the model.
|
|
34
|
+
_trainloader: DataLoader for the training dataset.
|
|
35
|
+
_validloader: DataLoader for the validation dataset, if provided.
|
|
36
|
+
_model: The instantiated model architecture.
|
|
37
|
+
_optimizer: The optimizer used for training.
|
|
38
|
+
_fabric: Lightning Fabric wrapper for device and precision management.
|
|
39
|
+
ontologies: Ontology information, if provided for Ontix
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
trainset: Optional[BaseDataset],
|
|
45
|
+
validset: Optional[BaseDataset],
|
|
46
|
+
result: Result,
|
|
47
|
+
config: DefaultConfig,
|
|
48
|
+
model_type: Type[BaseAutoencoder],
|
|
49
|
+
loss_type: Type[BaseLoss],
|
|
50
|
+
ontologies: Optional[
|
|
51
|
+
Union[Tuple, List]
|
|
52
|
+
] = None, # Addition to Varix, mandotory for Ontix
|
|
53
|
+
**kwargs,
|
|
54
|
+
):
|
|
55
|
+
self._trainset = trainset
|
|
56
|
+
self._model_type = model_type
|
|
57
|
+
self._validset = validset
|
|
58
|
+
self._result = result
|
|
59
|
+
self._config = config
|
|
60
|
+
self._loss_type = loss_type
|
|
61
|
+
self.ontologies = ontologies
|
|
62
|
+
self.setup_trainer()
|
|
63
|
+
|
|
64
|
+
def setup_trainer(self, old_model=None):
|
|
65
|
+
if old_model is None:
|
|
66
|
+
self._input_validation()
|
|
67
|
+
self._init_loaders()
|
|
68
|
+
|
|
69
|
+
self._loss_fn = self._loss_type(config=self._config)
|
|
70
|
+
|
|
71
|
+
self._handle_reproducibility()
|
|
72
|
+
# Internal data handling
|
|
73
|
+
self._model: BaseAutoencoder
|
|
74
|
+
self._fabric = Fabric(
|
|
75
|
+
accelerator=self._config.device,
|
|
76
|
+
devices=self._config.n_gpus,
|
|
77
|
+
precision=self._config.float_precision,
|
|
78
|
+
strategy=self._config.gpu_strategy,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
self._fabric.launch()
|
|
82
|
+
self._setup_fabric(old_model=old_model)
|
|
83
|
+
|
|
84
|
+
self._n_cpus = os.cpu_count()
|
|
85
|
+
if self._n_cpus is None:
|
|
86
|
+
self._n_cpus = 0
|
|
87
|
+
|
|
88
|
+
def _setup_fabric(self, old_model=None):
|
|
89
|
+
"""
|
|
90
|
+
Sets up the model, optimizer, and data loaders with Lightning Fabric.
|
|
91
|
+
"""
|
|
92
|
+
self._init_model_architecture(
|
|
93
|
+
ontologies=self.ontologies, old_model=old_model
|
|
94
|
+
) # Ontix
|
|
95
|
+
|
|
96
|
+
self._optimizer = torch.optim.AdamW(
|
|
97
|
+
params=self._model.parameters(),
|
|
98
|
+
lr=self._config.learning_rate,
|
|
99
|
+
weight_decay=self._config.weight_decay,
|
|
100
|
+
)
|
|
101
|
+
if old_model is None:
|
|
102
|
+
self._trainloader = self._fabric.setup_dataloaders(self._trainloader) # type: ignore
|
|
103
|
+
if self._validloader is not None:
|
|
104
|
+
self._validloader = self._fabric.setup_dataloaders(self._validloader) # type: ignore
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
Version(torch.__version__) >= Version("2.0")
|
|
108
|
+
and torch.cuda.is_available()
|
|
109
|
+
and old_model is None
|
|
110
|
+
and self._config.compile_model
|
|
111
|
+
): # dont compile twice
|
|
112
|
+
self._model = torch.compile(self._model)
|
|
113
|
+
|
|
114
|
+
self._model, self._optimizer = self._fabric.setup(self._model, self._optimizer)
|
|
115
|
+
|
|
116
|
+
def _init_loaders(self):
|
|
117
|
+
"""Initializes the DataLoaders for training and validation datasets."""
|
|
118
|
+
# g = torch.Generator()
|
|
119
|
+
# g.manual_seed(self._config.global_seed)
|
|
120
|
+
last_batch_is_one_sample = len(self._trainset) % self._config.batch_size == 1
|
|
121
|
+
corrected_bs = (
|
|
122
|
+
self._config.batch_size + 1
|
|
123
|
+
if last_batch_is_one_sample
|
|
124
|
+
else self._config.batch_size
|
|
125
|
+
)
|
|
126
|
+
if last_batch_is_one_sample:
|
|
127
|
+
warnings.warn(
|
|
128
|
+
f"increased batch_size to {corrected_bs} for trainset, to avoid dropping samples and having batches (makes trainingdynamics messy with missing samples per epoch) of size one (fails for Models with BachNorm)"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
self._trainloader = DataLoader(
|
|
132
|
+
cast(BaseDataset, self._trainset),
|
|
133
|
+
shuffle=True,
|
|
134
|
+
batch_size=corrected_bs,
|
|
135
|
+
worker_init_fn=self._seed_worker,
|
|
136
|
+
pin_memory=self._config.pin_memory,
|
|
137
|
+
# generator=g,
|
|
138
|
+
)
|
|
139
|
+
if self._validset:
|
|
140
|
+
last_batch_is_one_sample = (
|
|
141
|
+
len(self._validset) % self._config.batch_size == 1
|
|
142
|
+
)
|
|
143
|
+
corrected_bs = (
|
|
144
|
+
self._config.batch_size + 1
|
|
145
|
+
if last_batch_is_one_sample
|
|
146
|
+
else self._config.batch_size
|
|
147
|
+
)
|
|
148
|
+
if last_batch_is_one_sample:
|
|
149
|
+
warnings.warn(
|
|
150
|
+
f"increased batch_size to {corrected_bs} for validset, to avoid dropping samples and having batches (makes trainingdynamics messy with missing samples per epoch) of size one (fails for Models with BachNorm)"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
self._validloader = DataLoader(
|
|
154
|
+
dataset=self._validset,
|
|
155
|
+
batch_size=self._config.batch_size,
|
|
156
|
+
shuffle=False,
|
|
157
|
+
pin_memory=self._config.pin_memory,
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
self._validloader = None # type: ignore
|
|
161
|
+
|
|
162
|
+
def _input_validation(self) -> None:
|
|
163
|
+
if self._trainset is None:
|
|
164
|
+
raise ValueError(
|
|
165
|
+
"Trainset cannot be None. Check the indices you provided with a custom split or be sure that the train_ratio attribute of the config is >0."
|
|
166
|
+
)
|
|
167
|
+
if not isinstance(self._trainset, BaseDataset):
|
|
168
|
+
raise TypeError(
|
|
169
|
+
f"Expected train type to be an instance of BaseDataset, got {type(self._trainset)}."
|
|
170
|
+
)
|
|
171
|
+
if self._validset is None:
|
|
172
|
+
print("training without validation")
|
|
173
|
+
elif not isinstance(self._validset, BaseDataset):
|
|
174
|
+
raise TypeError(
|
|
175
|
+
f"Expected valid type to be an instance of BaseDataset, got {type(self._validset)}."
|
|
176
|
+
)
|
|
177
|
+
if self._config is None:
|
|
178
|
+
raise ValueError("Config cannot be None.")
|
|
179
|
+
|
|
180
|
+
def _handle_reproducibility(self) -> None:
|
|
181
|
+
"""Sets all relevant seeds for reproducibility
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
NotImplementedError: If the device is set to "mps" (Apple Silicon).
|
|
185
|
+
"""
|
|
186
|
+
if self._config.reproducible:
|
|
187
|
+
torch.use_deterministic_algorithms(True)
|
|
188
|
+
torch.manual_seed(seed=self._config.global_seed)
|
|
189
|
+
random.seed(self._config.global_seed)
|
|
190
|
+
np.random.seed(self._config.global_seed)
|
|
191
|
+
if torch.cuda.is_available():
|
|
192
|
+
torch.cuda.manual_seed(seed=self._config.global_seed)
|
|
193
|
+
torch.cuda.manual_seed_all(seed=self._config.global_seed)
|
|
194
|
+
torch.backends.cudnn.deterministic = True
|
|
195
|
+
torch.backends.cudnn.benchmark = False
|
|
196
|
+
if torch.backends.mps.is_available():
|
|
197
|
+
torch.mps.manual_seed(seed=self._config.global_seed)
|
|
198
|
+
|
|
199
|
+
# torch.use_deterministic_algorithms(True, warn_only=True)
|
|
200
|
+
|
|
201
|
+
print(
|
|
202
|
+
"Warning: MPS backend has limited support for deterministic algorithms. "
|
|
203
|
+
"Seeding is active, but full reproducibility is not guaranteed."
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
print(
|
|
207
|
+
f"Reproducibility settings for device {self._config.device} are not implemented or necessary i.e. for cpu."
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
def _seed_worker(self, worker_id):
|
|
211
|
+
worker_seed = self._config.global_seed + worker_id
|
|
212
|
+
np.random.seed(worker_seed)
|
|
213
|
+
random.seed(worker_seed)
|
|
214
|
+
|
|
215
|
+
def _init_model_architecture(self, ontologies: tuple, old_model=None) -> None:
|
|
216
|
+
"""Initializes the model architecture, based on the model type and input dimension."""
|
|
217
|
+
if old_model:
|
|
218
|
+
self._model = old_model
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
self._input_dim = cast(BaseDataset, self._trainset).get_input_dim()
|
|
222
|
+
self.feature_order = self._trainset.feature_ids
|
|
223
|
+
if ontologies is None:
|
|
224
|
+
self._model = self._model_type(
|
|
225
|
+
config=self._config, input_dim=self._input_dim
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
else:
|
|
229
|
+
self._model = self._model_type(
|
|
230
|
+
config=self._config,
|
|
231
|
+
input_dim=self._input_dim,
|
|
232
|
+
ontologies=ontologies,
|
|
233
|
+
feature_order=self._trainset.feature_ids, # type: ignore
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def _should_checkpoint(self, epoch: int) -> bool:
|
|
237
|
+
return (
|
|
238
|
+
(epoch + 1) % self._config.checkpoint_interval == 0
|
|
239
|
+
or epoch == self._config.epochs - 1
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
@abc.abstractmethod
|
|
243
|
+
def train(self, epochs_overwrite: Optional[int] = None) -> Result:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
@abc.abstractmethod
|
|
247
|
+
def decode(self, x: torch.Tensor) -> torch.Tensor:
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
@abc.abstractmethod
|
|
251
|
+
def predict(
|
|
252
|
+
self, data: BaseDataset, model: Optional[torch.nn.Module] = None, **kwargs
|
|
253
|
+
) -> Result:
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
@abc.abstractmethod
|
|
257
|
+
def purge(self) -> None:
|
|
258
|
+
"""Cleans up any resources used during training, such as cached data or large attributes."""
|
|
259
|
+
pass
|