dragon-ml-toolbox 19.14.0__py3-none-any.whl → 20.0.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.
- {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/METADATA +29 -46
- dragon_ml_toolbox-20.0.0.dist-info/RECORD +178 -0
- ml_tools/{ETL_cleaning.py → ETL_cleaning/__init__.py} +13 -5
- ml_tools/ETL_cleaning/_basic_clean.py +351 -0
- ml_tools/ETL_cleaning/_clean_tools.py +128 -0
- ml_tools/ETL_cleaning/_dragon_cleaner.py +245 -0
- ml_tools/ETL_cleaning/_imprimir.py +13 -0
- ml_tools/{ETL_engineering.py → ETL_engineering/__init__.py} +8 -4
- ml_tools/ETL_engineering/_dragon_engineering.py +261 -0
- ml_tools/ETL_engineering/_imprimir.py +24 -0
- ml_tools/{_core/_ETL_engineering.py → ETL_engineering/_transforms.py} +14 -267
- ml_tools/{_core → GUI_tools}/_GUI_tools.py +37 -40
- ml_tools/{GUI_tools.py → GUI_tools/__init__.py} +7 -5
- ml_tools/GUI_tools/_imprimir.py +12 -0
- ml_tools/IO_tools/_IO_loggers.py +235 -0
- ml_tools/IO_tools/_IO_save_load.py +151 -0
- ml_tools/IO_tools/_IO_utils.py +140 -0
- ml_tools/{IO_tools.py → IO_tools/__init__.py} +13 -5
- ml_tools/IO_tools/_imprimir.py +14 -0
- ml_tools/MICE/_MICE_imputation.py +132 -0
- ml_tools/{MICE_imputation.py → MICE/__init__.py} +6 -7
- ml_tools/{_core/_MICE_imputation.py → MICE/_dragon_mice.py} +243 -322
- ml_tools/MICE/_imprimir.py +11 -0
- ml_tools/{ML_callbacks.py → ML_callbacks/__init__.py} +12 -4
- ml_tools/ML_callbacks/_base.py +101 -0
- ml_tools/ML_callbacks/_checkpoint.py +232 -0
- ml_tools/ML_callbacks/_early_stop.py +208 -0
- ml_tools/ML_callbacks/_imprimir.py +12 -0
- ml_tools/ML_callbacks/_scheduler.py +197 -0
- ml_tools/{ML_chaining_utilities.py → ML_chain/__init__.py} +8 -3
- ml_tools/{_core/_ML_chaining_utilities.py → ML_chain/_chaining_tools.py} +5 -129
- ml_tools/ML_chain/_dragon_chain.py +140 -0
- ml_tools/ML_chain/_imprimir.py +11 -0
- ml_tools/ML_configuration/__init__.py +90 -0
- ml_tools/ML_configuration/_base_model_config.py +69 -0
- ml_tools/ML_configuration/_finalize.py +366 -0
- ml_tools/ML_configuration/_imprimir.py +47 -0
- ml_tools/ML_configuration/_metrics.py +593 -0
- ml_tools/ML_configuration/_models.py +206 -0
- ml_tools/ML_configuration/_training.py +124 -0
- ml_tools/ML_datasetmaster/__init__.py +28 -0
- ml_tools/ML_datasetmaster/_base_datasetmaster.py +337 -0
- ml_tools/{_core/_ML_datasetmaster.py → ML_datasetmaster/_datasetmaster.py} +9 -329
- ml_tools/ML_datasetmaster/_imprimir.py +15 -0
- ml_tools/{_core/_ML_sequence_datasetmaster.py → ML_datasetmaster/_sequence_datasetmaster.py} +13 -15
- ml_tools/{_core/_ML_vision_datasetmaster.py → ML_datasetmaster/_vision_datasetmaster.py} +63 -65
- ml_tools/ML_evaluation/__init__.py +53 -0
- ml_tools/ML_evaluation/_classification.py +629 -0
- ml_tools/ML_evaluation/_feature_importance.py +409 -0
- ml_tools/ML_evaluation/_imprimir.py +25 -0
- ml_tools/ML_evaluation/_loss.py +92 -0
- ml_tools/ML_evaluation/_regression.py +273 -0
- ml_tools/{_core/_ML_sequence_evaluation.py → ML_evaluation/_sequence.py} +8 -11
- ml_tools/{_core/_ML_vision_evaluation.py → ML_evaluation/_vision.py} +12 -17
- ml_tools/{_core → ML_evaluation_captum}/_ML_evaluation_captum.py +11 -38
- ml_tools/{ML_evaluation_captum.py → ML_evaluation_captum/__init__.py} +6 -4
- ml_tools/ML_evaluation_captum/_imprimir.py +10 -0
- ml_tools/{_core → ML_finalize_handler}/_ML_finalize_handler.py +3 -7
- ml_tools/ML_finalize_handler/__init__.py +10 -0
- ml_tools/ML_finalize_handler/_imprimir.py +8 -0
- ml_tools/ML_inference/__init__.py +22 -0
- ml_tools/ML_inference/_base_inference.py +166 -0
- ml_tools/{_core/_ML_chaining_inference.py → ML_inference/_chain_inference.py} +14 -17
- ml_tools/ML_inference/_dragon_inference.py +332 -0
- ml_tools/ML_inference/_imprimir.py +11 -0
- ml_tools/ML_inference/_multi_inference.py +180 -0
- ml_tools/ML_inference_sequence/__init__.py +10 -0
- ml_tools/ML_inference_sequence/_imprimir.py +8 -0
- ml_tools/{_core/_ML_sequence_inference.py → ML_inference_sequence/_sequence_inference.py} +11 -15
- ml_tools/ML_inference_vision/__init__.py +10 -0
- ml_tools/ML_inference_vision/_imprimir.py +8 -0
- ml_tools/{_core/_ML_vision_inference.py → ML_inference_vision/_vision_inference.py} +15 -19
- ml_tools/ML_models/__init__.py +32 -0
- ml_tools/{_core/_ML_models_advanced.py → ML_models/_advanced_models.py} +22 -18
- ml_tools/ML_models/_base_mlp_attention.py +198 -0
- ml_tools/{_core/_models_advanced_base.py → ML_models/_base_save_load.py} +73 -49
- ml_tools/ML_models/_dragon_tabular.py +248 -0
- ml_tools/ML_models/_imprimir.py +18 -0
- ml_tools/ML_models/_mlp_attention.py +134 -0
- ml_tools/{_core → ML_models}/_models_advanced_helpers.py +13 -13
- ml_tools/ML_models_sequence/__init__.py +10 -0
- ml_tools/ML_models_sequence/_imprimir.py +8 -0
- ml_tools/{_core/_ML_sequence_models.py → ML_models_sequence/_sequence_models.py} +5 -8
- ml_tools/ML_models_vision/__init__.py +29 -0
- ml_tools/ML_models_vision/_base_wrapper.py +254 -0
- ml_tools/ML_models_vision/_image_classification.py +182 -0
- ml_tools/ML_models_vision/_image_segmentation.py +108 -0
- ml_tools/ML_models_vision/_imprimir.py +16 -0
- ml_tools/ML_models_vision/_object_detection.py +135 -0
- ml_tools/ML_optimization/__init__.py +21 -0
- ml_tools/ML_optimization/_imprimir.py +13 -0
- ml_tools/{_core/_ML_optimization_pareto.py → ML_optimization/_multi_dragon.py} +18 -24
- ml_tools/ML_optimization/_single_dragon.py +203 -0
- ml_tools/{_core/_ML_optimization.py → ML_optimization/_single_manual.py} +75 -213
- ml_tools/{_core → ML_scaler}/_ML_scaler.py +8 -11
- ml_tools/ML_scaler/__init__.py +10 -0
- ml_tools/ML_scaler/_imprimir.py +8 -0
- ml_tools/ML_trainer/__init__.py +20 -0
- ml_tools/ML_trainer/_base_trainer.py +297 -0
- ml_tools/ML_trainer/_dragon_detection_trainer.py +402 -0
- ml_tools/ML_trainer/_dragon_sequence_trainer.py +540 -0
- ml_tools/ML_trainer/_dragon_trainer.py +1160 -0
- ml_tools/ML_trainer/_imprimir.py +10 -0
- ml_tools/{ML_utilities.py → ML_utilities/__init__.py} +14 -6
- ml_tools/ML_utilities/_artifact_finder.py +382 -0
- ml_tools/ML_utilities/_imprimir.py +16 -0
- ml_tools/ML_utilities/_inspection.py +325 -0
- ml_tools/ML_utilities/_train_tools.py +205 -0
- ml_tools/{ML_vision_transformers.py → ML_vision_transformers/__init__.py} +9 -6
- ml_tools/{_core/_ML_vision_transformers.py → ML_vision_transformers/_core_transforms.py} +11 -155
- ml_tools/ML_vision_transformers/_imprimir.py +14 -0
- ml_tools/ML_vision_transformers/_offline_augmentation.py +159 -0
- ml_tools/{_core/_PSO_optimization.py → PSO_optimization/_PSO.py} +58 -15
- ml_tools/{PSO_optimization.py → PSO_optimization/__init__.py} +5 -3
- ml_tools/PSO_optimization/_imprimir.py +10 -0
- ml_tools/SQL/__init__.py +7 -0
- ml_tools/{_core/_SQL.py → SQL/_dragon_SQL.py} +7 -11
- ml_tools/SQL/_imprimir.py +8 -0
- ml_tools/{_core → VIF}/_VIF_factor.py +5 -8
- ml_tools/{VIF_factor.py → VIF/__init__.py} +4 -2
- ml_tools/VIF/_imprimir.py +10 -0
- ml_tools/_core/__init__.py +7 -1
- ml_tools/_core/_logger.py +8 -18
- ml_tools/_core/_schema_load_ops.py +43 -0
- ml_tools/_core/_script_info.py +2 -2
- ml_tools/{data_exploration.py → data_exploration/__init__.py} +32 -16
- ml_tools/data_exploration/_analysis.py +214 -0
- ml_tools/data_exploration/_cleaning.py +566 -0
- ml_tools/data_exploration/_features.py +583 -0
- ml_tools/data_exploration/_imprimir.py +32 -0
- ml_tools/data_exploration/_plotting.py +487 -0
- ml_tools/data_exploration/_schema_ops.py +176 -0
- ml_tools/{ensemble_evaluation.py → ensemble_evaluation/__init__.py} +6 -4
- ml_tools/{_core → ensemble_evaluation}/_ensemble_evaluation.py +3 -7
- ml_tools/ensemble_evaluation/_imprimir.py +14 -0
- ml_tools/{ensemble_inference.py → ensemble_inference/__init__.py} +5 -3
- ml_tools/{_core → ensemble_inference}/_ensemble_inference.py +15 -18
- ml_tools/ensemble_inference/_imprimir.py +9 -0
- ml_tools/{ensemble_learning.py → ensemble_learning/__init__.py} +4 -6
- ml_tools/{_core → ensemble_learning}/_ensemble_learning.py +7 -10
- ml_tools/ensemble_learning/_imprimir.py +10 -0
- ml_tools/{excel_handler.py → excel_handler/__init__.py} +5 -3
- ml_tools/{_core → excel_handler}/_excel_handler.py +6 -10
- ml_tools/excel_handler/_imprimir.py +13 -0
- ml_tools/{keys.py → keys/__init__.py} +4 -1
- ml_tools/keys/_imprimir.py +11 -0
- ml_tools/{_core → keys}/_keys.py +2 -0
- ml_tools/{math_utilities.py → math_utilities/__init__.py} +5 -2
- ml_tools/math_utilities/_imprimir.py +11 -0
- ml_tools/{_core → math_utilities}/_math_utilities.py +1 -5
- ml_tools/{optimization_tools.py → optimization_tools/__init__.py} +9 -4
- ml_tools/optimization_tools/_imprimir.py +13 -0
- ml_tools/optimization_tools/_optimization_bounds.py +236 -0
- ml_tools/optimization_tools/_optimization_plots.py +218 -0
- ml_tools/{path_manager.py → path_manager/__init__.py} +6 -3
- ml_tools/{_core/_path_manager.py → path_manager/_dragonmanager.py} +11 -347
- ml_tools/path_manager/_imprimir.py +15 -0
- ml_tools/path_manager/_path_tools.py +346 -0
- ml_tools/plot_fonts/__init__.py +8 -0
- ml_tools/plot_fonts/_imprimir.py +8 -0
- ml_tools/{_core → plot_fonts}/_plot_fonts.py +2 -5
- ml_tools/schema/__init__.py +15 -0
- ml_tools/schema/_feature_schema.py +223 -0
- ml_tools/schema/_gui_schema.py +191 -0
- ml_tools/schema/_imprimir.py +10 -0
- ml_tools/{serde.py → serde/__init__.py} +4 -2
- ml_tools/serde/_imprimir.py +10 -0
- ml_tools/{_core → serde}/_serde.py +3 -8
- ml_tools/{utilities.py → utilities/__init__.py} +11 -6
- ml_tools/utilities/_imprimir.py +18 -0
- ml_tools/{_core/_utilities.py → utilities/_utility_save_load.py} +13 -190
- ml_tools/utilities/_utility_tools.py +192 -0
- dragon_ml_toolbox-19.14.0.dist-info/RECORD +0 -111
- ml_tools/ML_chaining_inference.py +0 -8
- ml_tools/ML_configuration.py +0 -86
- ml_tools/ML_configuration_pytab.py +0 -14
- ml_tools/ML_datasetmaster.py +0 -10
- ml_tools/ML_evaluation.py +0 -16
- ml_tools/ML_evaluation_multi.py +0 -12
- ml_tools/ML_finalize_handler.py +0 -8
- ml_tools/ML_inference.py +0 -12
- ml_tools/ML_models.py +0 -14
- ml_tools/ML_models_advanced.py +0 -14
- ml_tools/ML_models_pytab.py +0 -14
- ml_tools/ML_optimization.py +0 -14
- ml_tools/ML_optimization_pareto.py +0 -8
- ml_tools/ML_scaler.py +0 -8
- ml_tools/ML_sequence_datasetmaster.py +0 -8
- ml_tools/ML_sequence_evaluation.py +0 -10
- ml_tools/ML_sequence_inference.py +0 -8
- ml_tools/ML_sequence_models.py +0 -8
- ml_tools/ML_trainer.py +0 -12
- ml_tools/ML_vision_datasetmaster.py +0 -12
- ml_tools/ML_vision_evaluation.py +0 -10
- ml_tools/ML_vision_inference.py +0 -8
- ml_tools/ML_vision_models.py +0 -18
- ml_tools/SQL.py +0 -8
- ml_tools/_core/_ETL_cleaning.py +0 -694
- ml_tools/_core/_IO_tools.py +0 -498
- ml_tools/_core/_ML_callbacks.py +0 -702
- ml_tools/_core/_ML_configuration.py +0 -1332
- ml_tools/_core/_ML_configuration_pytab.py +0 -102
- ml_tools/_core/_ML_evaluation.py +0 -867
- ml_tools/_core/_ML_evaluation_multi.py +0 -544
- ml_tools/_core/_ML_inference.py +0 -646
- ml_tools/_core/_ML_models.py +0 -668
- ml_tools/_core/_ML_models_pytab.py +0 -693
- ml_tools/_core/_ML_trainer.py +0 -2323
- ml_tools/_core/_ML_utilities.py +0 -886
- ml_tools/_core/_ML_vision_models.py +0 -644
- ml_tools/_core/_data_exploration.py +0 -1909
- ml_tools/_core/_optimization_tools.py +0 -493
- ml_tools/_core/_schema.py +0 -359
- ml_tools/plot_fonts.py +0 -8
- ml_tools/schema.py +0 -12
- {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/WHEEL +0 -0
- {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE +0 -0
- {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE-THIRD-PARTY.md +0 -0
- {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
from typing import Union,
|
|
1
|
+
from typing import Union, Type, Callable, Any
|
|
2
2
|
from PIL import ImageOps, Image
|
|
3
3
|
from torchvision import transforms
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import json
|
|
6
6
|
import random
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from .
|
|
10
|
-
from
|
|
11
|
-
from ._path_manager import make_fullpath
|
|
8
|
+
from .._core import get_logger
|
|
9
|
+
from ..keys._keys import VisionTransformRecipeKeys
|
|
10
|
+
from ..path_manager import make_fullpath
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
_LOGGER = get_logger("Transformers")
|
|
@@ -20,7 +19,8 @@ __all__ = [
|
|
|
20
19
|
"LetterboxResize",
|
|
21
20
|
"HistogramEqualization",
|
|
22
21
|
"RandomHistogramEqualization",
|
|
23
|
-
"
|
|
22
|
+
"_save_recipe",
|
|
23
|
+
"_load_recipe_and_build_transform",
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
# --- Custom Vision Transform Class ---
|
|
@@ -82,7 +82,7 @@ class LetterboxResize:
|
|
|
82
82
|
"""
|
|
83
83
|
def __init__(
|
|
84
84
|
self,
|
|
85
|
-
target_size: Union[int,
|
|
85
|
+
target_size: Union[int, tuple[int, int]],
|
|
86
86
|
pad_color: Union[str, int] = "black"
|
|
87
87
|
) -> None:
|
|
88
88
|
|
|
@@ -189,7 +189,7 @@ class RandomHistogramEqualization:
|
|
|
189
189
|
|
|
190
190
|
#############################################################
|
|
191
191
|
#NOTE: Add custom transforms.
|
|
192
|
-
TRANSFORM_REGISTRY:
|
|
192
|
+
TRANSFORM_REGISTRY: dict[str, Type[Callable]] = {
|
|
193
193
|
"ResizeAspectFill": ResizeAspectFill,
|
|
194
194
|
"LetterboxResize": LetterboxResize,
|
|
195
195
|
"HistogramEqualization": HistogramEqualization,
|
|
@@ -198,153 +198,12 @@ TRANSFORM_REGISTRY: Dict[str, Type[Callable]] = {
|
|
|
198
198
|
#############################################################
|
|
199
199
|
|
|
200
200
|
|
|
201
|
-
def
|
|
202
|
-
input_directory: Union[str, Path],
|
|
203
|
-
output_directory: Union[str, Path],
|
|
204
|
-
results_per_image: int,
|
|
205
|
-
recipe: Optional[Dict[str, Any]] = None,
|
|
206
|
-
save_format: Literal["WEBP", "JPEG", "PNG", "BMP", "TIF"] = "WEBP",
|
|
207
|
-
save_quality: int = 80
|
|
208
|
-
) -> None:
|
|
209
|
-
"""
|
|
210
|
-
Reads all valid images from an input directory, applies augmentations,
|
|
211
|
-
and saves the new images to an output directory (offline augmentation).
|
|
212
|
-
|
|
213
|
-
Skips subdirectories in the input path.
|
|
214
|
-
|
|
215
|
-
Args:
|
|
216
|
-
input_directory (Union[str, Path]): Path to the directory of source images.
|
|
217
|
-
output_directory (Union[str, Path]): Path to save the augmented images.
|
|
218
|
-
results_per_image (int): The number of augmented versions to create
|
|
219
|
-
for each source image.
|
|
220
|
-
recipe (Optional[Dict[str, Any]]): A transform recipe dictionary. If None,
|
|
221
|
-
a default set of strong, random
|
|
222
|
-
augmentations will be used.
|
|
223
|
-
save_format (str): The format to save images (e.g., "WEBP", "JPEG", "PNG").
|
|
224
|
-
Defaults to "WEBP" for good compression.
|
|
225
|
-
save_quality (int): The quality for lossy formats (1-100). Defaults to 80.
|
|
226
|
-
"""
|
|
227
|
-
VALID_IMG_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tif', '.tiff')
|
|
228
|
-
|
|
229
|
-
# --- 1. Validate Paths ---
|
|
230
|
-
in_path = make_fullpath(input_directory, enforce="directory")
|
|
231
|
-
out_path = make_fullpath(output_directory, make=True, enforce="directory")
|
|
232
|
-
|
|
233
|
-
_LOGGER.info(f"Starting offline augmentation:\n\tInput: {in_path}\n\tOutput: {out_path}")
|
|
234
|
-
|
|
235
|
-
# --- 2. Find Images ---
|
|
236
|
-
image_files = [
|
|
237
|
-
f for f in in_path.iterdir()
|
|
238
|
-
if f.is_file() and f.suffix.lower() in VALID_IMG_EXTENSIONS
|
|
239
|
-
]
|
|
240
|
-
|
|
241
|
-
if not image_files:
|
|
242
|
-
_LOGGER.warning(f"No valid image files found in {in_path}.")
|
|
243
|
-
return
|
|
244
|
-
|
|
245
|
-
_LOGGER.info(f"Found {len(image_files)} images to process.")
|
|
246
|
-
|
|
247
|
-
# --- 3. Define Transform Pipeline ---
|
|
248
|
-
transform_pipeline: transforms.Compose
|
|
249
|
-
|
|
250
|
-
if recipe:
|
|
251
|
-
_LOGGER.info("Building transformations from provided recipe.")
|
|
252
|
-
try:
|
|
253
|
-
transform_pipeline = _build_transform_from_recipe(recipe)
|
|
254
|
-
except Exception as e:
|
|
255
|
-
_LOGGER.error(f"Failed to build transform from recipe: {e}")
|
|
256
|
-
return
|
|
257
|
-
else:
|
|
258
|
-
_LOGGER.info("No recipe provided. Using default random augmentation pipeline.")
|
|
259
|
-
# Default "random" pipeline
|
|
260
|
-
transform_pipeline = transforms.Compose([
|
|
261
|
-
transforms.RandomResizedCrop(256, scale=(0.4, 1.0)),
|
|
262
|
-
transforms.RandomHorizontalFlip(p=0.5),
|
|
263
|
-
transforms.RandomRotation(degrees=90),
|
|
264
|
-
transforms.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3, hue=0.15),
|
|
265
|
-
transforms.RandomPerspective(distortion_scale=0.2, p=0.4),
|
|
266
|
-
transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),
|
|
267
|
-
transforms.RandomApply([
|
|
268
|
-
transforms.GaussianBlur(kernel_size=3)
|
|
269
|
-
], p=0.3)
|
|
270
|
-
])
|
|
271
|
-
|
|
272
|
-
# --- 4. Process Images ---
|
|
273
|
-
total_saved = 0
|
|
274
|
-
format_upper = save_format.upper()
|
|
275
|
-
|
|
276
|
-
for img_path in image_files:
|
|
277
|
-
_LOGGER.debug(f"Processing {img_path.name}...")
|
|
278
|
-
try:
|
|
279
|
-
original_image = Image.open(img_path).convert("RGB")
|
|
280
|
-
|
|
281
|
-
for i in range(results_per_image):
|
|
282
|
-
new_stem = f"{img_path.stem}_aug_{i+1:03d}"
|
|
283
|
-
output_path = out_path / f"{new_stem}.{format_upper.lower()}"
|
|
284
|
-
|
|
285
|
-
# Apply transform
|
|
286
|
-
transformed_image = transform_pipeline(original_image)
|
|
287
|
-
|
|
288
|
-
# Save
|
|
289
|
-
transformed_image.save(
|
|
290
|
-
output_path,
|
|
291
|
-
format=format_upper,
|
|
292
|
-
quality=save_quality,
|
|
293
|
-
optimize=True # Add optimize flag
|
|
294
|
-
)
|
|
295
|
-
total_saved += 1
|
|
296
|
-
|
|
297
|
-
except Exception as e:
|
|
298
|
-
_LOGGER.warning(f"Failed to process or save augmentations for {img_path.name}: {e}")
|
|
299
|
-
|
|
300
|
-
_LOGGER.info(f"Offline augmentation complete. Saved {total_saved} new images.")
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
def _build_transform_from_recipe(recipe: Dict[str, Any]) -> transforms.Compose:
|
|
304
|
-
"""Internal helper to build a transform pipeline from a recipe dict."""
|
|
305
|
-
pipeline_steps: List[Callable] = []
|
|
306
|
-
|
|
307
|
-
if VisionTransformRecipeKeys.PIPELINE not in recipe:
|
|
308
|
-
_LOGGER.error("Recipe dict is invalid: missing 'pipeline' key.")
|
|
309
|
-
raise ValueError("Invalid recipe format.")
|
|
310
|
-
|
|
311
|
-
for step in recipe[VisionTransformRecipeKeys.PIPELINE]:
|
|
312
|
-
t_name = step.get(VisionTransformRecipeKeys.NAME)
|
|
313
|
-
t_kwargs = step.get(VisionTransformRecipeKeys.KWARGS, {})
|
|
314
|
-
|
|
315
|
-
if not t_name:
|
|
316
|
-
_LOGGER.error(f"Invalid transform step, missing 'name': {step}")
|
|
317
|
-
continue
|
|
318
|
-
|
|
319
|
-
transform_class: Any = None
|
|
320
|
-
|
|
321
|
-
# 1. Check standard torchvision transforms
|
|
322
|
-
if hasattr(transforms, t_name):
|
|
323
|
-
transform_class = getattr(transforms, t_name)
|
|
324
|
-
# 2. Check custom transforms
|
|
325
|
-
elif t_name in TRANSFORM_REGISTRY:
|
|
326
|
-
transform_class = TRANSFORM_REGISTRY[t_name]
|
|
327
|
-
# 3. Not found
|
|
328
|
-
else:
|
|
329
|
-
_LOGGER.error(f"Unknown transform '{t_name}' in recipe. Not found in torchvision.transforms or TRANSFORM_REGISTRY.")
|
|
330
|
-
raise ValueError(f"Unknown transform name: {t_name}")
|
|
331
|
-
|
|
332
|
-
# Instantiate the transform
|
|
333
|
-
try:
|
|
334
|
-
pipeline_steps.append(transform_class(**t_kwargs))
|
|
335
|
-
except Exception as e:
|
|
336
|
-
_LOGGER.error(f"Failed to instantiate transform '{t_name}' with kwargs {t_kwargs}: {e}")
|
|
337
|
-
raise
|
|
338
|
-
|
|
339
|
-
return transforms.Compose(pipeline_steps)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
def _save_recipe(recipe: Dict[str, Any], filepath: Path) -> None:
|
|
201
|
+
def _save_recipe(recipe: dict[str, Any], filepath: Path) -> None:
|
|
343
202
|
"""
|
|
344
203
|
Saves a transform recipe dictionary to a JSON file.
|
|
345
204
|
|
|
346
205
|
Args:
|
|
347
|
-
recipe (
|
|
206
|
+
recipe (dict[str, Any]): The recipe dictionary to save.
|
|
348
207
|
filepath (str): The path to the output .json file.
|
|
349
208
|
"""
|
|
350
209
|
final_filepath = filepath.with_suffix(".json")
|
|
@@ -383,7 +242,7 @@ def _load_recipe_and_build_transform(filepath: Union[str,Path]) -> transforms.Co
|
|
|
383
242
|
_LOGGER.error(f"Failed to load recipe from '{final_filepath}': {e}")
|
|
384
243
|
raise
|
|
385
244
|
|
|
386
|
-
pipeline_steps:
|
|
245
|
+
pipeline_steps: list[Callable] = []
|
|
387
246
|
|
|
388
247
|
if VisionTransformRecipeKeys.PIPELINE not in recipe:
|
|
389
248
|
_LOGGER.error("Recipe file is invalid: missing 'pipeline' key.")
|
|
@@ -416,6 +275,3 @@ def _load_recipe_and_build_transform(filepath: Union[str,Path]) -> transforms.Co
|
|
|
416
275
|
_LOGGER.info(f"Successfully loaded and built transform pipeline from '{final_filepath.name}'.")
|
|
417
276
|
return transforms.Compose(pipeline_steps)
|
|
418
277
|
|
|
419
|
-
|
|
420
|
-
def info():
|
|
421
|
-
_script_info(__all__)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .._core import _imprimir_disponibles
|
|
2
|
+
|
|
3
|
+
_GRUPOS = [
|
|
4
|
+
# Custom Transforms
|
|
5
|
+
"ResizeAspectFill",
|
|
6
|
+
"LetterboxResize",
|
|
7
|
+
"HistogramEqualization",
|
|
8
|
+
"RandomHistogramEqualization",
|
|
9
|
+
# Offline Augmentation
|
|
10
|
+
"create_offline_augmentations",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
def info():
|
|
14
|
+
_imprimir_disponibles(_GRUPOS)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
from typing import Union, Callable, Optional, Any, Literal
|
|
2
|
+
from PIL import Image
|
|
3
|
+
from torchvision import transforms
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .._core import get_logger
|
|
7
|
+
from ..keys._keys import VisionTransformRecipeKeys
|
|
8
|
+
from ..path_manager import make_fullpath
|
|
9
|
+
|
|
10
|
+
from ._core_transforms import TRANSFORM_REGISTRY
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_LOGGER = get_logger("Offline Augmentation")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"create_offline_augmentations"
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
def create_offline_augmentations(
|
|
21
|
+
input_directory: Union[str, Path],
|
|
22
|
+
output_directory: Union[str, Path],
|
|
23
|
+
results_per_image: int,
|
|
24
|
+
recipe: Optional[dict[str, Any]] = None,
|
|
25
|
+
save_format: Literal["WEBP", "JPEG", "PNG", "BMP", "TIF"] = "WEBP",
|
|
26
|
+
save_quality: int = 80
|
|
27
|
+
) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Reads all valid images from an input directory, applies augmentations,
|
|
30
|
+
and saves the new images to an output directory (offline augmentation).
|
|
31
|
+
|
|
32
|
+
Skips subdirectories in the input path.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
input_directory (Union[str, Path]): Path to the directory of source images.
|
|
36
|
+
output_directory (Union[str, Path]): Path to save the augmented images.
|
|
37
|
+
results_per_image (int): The number of augmented versions to create
|
|
38
|
+
for each source image.
|
|
39
|
+
recipe (Optional[Dict[str, Any]]): A transform recipe dictionary. If None,
|
|
40
|
+
a default set of strong, random
|
|
41
|
+
augmentations will be used.
|
|
42
|
+
save_format (str): The format to save images (e.g., "WEBP", "JPEG", "PNG").
|
|
43
|
+
Defaults to "WEBP" for good compression.
|
|
44
|
+
save_quality (int): The quality for lossy formats (1-100). Defaults to 80.
|
|
45
|
+
"""
|
|
46
|
+
VALID_IMG_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tif', '.tiff')
|
|
47
|
+
|
|
48
|
+
# --- 1. Validate Paths ---
|
|
49
|
+
in_path = make_fullpath(input_directory, enforce="directory")
|
|
50
|
+
out_path = make_fullpath(output_directory, make=True, enforce="directory")
|
|
51
|
+
|
|
52
|
+
_LOGGER.info(f"Starting offline augmentation:\n\tInput: {in_path}\n\tOutput: {out_path}")
|
|
53
|
+
|
|
54
|
+
# --- 2. Find Images ---
|
|
55
|
+
image_files = [
|
|
56
|
+
f for f in in_path.iterdir()
|
|
57
|
+
if f.is_file() and f.suffix.lower() in VALID_IMG_EXTENSIONS
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
if not image_files:
|
|
61
|
+
_LOGGER.warning(f"No valid image files found in {in_path}.")
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
_LOGGER.info(f"Found {len(image_files)} images to process.")
|
|
65
|
+
|
|
66
|
+
# --- 3. Define Transform Pipeline ---
|
|
67
|
+
transform_pipeline: transforms.Compose
|
|
68
|
+
|
|
69
|
+
if recipe:
|
|
70
|
+
_LOGGER.info("Building transformations from provided recipe.")
|
|
71
|
+
try:
|
|
72
|
+
transform_pipeline = _build_transform_from_recipe(recipe)
|
|
73
|
+
except Exception as e:
|
|
74
|
+
_LOGGER.error(f"Failed to build transform from recipe: {e}")
|
|
75
|
+
return
|
|
76
|
+
else:
|
|
77
|
+
_LOGGER.info("No recipe provided. Using default random augmentation pipeline.")
|
|
78
|
+
# Default "random" pipeline
|
|
79
|
+
transform_pipeline = transforms.Compose([
|
|
80
|
+
transforms.RandomResizedCrop(256, scale=(0.4, 1.0)),
|
|
81
|
+
transforms.RandomHorizontalFlip(p=0.5),
|
|
82
|
+
transforms.RandomRotation(degrees=90),
|
|
83
|
+
transforms.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3, hue=0.15),
|
|
84
|
+
transforms.RandomPerspective(distortion_scale=0.2, p=0.4),
|
|
85
|
+
transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),
|
|
86
|
+
transforms.RandomApply([
|
|
87
|
+
transforms.GaussianBlur(kernel_size=3)
|
|
88
|
+
], p=0.3)
|
|
89
|
+
])
|
|
90
|
+
|
|
91
|
+
# --- 4. Process Images ---
|
|
92
|
+
total_saved = 0
|
|
93
|
+
format_upper = save_format.upper()
|
|
94
|
+
|
|
95
|
+
for img_path in image_files:
|
|
96
|
+
_LOGGER.debug(f"Processing {img_path.name}...")
|
|
97
|
+
try:
|
|
98
|
+
original_image = Image.open(img_path).convert("RGB")
|
|
99
|
+
|
|
100
|
+
for i in range(results_per_image):
|
|
101
|
+
new_stem = f"{img_path.stem}_aug_{i+1:03d}"
|
|
102
|
+
output_path = out_path / f"{new_stem}.{format_upper.lower()}"
|
|
103
|
+
|
|
104
|
+
# Apply transform
|
|
105
|
+
transformed_image = transform_pipeline(original_image)
|
|
106
|
+
|
|
107
|
+
# Save
|
|
108
|
+
transformed_image.save(
|
|
109
|
+
output_path,
|
|
110
|
+
format=format_upper,
|
|
111
|
+
quality=save_quality,
|
|
112
|
+
optimize=True # Add optimize flag
|
|
113
|
+
)
|
|
114
|
+
total_saved += 1
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
_LOGGER.warning(f"Failed to process or save augmentations for {img_path.name}: {e}")
|
|
118
|
+
|
|
119
|
+
_LOGGER.info(f"Offline augmentation complete. Saved {total_saved} new images.")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _build_transform_from_recipe(recipe: dict[str, Any]) -> transforms.Compose:
|
|
123
|
+
"""Internal helper to build a transform pipeline from a recipe dict."""
|
|
124
|
+
pipeline_steps: list[Callable] = []
|
|
125
|
+
|
|
126
|
+
if VisionTransformRecipeKeys.PIPELINE not in recipe:
|
|
127
|
+
_LOGGER.error("Recipe dict is invalid: missing 'pipeline' key.")
|
|
128
|
+
raise ValueError("Invalid recipe format.")
|
|
129
|
+
|
|
130
|
+
for step in recipe[VisionTransformRecipeKeys.PIPELINE]:
|
|
131
|
+
t_name = step.get(VisionTransformRecipeKeys.NAME)
|
|
132
|
+
t_kwargs = step.get(VisionTransformRecipeKeys.KWARGS, {})
|
|
133
|
+
|
|
134
|
+
if not t_name:
|
|
135
|
+
_LOGGER.error(f"Invalid transform step, missing 'name': {step}")
|
|
136
|
+
continue
|
|
137
|
+
|
|
138
|
+
transform_class: Any = None
|
|
139
|
+
|
|
140
|
+
# 1. Check standard torchvision transforms
|
|
141
|
+
if hasattr(transforms, t_name):
|
|
142
|
+
transform_class = getattr(transforms, t_name)
|
|
143
|
+
# 2. Check custom transforms
|
|
144
|
+
elif t_name in TRANSFORM_REGISTRY:
|
|
145
|
+
transform_class = TRANSFORM_REGISTRY[t_name]
|
|
146
|
+
# 3. Not found
|
|
147
|
+
else:
|
|
148
|
+
_LOGGER.error(f"Unknown transform '{t_name}' in recipe. Not found in torchvision.transforms or TRANSFORM_REGISTRY.")
|
|
149
|
+
raise ValueError(f"Unknown transform name: {t_name}")
|
|
150
|
+
|
|
151
|
+
# Instantiate the transform
|
|
152
|
+
try:
|
|
153
|
+
pipeline_steps.append(transform_class(**t_kwargs))
|
|
154
|
+
except Exception as e:
|
|
155
|
+
_LOGGER.error(f"Failed to instantiate transform '{t_name}' with kwargs {t_kwargs}: {e}")
|
|
156
|
+
raise
|
|
157
|
+
|
|
158
|
+
return transforms.Compose(pipeline_steps)
|
|
159
|
+
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
import xgboost as xgb
|
|
4
5
|
import lightgbm as lgb
|
|
5
|
-
from typing import Literal, Union,
|
|
6
|
+
from typing import Literal, Union, Optional
|
|
6
7
|
from copy import deepcopy
|
|
7
8
|
import torch
|
|
8
9
|
from tqdm import trange
|
|
9
10
|
from contextlib import nullcontext
|
|
10
11
|
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
from
|
|
15
|
-
from ._keys import EnsembleKeys
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from ._optimization_tools import _save_result
|
|
12
|
+
from ..serde import deserialize_object
|
|
13
|
+
from ..SQL import DragonSQL
|
|
14
|
+
|
|
15
|
+
from ..math_utilities import threshold_binary_values, threshold_binary_values_batch
|
|
16
|
+
from ..keys._keys import EnsembleKeys
|
|
17
|
+
from ..path_manager import sanitize_filename, make_fullpath, list_files_by_extension
|
|
18
|
+
from .._core import get_logger
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
_LOGGER = get_logger("PSO")
|
|
@@ -247,7 +247,7 @@ def run_pso(lower_boundaries: list[float],
|
|
|
247
247
|
swarm_size: int=200,
|
|
248
248
|
max_iterations: int=3000,
|
|
249
249
|
random_state: int=101,
|
|
250
|
-
post_hoc_analysis: Optional[int]=20) -> Optional[
|
|
250
|
+
post_hoc_analysis: Optional[int]=20) -> Optional[tuple[dict[str, float], dict[str, float]]]:
|
|
251
251
|
"""
|
|
252
252
|
Executes Particle Swarm Optimization (PSO) to optimize a given objective function and saves the results as a CSV file.
|
|
253
253
|
|
|
@@ -384,6 +384,54 @@ def run_pso(lower_boundaries: list[float],
|
|
|
384
384
|
return None
|
|
385
385
|
|
|
386
386
|
|
|
387
|
+
def _save_result(
|
|
388
|
+
result_dict: dict,
|
|
389
|
+
save_format: Literal['csv', 'sqlite', 'both'],
|
|
390
|
+
csv_path: Path,
|
|
391
|
+
db_manager: Optional[DragonSQL] = None,
|
|
392
|
+
db_table_name: Optional[str] = None,
|
|
393
|
+
categorical_mappings: Optional[dict[str, dict[str, int]]] = None
|
|
394
|
+
):
|
|
395
|
+
"""
|
|
396
|
+
Private helper to handle saving a single result to CSV, SQLite, or both.
|
|
397
|
+
|
|
398
|
+
If `categorical_mappings` is provided, it will reverse-map integer values
|
|
399
|
+
to their string representations before saving.
|
|
400
|
+
"""
|
|
401
|
+
# --- Reverse Mapping Logic ---
|
|
402
|
+
# Create a copy to hold the values to be saved
|
|
403
|
+
save_dict = result_dict.copy()
|
|
404
|
+
|
|
405
|
+
if categorical_mappings:
|
|
406
|
+
for feature_name, mapping in categorical_mappings.items():
|
|
407
|
+
if feature_name in save_dict:
|
|
408
|
+
# Create a reverse map {0: 'Category_A', 1: 'Category_B'}
|
|
409
|
+
reverse_map = {idx: name for name, idx in mapping.items()}
|
|
410
|
+
|
|
411
|
+
# Get the integer value from the results (e.g., 0)
|
|
412
|
+
int_value = save_dict[feature_name]
|
|
413
|
+
|
|
414
|
+
# Find the corresponding string (e.g., 'Category_A')
|
|
415
|
+
# Use .get() for safety, defaulting to the original value if not found
|
|
416
|
+
string_value = reverse_map.get(int_value, int_value)
|
|
417
|
+
|
|
418
|
+
# Update the dictionary that will be saved
|
|
419
|
+
save_dict[feature_name] = string_value
|
|
420
|
+
|
|
421
|
+
# Save to CSV
|
|
422
|
+
if save_format in ['csv', 'both']:
|
|
423
|
+
df_row = pd.DataFrame([save_dict])
|
|
424
|
+
file_exists = csv_path.exists()
|
|
425
|
+
df_row.to_csv(csv_path, mode='a', index=False, header=not file_exists)
|
|
426
|
+
|
|
427
|
+
# Save to SQLite
|
|
428
|
+
if save_format in ['sqlite', 'both']:
|
|
429
|
+
if db_manager and db_table_name:
|
|
430
|
+
db_manager.insert_row(db_table_name, save_dict)
|
|
431
|
+
else:
|
|
432
|
+
_LOGGER.warning("SQLite saving requested but db_manager or table_name not provided.")
|
|
433
|
+
|
|
434
|
+
|
|
387
435
|
def _pso(func: ObjectiveFunction,
|
|
388
436
|
lb: np.ndarray,
|
|
389
437
|
ub: np.ndarray,
|
|
@@ -536,8 +584,3 @@ def _pso(func: ObjectiveFunction,
|
|
|
536
584
|
else:
|
|
537
585
|
return best_position, best_score
|
|
538
586
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
def info():
|
|
543
|
-
_script_info(__all__)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from ._PSO import (
|
|
2
2
|
ObjectiveFunction,
|
|
3
3
|
multiple_objective_functions_from_dir,
|
|
4
|
-
run_pso
|
|
5
|
-
info
|
|
4
|
+
run_pso
|
|
6
5
|
)
|
|
7
6
|
|
|
7
|
+
from ._imprimir import info
|
|
8
|
+
|
|
9
|
+
|
|
8
10
|
__all__ = [
|
|
9
11
|
"ObjectiveFunction",
|
|
10
12
|
"multiple_objective_functions_from_dir",
|
ml_tools/SQL/__init__.py
ADDED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import sqlite3
|
|
2
2
|
import pandas as pd
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Union,
|
|
4
|
+
from typing import Union, Any, Optional, Literal
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from ._path_manager import make_fullpath, sanitize_filename
|
|
6
|
+
from .._core import get_logger
|
|
7
|
+
from ..path_manager import make_fullpath, sanitize_filename
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
_LOGGER = get_logger("DragonSQL")
|
|
@@ -80,7 +79,7 @@ class DragonSQL:
|
|
|
80
79
|
self.conn.close()
|
|
81
80
|
_LOGGER.info(f"Database connection closed: {self.db_path.name}")
|
|
82
81
|
|
|
83
|
-
def create_table(self, table_name: str, schema:
|
|
82
|
+
def create_table(self, table_name: str, schema: dict[str, str], if_not_exists: bool = True):
|
|
84
83
|
"""
|
|
85
84
|
Creates a new table in the database based on a provided schema.
|
|
86
85
|
|
|
@@ -109,7 +108,7 @@ class DragonSQL:
|
|
|
109
108
|
_LOGGER.info(f"➡️ Executing: {query}")
|
|
110
109
|
self.cursor.execute(query)
|
|
111
110
|
|
|
112
|
-
def insert_row(self, table_name: str, data:
|
|
111
|
+
def insert_row(self, table_name: str, data: dict[str, Any]):
|
|
113
112
|
"""
|
|
114
113
|
Inserts a single row of data into the specified table.
|
|
115
114
|
|
|
@@ -175,7 +174,7 @@ class DragonSQL:
|
|
|
175
174
|
|
|
176
175
|
self.cursor.execute(query, params if params else ())
|
|
177
176
|
|
|
178
|
-
def insert_many(self, table_name: str, data:
|
|
177
|
+
def insert_many(self, table_name: str, data: list[dict[str, Any]]):
|
|
179
178
|
"""
|
|
180
179
|
Inserts multiple rows into the specified table in a single, efficient transaction.
|
|
181
180
|
|
|
@@ -239,7 +238,7 @@ class DragonSQL:
|
|
|
239
238
|
)
|
|
240
239
|
_LOGGER.info(f"➡️ Wrote {len(df)} rows from DataFrame to table '{table_name}' using mode '{if_exists}'.")
|
|
241
240
|
|
|
242
|
-
def list_tables(self) ->
|
|
241
|
+
def list_tables(self) -> list[str]:
|
|
243
242
|
"""Returns a list of all table names in the database."""
|
|
244
243
|
if not self.cursor:
|
|
245
244
|
_LOGGER.error("Database connection is not open.")
|
|
@@ -300,6 +299,3 @@ class DragonSQL:
|
|
|
300
299
|
else:
|
|
301
300
|
_LOGGER.error("Cannot commit: Database connection is not open.")
|
|
302
301
|
|
|
303
|
-
|
|
304
|
-
def info():
|
|
305
|
-
_script_info(__all__)
|
|
@@ -7,10 +7,10 @@ from statsmodels.tools.tools import add_constant
|
|
|
7
7
|
import warnings
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
from
|
|
10
|
+
from ..utilities import yield_dataframes_from_dir, save_dataframe_filename
|
|
11
|
+
|
|
12
|
+
from ..path_manager import sanitize_filename, make_fullpath
|
|
13
|
+
from .._core import get_logger
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
_LOGGER = get_logger("VIF")
|
|
@@ -31,7 +31,7 @@ def compute_vif(
|
|
|
31
31
|
save_dir: Optional[Union[str,Path]] = None,
|
|
32
32
|
filename: Optional[str] = None,
|
|
33
33
|
fontsize: int = 14,
|
|
34
|
-
show_plot: bool =
|
|
34
|
+
show_plot: bool = False
|
|
35
35
|
) -> pd.DataFrame:
|
|
36
36
|
"""
|
|
37
37
|
Computes Variance Inflation Factors (VIF) for numeric columns in a DataFrame. Optionally, generates a bar plot of VIF values.
|
|
@@ -234,6 +234,3 @@ def compute_vif_multi(input_directory: Union[str, Path],
|
|
|
234
234
|
if len(dropped_cols) > 0:
|
|
235
235
|
save_dataframe_filename(df=result_df, save_dir=output_dataset_path, filename=new_filename)
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
def info():
|
|
239
|
-
_script_info(__all__)
|