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,247 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import random
|
|
3
|
+
import numpy as np
|
|
4
|
+
import os
|
|
5
|
+
import warnings
|
|
6
|
+
from typing import Optional, Type, List, cast, Tuple, Union
|
|
7
|
+
|
|
8
|
+
import torch
|
|
9
|
+
from lightning_fabric import Fabric
|
|
10
|
+
from torch.utils.data import DataLoader
|
|
11
|
+
|
|
12
|
+
from autoencodix.base._base_dataset import BaseDataset
|
|
13
|
+
from autoencodix.base._base_loss import BaseLoss
|
|
14
|
+
from autoencodix.base._base_autoencoder import BaseAutoencoder
|
|
15
|
+
from autoencodix.utils._result import Result
|
|
16
|
+
from autoencodix.configs.default_config import DefaultConfig
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseTrainer(abc.ABC):
|
|
20
|
+
"""General training logic for all autoencoder models.
|
|
21
|
+
|
|
22
|
+
This class sets up the model, optimizer, and data loaders. It also handles
|
|
23
|
+
reproducibility and model-specific configurations. Subclasses must implement
|
|
24
|
+
model training and prediction logic.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
_trainset: The dataset used for training.
|
|
28
|
+
_validset: The dataset used for validation, if provided.
|
|
29
|
+
_result: An object to store and manage training results.
|
|
30
|
+
_config: Configuration object containing training hyperparameters and settings.
|
|
31
|
+
_model_type: The autoencoder model class to be trained.
|
|
32
|
+
_loss_fn: Instantiated loss function specific to the model.
|
|
33
|
+
_trainloader: DataLoader for the training dataset.
|
|
34
|
+
_validloader: DataLoader for the validation dataset, if provided.
|
|
35
|
+
_model: The instantiated model architecture.
|
|
36
|
+
_optimizer: The optimizer used for training.
|
|
37
|
+
_fabric: Lightning Fabric wrapper for device and precision management.
|
|
38
|
+
ontologies: Ontology information, if provided for Ontix
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
trainset: Optional[BaseDataset],
|
|
44
|
+
validset: Optional[BaseDataset],
|
|
45
|
+
result: Result,
|
|
46
|
+
config: DefaultConfig,
|
|
47
|
+
model_type: Type[BaseAutoencoder],
|
|
48
|
+
loss_type: Type[BaseLoss],
|
|
49
|
+
ontologies: Optional[
|
|
50
|
+
Union[Tuple, List]
|
|
51
|
+
] = None, # Addition to Varix, mandotory for Ontix
|
|
52
|
+
):
|
|
53
|
+
self._trainset = trainset
|
|
54
|
+
self._model_type = model_type
|
|
55
|
+
self._validset = validset
|
|
56
|
+
self._result = result
|
|
57
|
+
self._config = config
|
|
58
|
+
self._loss_type = loss_type
|
|
59
|
+
self.ontologies = ontologies
|
|
60
|
+
self.setup_trainer()
|
|
61
|
+
|
|
62
|
+
def setup_trainer(self, old_model=None):
|
|
63
|
+
if old_model is None:
|
|
64
|
+
self._input_validation()
|
|
65
|
+
self._init_loaders()
|
|
66
|
+
|
|
67
|
+
self._loss_fn = self._loss_type(config=self._config)
|
|
68
|
+
|
|
69
|
+
self._handle_reproducibility()
|
|
70
|
+
# Internal data handling
|
|
71
|
+
self._model: BaseAutoencoder
|
|
72
|
+
self._fabric = Fabric(
|
|
73
|
+
accelerator=self._config.device,
|
|
74
|
+
devices=self._config.n_gpus,
|
|
75
|
+
precision=self._config.float_precision,
|
|
76
|
+
strategy=self._config.gpu_strategy,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self._fabric.launch()
|
|
80
|
+
self._setup_fabric(old_model=old_model)
|
|
81
|
+
|
|
82
|
+
self._n_cpus = os.cpu_count()
|
|
83
|
+
if self._n_cpus is None:
|
|
84
|
+
self._n_cpus = 0
|
|
85
|
+
|
|
86
|
+
def _setup_fabric(self, old_model=None):
|
|
87
|
+
"""
|
|
88
|
+
Sets up the model, optimizer, and data loaders with Lightning Fabric.
|
|
89
|
+
"""
|
|
90
|
+
self._init_model_architecture(
|
|
91
|
+
ontologies=self.ontologies, old_model=old_model
|
|
92
|
+
) # Ontix
|
|
93
|
+
|
|
94
|
+
self._optimizer = torch.optim.AdamW(
|
|
95
|
+
params=self._model.parameters(),
|
|
96
|
+
lr=self._config.learning_rate,
|
|
97
|
+
weight_decay=self._config.weight_decay,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
self._model, self._optimizer = self._fabric.setup(self._model, self._optimizer)
|
|
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
|
+
def _init_loaders(self):
|
|
107
|
+
"""Initializes the DataLoaders for training and validation datasets."""
|
|
108
|
+
# g = torch.Generator()
|
|
109
|
+
# g.manual_seed(self._config.global_seed)
|
|
110
|
+
last_batch_is_one_sample = len(self._trainset) % self._config.batch_size == 1
|
|
111
|
+
corrected_bs = (
|
|
112
|
+
self._config.batch_size + 1
|
|
113
|
+
if last_batch_is_one_sample
|
|
114
|
+
else self._config.batch_size
|
|
115
|
+
)
|
|
116
|
+
if last_batch_is_one_sample:
|
|
117
|
+
warnings.warn(
|
|
118
|
+
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)"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
self._trainloader = DataLoader(
|
|
122
|
+
cast(BaseDataset, self._trainset),
|
|
123
|
+
shuffle=True,
|
|
124
|
+
batch_size=corrected_bs,
|
|
125
|
+
worker_init_fn=self._seed_worker,
|
|
126
|
+
# generator=g,
|
|
127
|
+
)
|
|
128
|
+
if self._validset:
|
|
129
|
+
last_batch_is_one_sample = (
|
|
130
|
+
len(self._validset) % self._config.batch_size == 1
|
|
131
|
+
)
|
|
132
|
+
corrected_bs = (
|
|
133
|
+
self._config.batch_size + 1
|
|
134
|
+
if last_batch_is_one_sample
|
|
135
|
+
else self._config.batch_size
|
|
136
|
+
)
|
|
137
|
+
if last_batch_is_one_sample:
|
|
138
|
+
warnings.warn(
|
|
139
|
+
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)"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
self._validloader = DataLoader(
|
|
143
|
+
dataset=self._validset,
|
|
144
|
+
batch_size=self._config.batch_size,
|
|
145
|
+
shuffle=False,
|
|
146
|
+
)
|
|
147
|
+
else:
|
|
148
|
+
self._validloader = None # type: ignore
|
|
149
|
+
|
|
150
|
+
def _input_validation(self) -> None:
|
|
151
|
+
if self._trainset is None:
|
|
152
|
+
raise ValueError(
|
|
153
|
+
"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."
|
|
154
|
+
)
|
|
155
|
+
if not isinstance(self._trainset, BaseDataset):
|
|
156
|
+
raise TypeError(
|
|
157
|
+
f"Expected train type to be an instance of BaseDataset, got {type(self._trainset)}."
|
|
158
|
+
)
|
|
159
|
+
if self._validset is None:
|
|
160
|
+
print("training without validation")
|
|
161
|
+
elif not isinstance(self._validset, BaseDataset):
|
|
162
|
+
raise TypeError(
|
|
163
|
+
f"Expected valid type to be an instance of BaseDataset, got {type(self._validset)}."
|
|
164
|
+
)
|
|
165
|
+
if self._config is None:
|
|
166
|
+
raise ValueError("Config cannot be None.")
|
|
167
|
+
|
|
168
|
+
def _handle_reproducibility(self) -> None:
|
|
169
|
+
"""Sets all relevant seeds for reproducibility
|
|
170
|
+
|
|
171
|
+
Raises:
|
|
172
|
+
NotImplementedError: If the device is set to "mps" (Apple Silicon).
|
|
173
|
+
"""
|
|
174
|
+
if self._config.reproducible:
|
|
175
|
+
torch.use_deterministic_algorithms(True)
|
|
176
|
+
torch.manual_seed(seed=self._config.global_seed)
|
|
177
|
+
random.seed(self._config.global_seed)
|
|
178
|
+
np.random.seed(self._config.global_seed)
|
|
179
|
+
if torch.cuda.is_available():
|
|
180
|
+
torch.cuda.manual_seed(seed=self._config.global_seed)
|
|
181
|
+
torch.cuda.manual_seed_all(seed=self._config.global_seed)
|
|
182
|
+
torch.backends.cudnn.deterministic = True
|
|
183
|
+
torch.backends.cudnn.benchmark = False
|
|
184
|
+
if torch.backends.mps.is_available():
|
|
185
|
+
torch.mps.manual_seed(seed=self._config.global_seed)
|
|
186
|
+
|
|
187
|
+
# torch.use_deterministic_algorithms(True, warn_only=True)
|
|
188
|
+
|
|
189
|
+
print(
|
|
190
|
+
"Warning: MPS backend has limited support for deterministic algorithms. "
|
|
191
|
+
"Seeding is active, but full reproducibility is not guaranteed."
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
print(
|
|
195
|
+
f"Reproducibility settings for device {self._model.device.type} are not implemented or necessary i.e. for cpu."
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def _seed_worker(self, worker_id):
|
|
199
|
+
worker_seed = self._config.global_seed + worker_id
|
|
200
|
+
np.random.seed(worker_seed)
|
|
201
|
+
random.seed(worker_seed)
|
|
202
|
+
|
|
203
|
+
def _init_model_architecture(self, ontologies: tuple, old_model=None) -> None:
|
|
204
|
+
"""Initializes the model architecture, based on the model type and input dimension."""
|
|
205
|
+
if old_model:
|
|
206
|
+
self._model = old_model
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
self._input_dim = cast(BaseDataset, self._trainset).get_input_dim()
|
|
210
|
+
self.feature_order = self._trainset.feature_ids
|
|
211
|
+
if ontologies is None:
|
|
212
|
+
self._model = self._model_type(
|
|
213
|
+
config=self._config, input_dim=self._input_dim
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
else:
|
|
217
|
+
self._model = self._model_type(
|
|
218
|
+
config=self._config,
|
|
219
|
+
input_dim=self._input_dim,
|
|
220
|
+
ontologies=ontologies,
|
|
221
|
+
feature_order=self._trainset.feature_ids, # type: ignore
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def _should_checkpoint(self, epoch: int) -> bool:
|
|
225
|
+
return (
|
|
226
|
+
(epoch + 1) % self._config.checkpoint_interval == 0
|
|
227
|
+
or epoch == self._config.epochs - 1
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
@abc.abstractmethod
|
|
231
|
+
def train(self, epochs_overwrite: Optional[int] = None) -> Result:
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
@abc.abstractmethod
|
|
235
|
+
def decode(self, x: torch.Tensor) -> torch.Tensor:
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
@abc.abstractmethod
|
|
239
|
+
def predict(
|
|
240
|
+
self, data: BaseDataset, model: Optional[torch.nn.Module] = None, **kwargs
|
|
241
|
+
) -> Result:
|
|
242
|
+
pass
|
|
243
|
+
|
|
244
|
+
@abc.abstractmethod
|
|
245
|
+
def purge(self) -> None:
|
|
246
|
+
"""Cleans up any resources used during training, such as cached data or large attributes."""
|
|
247
|
+
pass
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from ._base_pipeline import BasePipeline
|
|
2
|
+
from ._base_autoencoder import BaseAutoencoder
|
|
3
|
+
from ._base_dataset import BaseDataset
|
|
4
|
+
from ._base_predictor import BasePredictor
|
|
5
|
+
from ._base_preprocessor import BasePreprocessor
|
|
6
|
+
from ._base_evaluator import BaseEvaluator
|
|
7
|
+
from ._base_loss import BaseLoss
|
|
8
|
+
from ._base_trainer import BaseTrainer
|
|
9
|
+
from ._base_visualizer import BaseVisualizer
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"BasePipeline",
|
|
13
|
+
"BaseAutoencoder",
|
|
14
|
+
"BaseDataset",
|
|
15
|
+
"BasePredictor",
|
|
16
|
+
"BasePreprocessor",
|
|
17
|
+
"BaseEvaluator",
|
|
18
|
+
"BaseLoss",
|
|
19
|
+
"BaseTrainer",
|
|
20
|
+
"BaseVisualizer",
|
|
21
|
+
]
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Optional, Tuple, Union, Dict
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
import torch.nn as nn
|
|
6
|
+
|
|
7
|
+
from autoencodix.utils._model_output import ModelOutput
|
|
8
|
+
from autoencodix.configs.default_config import DefaultConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BaseAutoencoder(ABC, nn.Module):
|
|
12
|
+
"""Interface for building autoencoder models.
|
|
13
|
+
|
|
14
|
+
Defines standard methods for encoding data to a latent space and decoding
|
|
15
|
+
back to the original space. Includes a weight initialization method for
|
|
16
|
+
stable training. Intended to be extended by specific autoencoder variants
|
|
17
|
+
like VAE.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
input_dim: Number of input features.
|
|
21
|
+
config: Configuration object containing model architecture parameters.
|
|
22
|
+
_encoder: Encoder network.
|
|
23
|
+
_decoder: Decoder network.
|
|
24
|
+
ontologies: Ontology information, if provided for Ontix
|
|
25
|
+
feature_order: For Ontix
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
config: Optional[DefaultConfig],
|
|
31
|
+
input_dim: Union[int, Tuple[int, ...]],
|
|
32
|
+
ontologies: Optional[Union[Tuple, Dict]] = None,
|
|
33
|
+
feature_order: Optional[Union[Tuple, Dict]] = None,
|
|
34
|
+
):
|
|
35
|
+
"""Initializes the BaseAutoencoder.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
config: Configuration object containing model parameters.
|
|
39
|
+
If None, a default configuration will be used.
|
|
40
|
+
input_dim: Number of input features.
|
|
41
|
+
ontologies: Ontology information, if provided for Ontix
|
|
42
|
+
feature_order: For Ontix
|
|
43
|
+
"""
|
|
44
|
+
super().__init__()
|
|
45
|
+
if config is None:
|
|
46
|
+
config = DefaultConfig()
|
|
47
|
+
self.input_dim = input_dim
|
|
48
|
+
self._encoder: Optional[nn.Module] = None
|
|
49
|
+
self._decoder: Optional[nn.Module] = None
|
|
50
|
+
self.config = config
|
|
51
|
+
self.ontologies = ontologies
|
|
52
|
+
self.feature_order = feature_order
|
|
53
|
+
self.init_args = dict(
|
|
54
|
+
config=config,
|
|
55
|
+
input_dim=input_dim,
|
|
56
|
+
ontologies=ontologies,
|
|
57
|
+
feature_order=feature_order,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def _build_network(self) -> None:
|
|
62
|
+
"""Builds the encoder and decoder networks for the autoencoder model.
|
|
63
|
+
|
|
64
|
+
Populates the self._encoder and self._decoder attributes.
|
|
65
|
+
This method should be implemented by subclasses to define
|
|
66
|
+
the architecture of the encoder and decoder networks.
|
|
67
|
+
"""
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def encode(
|
|
72
|
+
self, x: torch.Tensor
|
|
73
|
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
|
74
|
+
"""Encodes the input into the latent space.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
x: The input tensor to be encoded.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
The encoded latent space representation, or mu and logvar for VAEs.
|
|
81
|
+
"""
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def get_latent_space(self, x: torch.Tensor) -> torch.Tensor:
|
|
86
|
+
"""Returns the latent space representation of the input.
|
|
87
|
+
|
|
88
|
+
Method for unification of getting a latent space between Variational
|
|
89
|
+
and Vanilla Autoencoders. This method is a wrapper around the encode
|
|
90
|
+
method, or the reparameterization method for VAE.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
x: The input tensor to be encoded.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
The latent space representation of the input tensor.
|
|
97
|
+
"""
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
def decode(self, x: torch.Tensor) -> torch.Tensor:
|
|
102
|
+
"""Decodes the latent representation back to the input space.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
x: The latent tensor to be decoded.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
The decoded tensor, reconstructed from the latent space.
|
|
109
|
+
"""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def forward(self, x: torch.Tensor) -> ModelOutput:
|
|
114
|
+
"""Combines encoding and decoding steps for the autoencoder.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
x: The input tensor to be processed.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The reconstructed input tensor and any additional information,
|
|
121
|
+
depending on the model type.
|
|
122
|
+
"""
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
def _init_weights(self, m):
|
|
126
|
+
"""Initializes weights using Xavier uniform initialization.
|
|
127
|
+
|
|
128
|
+
This weight initialization method helps maintain the variance of
|
|
129
|
+
activations across layers, preventing gradients from vanishing or
|
|
130
|
+
exploding during training. This approach ensures stable and efficient
|
|
131
|
+
training of the autoencoder model.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
m: The module to initialize.
|
|
135
|
+
"""
|
|
136
|
+
if isinstance(m, nn.Linear):
|
|
137
|
+
torch.nn.init.xavier_uniform_(m.weight)
|
|
138
|
+
m.bias.data.fill_(0.01)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import scipy as sp
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import torch
|
|
8
|
+
from torch.utils.data import Dataset
|
|
9
|
+
|
|
10
|
+
from autoencodix.data._imgdataclass import ImgData
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DataSetTypes(str, Enum):
|
|
14
|
+
NUM = "NUM"
|
|
15
|
+
IMG = "IMG"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BaseDataset(abc.ABC, Dataset):
|
|
19
|
+
"""Interface to guide implementation for custom PyTorch datasets.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
data: The dataset content (can be a torch.Tensor or other data structure).
|
|
23
|
+
config: Optional configuration object.
|
|
24
|
+
sample_ids: Optional list of identifiers for each sample.
|
|
25
|
+
feature_ids: Optional list of identifiers for each feature.
|
|
26
|
+
mytype: Enum indicating the dataset type (should be set in subclasses).
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
data: Union[torch.Tensor, List[ImgData], sp.sparse.spmatrix],
|
|
32
|
+
config: Optional[Any] = None,
|
|
33
|
+
sample_ids: Optional[List[Any]] = None,
|
|
34
|
+
feature_ids: Optional[List[Any]] = None,
|
|
35
|
+
):
|
|
36
|
+
"""Initializes the dataset.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
data: The data to be used by the dataset.
|
|
40
|
+
config: Optional configuration parameters.
|
|
41
|
+
sample_ids: Optional identifiers for each sample.
|
|
42
|
+
feature_ids: Optional identifiers for each feature.
|
|
43
|
+
mytype: Enum indicating the dataset type (should be set in subclasses).
|
|
44
|
+
"""
|
|
45
|
+
self.data = data
|
|
46
|
+
self.raw_data = data # for child class ImageDataset
|
|
47
|
+
self.config = config
|
|
48
|
+
self.sample_ids = sample_ids
|
|
49
|
+
self.feature_ids = feature_ids
|
|
50
|
+
self.mytype: Enum # Should be set in subclasses to indicate the dataset type (e.g., DataSetTypes.NUM or DataSetTypes.IMG)
|
|
51
|
+
|
|
52
|
+
self.metadata: Optional[Union[pd.Series, pd.DataFrame]] = (None,)
|
|
53
|
+
self.datasets: Dict[str, BaseDataset] = {} # for xmodalix child
|
|
54
|
+
|
|
55
|
+
def __len__(self) -> int:
|
|
56
|
+
"""Returns the number of samples in the dataset.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The number of samples in the dataset.
|
|
60
|
+
"""
|
|
61
|
+
if isinstance(self.data, list):
|
|
62
|
+
return len(self.data)
|
|
63
|
+
else:
|
|
64
|
+
return self.data.shape[0]
|
|
65
|
+
|
|
66
|
+
def get_input_dim(self) -> Union[int, Tuple[int, ...]]:
|
|
67
|
+
"""Gets the input dimension of the dataset (n_features)
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The input dimension of the dataset's feature space.
|
|
71
|
+
"""
|
|
72
|
+
if isinstance(self.data, (torch.Tensor, sp.sparse.spmatrix)):
|
|
73
|
+
return self.data.shape[1]
|
|
74
|
+
|
|
75
|
+
elif isinstance(self.data, list):
|
|
76
|
+
if len(self.data) == 0:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
"Dataset is ImgData, and the list of ImgData is empty, cannot determine input dimension."
|
|
79
|
+
)
|
|
80
|
+
if isinstance(self.data[0], ImgData):
|
|
81
|
+
return self.data[0].img.shape[0]
|
|
82
|
+
else:
|
|
83
|
+
raise ValueError(
|
|
84
|
+
f"List data is not of type ImgData, got {type(self.data[0])}, cannot determine input dimension."
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
raise ValueError("Unsupported data type for input dimension retrieval.")
|
|
88
|
+
|
|
89
|
+
def _to_df(self, modality: Optional[str] = None) -> pd.DataFrame:
|
|
90
|
+
"""
|
|
91
|
+
Convert the dataset to a pandas DataFrame.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
DataFrame representation of the dataset
|
|
95
|
+
"""
|
|
96
|
+
if isinstance(self.data, torch.Tensor):
|
|
97
|
+
return pd.DataFrame(
|
|
98
|
+
self.data.numpy(), columns=self.feature_ids, index=self.sample_ids
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
raise TypeError(
|
|
102
|
+
"Data is not a torch.Tensor and cannot be converted to DataFrame."
|
|
103
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
from autoencodix.utils._result import Result
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseEvaluator(abc.ABC):
|
|
7
|
+
@abc.abstractmethod
|
|
8
|
+
def evaluate(self, *args):
|
|
9
|
+
"""
|
|
10
|
+
Evaluate the Autoencodix pipeline on defined machine learning tasks.
|
|
11
|
+
|
|
12
|
+
Subclasses must implement this method to perform evaluation using the provided arguments.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
*args: Variable length argument list for evaluation parameters.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Result: The evaluation result.
|
|
19
|
+
"""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def _expand_reference_methods(reference_methods: list, result: Result) -> list:
|
|
24
|
+
"""
|
|
25
|
+
Expands the list of reference methods if needed for evaluation.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
reference_methods (list): The list of reference methods to potentially expand.
|
|
29
|
+
result (Result): The evaluation result object.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
list: The (possibly expanded) list of reference methods.
|
|
33
|
+
"""
|
|
34
|
+
return reference_methods
|