dragon-ml-toolbox 19.13.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.
Files changed (219) hide show
  1. {dragon_ml_toolbox-19.13.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/METADATA +29 -46
  2. dragon_ml_toolbox-20.0.0.dist-info/RECORD +178 -0
  3. ml_tools/{ETL_cleaning.py → ETL_cleaning/__init__.py} +13 -5
  4. ml_tools/ETL_cleaning/_basic_clean.py +351 -0
  5. ml_tools/ETL_cleaning/_clean_tools.py +128 -0
  6. ml_tools/ETL_cleaning/_dragon_cleaner.py +245 -0
  7. ml_tools/ETL_cleaning/_imprimir.py +13 -0
  8. ml_tools/{ETL_engineering.py → ETL_engineering/__init__.py} +8 -4
  9. ml_tools/ETL_engineering/_dragon_engineering.py +261 -0
  10. ml_tools/ETL_engineering/_imprimir.py +24 -0
  11. ml_tools/{_core/_ETL_engineering.py → ETL_engineering/_transforms.py} +14 -267
  12. ml_tools/{_core → GUI_tools}/_GUI_tools.py +37 -40
  13. ml_tools/{GUI_tools.py → GUI_tools/__init__.py} +7 -5
  14. ml_tools/GUI_tools/_imprimir.py +12 -0
  15. ml_tools/IO_tools/_IO_loggers.py +235 -0
  16. ml_tools/IO_tools/_IO_save_load.py +151 -0
  17. ml_tools/IO_tools/_IO_utils.py +140 -0
  18. ml_tools/{IO_tools.py → IO_tools/__init__.py} +13 -5
  19. ml_tools/IO_tools/_imprimir.py +14 -0
  20. ml_tools/MICE/_MICE_imputation.py +132 -0
  21. ml_tools/{MICE_imputation.py → MICE/__init__.py} +6 -7
  22. ml_tools/{_core/_MICE_imputation.py → MICE/_dragon_mice.py} +243 -322
  23. ml_tools/MICE/_imprimir.py +11 -0
  24. ml_tools/{ML_callbacks.py → ML_callbacks/__init__.py} +12 -4
  25. ml_tools/ML_callbacks/_base.py +101 -0
  26. ml_tools/ML_callbacks/_checkpoint.py +232 -0
  27. ml_tools/ML_callbacks/_early_stop.py +208 -0
  28. ml_tools/ML_callbacks/_imprimir.py +12 -0
  29. ml_tools/ML_callbacks/_scheduler.py +197 -0
  30. ml_tools/{ML_chaining_utilities.py → ML_chain/__init__.py} +8 -3
  31. ml_tools/{_core/_ML_chaining_utilities.py → ML_chain/_chaining_tools.py} +5 -129
  32. ml_tools/ML_chain/_dragon_chain.py +140 -0
  33. ml_tools/ML_chain/_imprimir.py +11 -0
  34. ml_tools/ML_configuration/__init__.py +90 -0
  35. ml_tools/ML_configuration/_base_model_config.py +69 -0
  36. ml_tools/ML_configuration/_finalize.py +366 -0
  37. ml_tools/ML_configuration/_imprimir.py +47 -0
  38. ml_tools/ML_configuration/_metrics.py +593 -0
  39. ml_tools/ML_configuration/_models.py +206 -0
  40. ml_tools/ML_configuration/_training.py +124 -0
  41. ml_tools/ML_datasetmaster/__init__.py +28 -0
  42. ml_tools/ML_datasetmaster/_base_datasetmaster.py +337 -0
  43. ml_tools/{_core/_ML_datasetmaster.py → ML_datasetmaster/_datasetmaster.py} +9 -329
  44. ml_tools/ML_datasetmaster/_imprimir.py +15 -0
  45. ml_tools/{_core/_ML_sequence_datasetmaster.py → ML_datasetmaster/_sequence_datasetmaster.py} +13 -15
  46. ml_tools/{_core/_ML_vision_datasetmaster.py → ML_datasetmaster/_vision_datasetmaster.py} +63 -65
  47. ml_tools/ML_evaluation/__init__.py +53 -0
  48. ml_tools/ML_evaluation/_classification.py +629 -0
  49. ml_tools/ML_evaluation/_feature_importance.py +409 -0
  50. ml_tools/ML_evaluation/_imprimir.py +25 -0
  51. ml_tools/ML_evaluation/_loss.py +92 -0
  52. ml_tools/ML_evaluation/_regression.py +273 -0
  53. ml_tools/{_core/_ML_sequence_evaluation.py → ML_evaluation/_sequence.py} +8 -11
  54. ml_tools/{_core/_ML_vision_evaluation.py → ML_evaluation/_vision.py} +12 -17
  55. ml_tools/{_core → ML_evaluation_captum}/_ML_evaluation_captum.py +11 -38
  56. ml_tools/{ML_evaluation_captum.py → ML_evaluation_captum/__init__.py} +6 -4
  57. ml_tools/ML_evaluation_captum/_imprimir.py +10 -0
  58. ml_tools/{_core → ML_finalize_handler}/_ML_finalize_handler.py +3 -7
  59. ml_tools/ML_finalize_handler/__init__.py +10 -0
  60. ml_tools/ML_finalize_handler/_imprimir.py +8 -0
  61. ml_tools/ML_inference/__init__.py +22 -0
  62. ml_tools/ML_inference/_base_inference.py +166 -0
  63. ml_tools/{_core/_ML_chaining_inference.py → ML_inference/_chain_inference.py} +14 -17
  64. ml_tools/ML_inference/_dragon_inference.py +332 -0
  65. ml_tools/ML_inference/_imprimir.py +11 -0
  66. ml_tools/ML_inference/_multi_inference.py +180 -0
  67. ml_tools/ML_inference_sequence/__init__.py +10 -0
  68. ml_tools/ML_inference_sequence/_imprimir.py +8 -0
  69. ml_tools/{_core/_ML_sequence_inference.py → ML_inference_sequence/_sequence_inference.py} +11 -15
  70. ml_tools/ML_inference_vision/__init__.py +10 -0
  71. ml_tools/ML_inference_vision/_imprimir.py +8 -0
  72. ml_tools/{_core/_ML_vision_inference.py → ML_inference_vision/_vision_inference.py} +15 -19
  73. ml_tools/ML_models/__init__.py +32 -0
  74. ml_tools/{_core/_ML_models_advanced.py → ML_models/_advanced_models.py} +22 -18
  75. ml_tools/ML_models/_base_mlp_attention.py +198 -0
  76. ml_tools/{_core/_models_advanced_base.py → ML_models/_base_save_load.py} +73 -49
  77. ml_tools/ML_models/_dragon_tabular.py +248 -0
  78. ml_tools/ML_models/_imprimir.py +18 -0
  79. ml_tools/ML_models/_mlp_attention.py +134 -0
  80. ml_tools/{_core → ML_models}/_models_advanced_helpers.py +13 -13
  81. ml_tools/ML_models_sequence/__init__.py +10 -0
  82. ml_tools/ML_models_sequence/_imprimir.py +8 -0
  83. ml_tools/{_core/_ML_sequence_models.py → ML_models_sequence/_sequence_models.py} +5 -8
  84. ml_tools/ML_models_vision/__init__.py +29 -0
  85. ml_tools/ML_models_vision/_base_wrapper.py +254 -0
  86. ml_tools/ML_models_vision/_image_classification.py +182 -0
  87. ml_tools/ML_models_vision/_image_segmentation.py +108 -0
  88. ml_tools/ML_models_vision/_imprimir.py +16 -0
  89. ml_tools/ML_models_vision/_object_detection.py +135 -0
  90. ml_tools/ML_optimization/__init__.py +21 -0
  91. ml_tools/ML_optimization/_imprimir.py +13 -0
  92. ml_tools/{_core/_ML_optimization_pareto.py → ML_optimization/_multi_dragon.py} +18 -24
  93. ml_tools/ML_optimization/_single_dragon.py +203 -0
  94. ml_tools/{_core/_ML_optimization.py → ML_optimization/_single_manual.py} +75 -213
  95. ml_tools/{_core → ML_scaler}/_ML_scaler.py +8 -11
  96. ml_tools/ML_scaler/__init__.py +10 -0
  97. ml_tools/ML_scaler/_imprimir.py +8 -0
  98. ml_tools/ML_trainer/__init__.py +20 -0
  99. ml_tools/ML_trainer/_base_trainer.py +297 -0
  100. ml_tools/ML_trainer/_dragon_detection_trainer.py +402 -0
  101. ml_tools/ML_trainer/_dragon_sequence_trainer.py +540 -0
  102. ml_tools/ML_trainer/_dragon_trainer.py +1160 -0
  103. ml_tools/ML_trainer/_imprimir.py +10 -0
  104. ml_tools/{ML_utilities.py → ML_utilities/__init__.py} +14 -6
  105. ml_tools/ML_utilities/_artifact_finder.py +382 -0
  106. ml_tools/ML_utilities/_imprimir.py +16 -0
  107. ml_tools/ML_utilities/_inspection.py +325 -0
  108. ml_tools/ML_utilities/_train_tools.py +205 -0
  109. ml_tools/{ML_vision_transformers.py → ML_vision_transformers/__init__.py} +9 -6
  110. ml_tools/{_core/_ML_vision_transformers.py → ML_vision_transformers/_core_transforms.py} +11 -155
  111. ml_tools/ML_vision_transformers/_imprimir.py +14 -0
  112. ml_tools/ML_vision_transformers/_offline_augmentation.py +159 -0
  113. ml_tools/{_core/_PSO_optimization.py → PSO_optimization/_PSO.py} +58 -15
  114. ml_tools/{PSO_optimization.py → PSO_optimization/__init__.py} +5 -3
  115. ml_tools/PSO_optimization/_imprimir.py +10 -0
  116. ml_tools/SQL/__init__.py +7 -0
  117. ml_tools/{_core/_SQL.py → SQL/_dragon_SQL.py} +7 -11
  118. ml_tools/SQL/_imprimir.py +8 -0
  119. ml_tools/{_core → VIF}/_VIF_factor.py +5 -8
  120. ml_tools/{VIF_factor.py → VIF/__init__.py} +4 -2
  121. ml_tools/VIF/_imprimir.py +10 -0
  122. ml_tools/_core/__init__.py +7 -1
  123. ml_tools/_core/_logger.py +8 -18
  124. ml_tools/_core/_schema_load_ops.py +43 -0
  125. ml_tools/_core/_script_info.py +2 -2
  126. ml_tools/{data_exploration.py → data_exploration/__init__.py} +32 -16
  127. ml_tools/data_exploration/_analysis.py +214 -0
  128. ml_tools/data_exploration/_cleaning.py +566 -0
  129. ml_tools/data_exploration/_features.py +583 -0
  130. ml_tools/data_exploration/_imprimir.py +32 -0
  131. ml_tools/data_exploration/_plotting.py +487 -0
  132. ml_tools/data_exploration/_schema_ops.py +176 -0
  133. ml_tools/{ensemble_evaluation.py → ensemble_evaluation/__init__.py} +6 -4
  134. ml_tools/{_core → ensemble_evaluation}/_ensemble_evaluation.py +3 -7
  135. ml_tools/ensemble_evaluation/_imprimir.py +14 -0
  136. ml_tools/{ensemble_inference.py → ensemble_inference/__init__.py} +5 -3
  137. ml_tools/{_core → ensemble_inference}/_ensemble_inference.py +15 -18
  138. ml_tools/ensemble_inference/_imprimir.py +9 -0
  139. ml_tools/{ensemble_learning.py → ensemble_learning/__init__.py} +4 -6
  140. ml_tools/{_core → ensemble_learning}/_ensemble_learning.py +7 -10
  141. ml_tools/ensemble_learning/_imprimir.py +10 -0
  142. ml_tools/{excel_handler.py → excel_handler/__init__.py} +5 -3
  143. ml_tools/{_core → excel_handler}/_excel_handler.py +6 -10
  144. ml_tools/excel_handler/_imprimir.py +13 -0
  145. ml_tools/{keys.py → keys/__init__.py} +4 -1
  146. ml_tools/keys/_imprimir.py +11 -0
  147. ml_tools/{_core → keys}/_keys.py +2 -0
  148. ml_tools/{math_utilities.py → math_utilities/__init__.py} +5 -2
  149. ml_tools/math_utilities/_imprimir.py +11 -0
  150. ml_tools/{_core → math_utilities}/_math_utilities.py +1 -5
  151. ml_tools/{optimization_tools.py → optimization_tools/__init__.py} +9 -4
  152. ml_tools/optimization_tools/_imprimir.py +13 -0
  153. ml_tools/optimization_tools/_optimization_bounds.py +236 -0
  154. ml_tools/optimization_tools/_optimization_plots.py +218 -0
  155. ml_tools/{path_manager.py → path_manager/__init__.py} +6 -3
  156. ml_tools/{_core/_path_manager.py → path_manager/_dragonmanager.py} +11 -347
  157. ml_tools/path_manager/_imprimir.py +15 -0
  158. ml_tools/path_manager/_path_tools.py +346 -0
  159. ml_tools/plot_fonts/__init__.py +8 -0
  160. ml_tools/plot_fonts/_imprimir.py +8 -0
  161. ml_tools/{_core → plot_fonts}/_plot_fonts.py +2 -5
  162. ml_tools/schema/__init__.py +15 -0
  163. ml_tools/schema/_feature_schema.py +223 -0
  164. ml_tools/schema/_gui_schema.py +191 -0
  165. ml_tools/schema/_imprimir.py +10 -0
  166. ml_tools/{serde.py → serde/__init__.py} +4 -2
  167. ml_tools/serde/_imprimir.py +10 -0
  168. ml_tools/{_core → serde}/_serde.py +3 -8
  169. ml_tools/{utilities.py → utilities/__init__.py} +11 -6
  170. ml_tools/utilities/_imprimir.py +18 -0
  171. ml_tools/{_core/_utilities.py → utilities/_utility_save_load.py} +13 -190
  172. ml_tools/utilities/_utility_tools.py +192 -0
  173. dragon_ml_toolbox-19.13.0.dist-info/RECORD +0 -111
  174. ml_tools/ML_chaining_inference.py +0 -8
  175. ml_tools/ML_configuration.py +0 -86
  176. ml_tools/ML_configuration_pytab.py +0 -14
  177. ml_tools/ML_datasetmaster.py +0 -10
  178. ml_tools/ML_evaluation.py +0 -16
  179. ml_tools/ML_evaluation_multi.py +0 -12
  180. ml_tools/ML_finalize_handler.py +0 -8
  181. ml_tools/ML_inference.py +0 -12
  182. ml_tools/ML_models.py +0 -14
  183. ml_tools/ML_models_advanced.py +0 -14
  184. ml_tools/ML_models_pytab.py +0 -14
  185. ml_tools/ML_optimization.py +0 -14
  186. ml_tools/ML_optimization_pareto.py +0 -8
  187. ml_tools/ML_scaler.py +0 -8
  188. ml_tools/ML_sequence_datasetmaster.py +0 -8
  189. ml_tools/ML_sequence_evaluation.py +0 -10
  190. ml_tools/ML_sequence_inference.py +0 -8
  191. ml_tools/ML_sequence_models.py +0 -8
  192. ml_tools/ML_trainer.py +0 -12
  193. ml_tools/ML_vision_datasetmaster.py +0 -12
  194. ml_tools/ML_vision_evaluation.py +0 -10
  195. ml_tools/ML_vision_inference.py +0 -8
  196. ml_tools/ML_vision_models.py +0 -18
  197. ml_tools/SQL.py +0 -8
  198. ml_tools/_core/_ETL_cleaning.py +0 -694
  199. ml_tools/_core/_IO_tools.py +0 -498
  200. ml_tools/_core/_ML_callbacks.py +0 -702
  201. ml_tools/_core/_ML_configuration.py +0 -1332
  202. ml_tools/_core/_ML_configuration_pytab.py +0 -102
  203. ml_tools/_core/_ML_evaluation.py +0 -867
  204. ml_tools/_core/_ML_evaluation_multi.py +0 -544
  205. ml_tools/_core/_ML_inference.py +0 -646
  206. ml_tools/_core/_ML_models.py +0 -668
  207. ml_tools/_core/_ML_models_pytab.py +0 -693
  208. ml_tools/_core/_ML_trainer.py +0 -2323
  209. ml_tools/_core/_ML_utilities.py +0 -886
  210. ml_tools/_core/_ML_vision_models.py +0 -644
  211. ml_tools/_core/_data_exploration.py +0 -1901
  212. ml_tools/_core/_optimization_tools.py +0 -493
  213. ml_tools/_core/_schema.py +0 -359
  214. ml_tools/plot_fonts.py +0 -8
  215. ml_tools/schema.py +0 -12
  216. {dragon_ml_toolbox-19.13.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/WHEEL +0 -0
  217. {dragon_ml_toolbox-19.13.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE +0 -0
  218. {dragon_ml_toolbox-19.13.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE-THIRD-PARTY.md +0 -0
  219. {dragon_ml_toolbox-19.13.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,10 @@
1
+ from .._core import _imprimir_disponibles
2
+
3
+ _GRUPOS = [
4
+ "DragonTrainer",
5
+ "DragonSequenceTrainer",
6
+ "DragonDetectionTrainer",
7
+ ]
8
+
9
+ def info():
10
+ _imprimir_disponibles(_GRUPOS)
@@ -1,18 +1,26 @@
1
- from ._core._ML_utilities import (
2
- ArtifactFinder,
1
+ from ._artifact_finder import (
2
+ DragonArtifactFinder,
3
3
  find_model_artifacts_multi,
4
- build_optimizer_params,
4
+ )
5
+
6
+ from ._inspection import (
5
7
  get_model_parameters,
6
8
  inspect_model_architecture,
7
9
  inspect_pth_file,
10
+ select_features_by_shap
11
+ )
12
+
13
+ from ._train_tools import (
14
+ build_optimizer_params,
8
15
  set_parameter_requires_grad,
9
16
  save_pretrained_transforms,
10
- select_features_by_shap,
11
- info
12
17
  )
13
18
 
19
+ from ._imprimir import info
20
+
21
+
14
22
  __all__ = [
15
- "ArtifactFinder",
23
+ "DragonArtifactFinder",
16
24
  "find_model_artifacts_multi",
17
25
  "build_optimizer_params",
18
26
  "get_model_parameters",
@@ -0,0 +1,382 @@
1
+ from pathlib import Path
2
+ from typing import Union
3
+
4
+ from ..IO_tools import load_list_strings
5
+ from ..schema import FeatureSchema
6
+
7
+ from ..path_manager import make_fullpath, list_subdirectories, list_files_by_extension
8
+ from .._core import get_logger
9
+ from ..keys._keys import DatasetKeys, PytorchModelArchitectureKeys, PytorchArtifactPathKeys
10
+
11
+
12
+ _LOGGER = get_logger("ArtifactFinder")
13
+
14
+
15
+ __all__ = [
16
+ "DragonArtifactFinder",
17
+ "find_model_artifacts_multi",
18
+ ]
19
+
20
+
21
+ class DragonArtifactFinder:
22
+ """
23
+ Finds, processes, and returns model training artifacts from a target directory.
24
+
25
+ The expected directory structure is:
26
+
27
+ ```
28
+ directory
29
+ ├── *.pth
30
+ ├── scaler_*.pth (Required if `load_scaler` is True)
31
+ ├── feature_names.txt
32
+ ├── target_names.txt
33
+ ├── architecture.json
34
+ └── FeatureSchema.json (Required if `load_schema` is True)
35
+ ```
36
+ """
37
+ def __init__(self,
38
+ directory: Union[str, Path],
39
+ load_scaler: bool,
40
+ load_schema: bool,
41
+ strict: bool=False,
42
+ verbose: bool=True) -> None:
43
+ """
44
+ Args:
45
+ directory (str | Path): The path to the directory that contains training artifacts.
46
+ load_scaler (bool): If True, requires and searches for a scaler file `scaler_*.pth`.
47
+ load_schema (bool): If True, requires and searches for a FeatureSchema file `FeatureSchema.json`.
48
+ strict (bool): If True, raises an error if any artifact is missing. If False, returns None for missing artifacts silently.
49
+ verbose (bool): Displays the missing artifacts in the directory or a success message.
50
+ """
51
+ # validate directory
52
+ dir_path = make_fullpath(directory, enforce="directory")
53
+
54
+ parsing_dict = _find_model_artifacts(target_directory=dir_path, load_scaler=load_scaler, verbose=False, strict=strict)
55
+
56
+ self._weights_path = parsing_dict[PytorchArtifactPathKeys.WEIGHTS_PATH]
57
+ self._feature_names_path = parsing_dict[PytorchArtifactPathKeys.FEATURES_PATH]
58
+ self._target_names_path = parsing_dict[PytorchArtifactPathKeys.TARGETS_PATH]
59
+ self._model_architecture_path = parsing_dict[PytorchArtifactPathKeys.ARCHITECTURE_PATH]
60
+ self._scaler_path = None
61
+ self._schema = None
62
+ self._strict = strict
63
+
64
+ if load_scaler:
65
+ self._scaler_path = parsing_dict[PytorchArtifactPathKeys.SCALER_PATH]
66
+
67
+ if load_schema:
68
+ try:
69
+ self._schema = FeatureSchema.from_json(directory=dir_path)
70
+ except Exception:
71
+ if strict:
72
+ # FeatureSchema logs its own error details
73
+ # _LOGGER.error(f"Failed to load FeatureSchema from '{dir_path.name}': {e}")
74
+ raise FileNotFoundError()
75
+ else:
76
+ # _LOGGER.warning(f"Could not load FeatureSchema from '{dir_path.name}': {e}")
77
+ self._schema = None
78
+
79
+ # Process feature names
80
+ if self._feature_names_path is not None:
81
+ self._feature_names = self._process_text(self._feature_names_path)
82
+ else:
83
+ self._feature_names = None
84
+ # Process target names
85
+ if self._target_names_path is not None:
86
+ self._target_names = self._process_text(self._target_names_path)
87
+ else:
88
+ self._target_names = None
89
+
90
+ if verbose:
91
+ # log missing artifacts
92
+ missing_artifacts = []
93
+ if self._feature_names is None:
94
+ missing_artifacts.append("Feature Names")
95
+ if self._target_names is None:
96
+ missing_artifacts.append("Target Names")
97
+ if self._weights_path is None:
98
+ missing_artifacts.append("Weights File")
99
+ if self._model_architecture_path is None:
100
+ missing_artifacts.append("Model Architecture File")
101
+ if load_scaler and self._scaler_path is None:
102
+ missing_artifacts.append("Scaler File")
103
+ if load_schema and self._schema is None:
104
+ missing_artifacts.append("FeatureSchema File")
105
+
106
+ if missing_artifacts:
107
+ _LOGGER.warning(f"Missing artifacts in '{dir_path.name}': {', '.join(missing_artifacts)}.")
108
+ else:
109
+ _LOGGER.info(f"All artifacts successfully loaded from '{dir_path.name}'.")
110
+
111
+ def _process_text(self, text_file_path: Path):
112
+ list_strings = load_list_strings(text_file=text_file_path, verbose=False)
113
+ return list_strings
114
+
115
+ @property
116
+ def feature_names(self) -> Union[list[str], None]:
117
+ """Returns the feature names as a list of strings."""
118
+ if self._strict and not self._feature_names:
119
+ _LOGGER.error("No feature names loaded for Strict mode.")
120
+ raise ValueError()
121
+ return self._feature_names
122
+
123
+ @property
124
+ def target_names(self) -> Union[list[str], None]:
125
+ """Returns the target names as a list of strings."""
126
+ if self._strict and not self._target_names:
127
+ _LOGGER.error("No target names loaded for Strict mode.")
128
+ raise ValueError()
129
+ return self._target_names
130
+
131
+ @property
132
+ def weights_path(self) -> Union[Path, None]:
133
+ """Returns the path to the state dictionary pth file."""
134
+ if self._strict and self._weights_path is None:
135
+ _LOGGER.error("No weights file loaded for Strict mode.")
136
+ raise ValueError()
137
+ return self._weights_path
138
+
139
+ @property
140
+ def model_architecture_path(self) -> Union[Path, None]:
141
+ """Returns the path to the model architecture json file."""
142
+ if self._strict and self._model_architecture_path is None:
143
+ _LOGGER.error("No model architecture file loaded for Strict mode.")
144
+ raise ValueError()
145
+ return self._model_architecture_path
146
+
147
+ @property
148
+ def scaler_path(self) -> Union[Path, None]:
149
+ """Returns the path to the scaler file."""
150
+ if self._strict and self._scaler_path is None:
151
+ _LOGGER.error("No scaler file loaded for Strict mode.")
152
+ raise ValueError()
153
+ else:
154
+ return self._scaler_path
155
+
156
+ @property
157
+ def feature_schema(self) -> Union[FeatureSchema, None]:
158
+ """Returns the FeatureSchema object."""
159
+ if self._strict and self._schema is None:
160
+ _LOGGER.error("No FeatureSchema loaded for Strict mode.")
161
+ raise ValueError()
162
+ else:
163
+ return self._schema
164
+
165
+ def __repr__(self) -> str:
166
+ dir_name = self._weights_path.parent.name if self._weights_path else "Unknown"
167
+ n_features = len(self._feature_names) if self._feature_names else "None"
168
+ n_targets = len(self._target_names) if self._target_names else "None"
169
+ scaler_status = self._scaler_path.name if self._scaler_path else "None"
170
+ schema_status = "Loaded" if self._schema else "None"
171
+
172
+ return (
173
+ f"{self.__class__.__name__}\n"
174
+ f" directory='{dir_name}'\n"
175
+ f" weights='{self._weights_path.name if self._weights_path else 'None'}'\n"
176
+ f" architecture='{self._model_architecture_path.name if self._model_architecture_path else 'None'}'\n"
177
+ f" scaler='{scaler_status}'\n"
178
+ f" schema='{schema_status}'\n"
179
+ f" features={n_features}\n"
180
+ f" targets={n_targets}"
181
+ )
182
+
183
+
184
+ def _find_model_artifacts(target_directory: Union[str,Path], load_scaler: bool, verbose: bool=True, strict:bool=True) -> dict[str, Union[Path, None]]:
185
+ """
186
+ Scans a directory to find paths to model weights, target names, feature names, and model architecture. Optionally an scaler path if `load_scaler` is True.
187
+
188
+ The expected directory structure is as follows:
189
+
190
+ ```
191
+ target_directory
192
+ ├── *.pth
193
+ ├── scaler_*.pth (Required if `load_scaler` is True)
194
+ ├── feature_names.txt
195
+ ├── target_names.txt
196
+ └── architecture.json
197
+ ```
198
+
199
+ Args:
200
+ target_directory (str | Path): The path to the directory that contains training artifacts.
201
+ load_scaler (bool): If True, the function requires and searches for a scaler file `scaler_*.pth`.
202
+ verbose (bool): If True, enables detailed logging during the search process.
203
+ strict (bool): If True, raises errors on missing files. If False, returns None for missing files.
204
+ """
205
+ # validate directory
206
+ dir_path = make_fullpath(target_directory, enforce="directory")
207
+ dir_name = dir_path.name
208
+
209
+ # find files
210
+ model_pth_dict = list_files_by_extension(directory=dir_path, extension="pth", verbose=False, raise_on_empty=False)
211
+
212
+ if not model_pth_dict:
213
+ pth_msg=f"No '.pth' files found in directory: {dir_name}."
214
+ if strict:
215
+ _LOGGER.error(pth_msg)
216
+ raise IOError()
217
+ else:
218
+ if verbose:
219
+ _LOGGER.warning(pth_msg)
220
+ model_pth_dict = None
221
+
222
+ # restriction
223
+ if model_pth_dict is not None:
224
+ valid_count = False
225
+ msg = ""
226
+
227
+ if load_scaler:
228
+ if len(model_pth_dict) == 2:
229
+ valid_count = True
230
+ else:
231
+ msg = f"Directory '{dir_name}' should contain exactly 2 '.pth' files: scaler and weights. Found {len(model_pth_dict)}."
232
+ else:
233
+ if len(model_pth_dict) == 1:
234
+ valid_count = True
235
+ else:
236
+ msg = f"Directory '{dir_name}' should contain exactly 1 '.pth' file for weights. Found {len(model_pth_dict)}."
237
+
238
+ # Respect strict mode for count mismatch
239
+ if not valid_count:
240
+ if strict:
241
+ _LOGGER.error(msg)
242
+ raise IOError()
243
+ else:
244
+ if verbose:
245
+ _LOGGER.warning(msg)
246
+ # Invalidate dictionary
247
+ model_pth_dict = None
248
+
249
+ ##### Scaler and Weights #####
250
+ scaler_path = None
251
+ weights_path = None
252
+
253
+ # load weights and scaler if present
254
+ if model_pth_dict is not None:
255
+ for pth_filename, pth_path in model_pth_dict.items():
256
+ if load_scaler and pth_filename.lower().startswith(DatasetKeys.SCALER_PREFIX):
257
+ scaler_path = pth_path
258
+ else:
259
+ weights_path = pth_path
260
+
261
+ # validation
262
+ if not weights_path and strict:
263
+ _LOGGER.error(f"Error parsing the model weights path from '{dir_name}'")
264
+ raise IOError()
265
+
266
+ if strict and load_scaler and not scaler_path:
267
+ _LOGGER.error(f"Error parsing the scaler path from '{dir_name}'")
268
+ raise IOError()
269
+
270
+ ##### Target and Feature names #####
271
+ target_names_path = None
272
+ feature_names_path = None
273
+
274
+ # load feature and target names
275
+ model_txt_dict = list_files_by_extension(directory=dir_path, extension="txt", verbose=False, raise_on_empty=False)
276
+
277
+ # if the directory has no txt files, the loop is skipped
278
+ for txt_filename, txt_path in model_txt_dict.items():
279
+ if txt_filename == DatasetKeys.FEATURE_NAMES:
280
+ feature_names_path = txt_path
281
+ elif txt_filename == DatasetKeys.TARGET_NAMES:
282
+ target_names_path = txt_path
283
+
284
+ # validation per case
285
+ if strict and not target_names_path:
286
+ _LOGGER.error(f"Error parsing the target names path from '{dir_name}'")
287
+ raise IOError()
288
+ elif verbose and not target_names_path:
289
+ _LOGGER.warning(f"Target names file not found in '{dir_name}'.")
290
+
291
+ if strict and not feature_names_path:
292
+ _LOGGER.error(f"Error parsing the feature names path from '{dir_name}'")
293
+ raise IOError()
294
+ elif verbose and not feature_names_path:
295
+ _LOGGER.warning(f"Feature names file not found in '{dir_name}'.")
296
+
297
+ ##### load model architecture path #####
298
+ architecture_path = None
299
+
300
+ model_json_dict = list_files_by_extension(directory=dir_path, extension="json", verbose=False, raise_on_empty=False)
301
+
302
+ # if the directory has no json files, the loop is skipped
303
+ for json_filename, json_path in model_json_dict.items():
304
+ if json_filename == PytorchModelArchitectureKeys.SAVENAME:
305
+ architecture_path = json_path
306
+
307
+ # validation
308
+ if strict and not architecture_path:
309
+ _LOGGER.error(f"Error parsing the model architecture path from '{dir_name}'")
310
+ raise IOError()
311
+ elif verbose and not architecture_path:
312
+ _LOGGER.warning(f"Model architecture file not found in '{dir_name}'.")
313
+
314
+ ##### Paths dictionary #####
315
+ parsing_dict = {
316
+ PytorchArtifactPathKeys.WEIGHTS_PATH: weights_path,
317
+ PytorchArtifactPathKeys.ARCHITECTURE_PATH: architecture_path,
318
+ PytorchArtifactPathKeys.FEATURES_PATH: feature_names_path,
319
+ PytorchArtifactPathKeys.TARGETS_PATH: target_names_path,
320
+ }
321
+
322
+ if load_scaler:
323
+ parsing_dict[PytorchArtifactPathKeys.SCALER_PATH] = scaler_path
324
+
325
+ return parsing_dict
326
+
327
+
328
+ def find_model_artifacts_multi(target_directory: Union[str,Path], load_scaler: bool, verbose: bool=False) -> list[dict[str, Path]]:
329
+ """
330
+ Scans subdirectories to find paths to model weights, target names, feature names, and model architecture. Optionally an scaler path if `load_scaler` is True.
331
+
332
+ This function operates on a specific directory structure. It expects the
333
+ `target_directory` to contain one or more subdirectories, where each
334
+ subdirectory represents a single trained model result.
335
+
336
+ This function works using a strict mode, meaning that it will raise errors if
337
+ any required artifacts are missing in a model's subdirectory.
338
+
339
+ The expected directory structure for each model is as follows:
340
+ ```
341
+ target_directory
342
+ ├── model_1
343
+ │ ├── *.pth
344
+ │ ├── scaler_*.pth (Required if `load_scaler` is True)
345
+ │ ├── feature_names.txt
346
+ │ ├── target_names.txt
347
+ │ └── architecture.json
348
+ └── model_2/
349
+ └── ...
350
+ ```
351
+
352
+ Args:
353
+ target_directory (str | Path): The path to the root directory that contains model subdirectories.
354
+ load_scaler (bool): If True, the function requires and searches for a scaler file (`.pth`) in each model subdirectory.
355
+ verbose (bool): If True, enables detailed logging during the file paths search process.
356
+
357
+ Returns:
358
+ (list[dict[str, Path]]): A list of dictionaries, where each dictionary
359
+ corresponds to a model found in a subdirectory. The dictionary
360
+ maps standardized keys to the absolute paths of the model's
361
+ artifacts (weights, architecture, features, targets, and scaler).
362
+ """
363
+ # validate directory
364
+ root_path = make_fullpath(target_directory, enforce="directory")
365
+
366
+ # store results
367
+ all_artifacts: list[dict[str, Path]] = list()
368
+
369
+ # find model directories
370
+ result_dirs_dict = list_subdirectories(root_dir=root_path, verbose=verbose, raise_on_empty=True)
371
+ for _dir_name, dir_path in result_dirs_dict.items():
372
+
373
+ parsing_dict = _find_model_artifacts(target_directory=dir_path,
374
+ load_scaler=load_scaler,
375
+ verbose=verbose,
376
+ strict=True)
377
+
378
+ # parsing_dict is guaranteed to have all required paths due to strict=True
379
+ all_artifacts.append(parsing_dict) # type: ignore
380
+
381
+ return all_artifacts
382
+
@@ -0,0 +1,16 @@
1
+ from .._core import _imprimir_disponibles
2
+
3
+ _GRUPOS = [
4
+ "DragonArtifactFinder",
5
+ "find_model_artifacts_multi",
6
+ "build_optimizer_params",
7
+ "get_model_parameters",
8
+ "inspect_model_architecture",
9
+ "inspect_pth_file",
10
+ "set_parameter_requires_grad",
11
+ "save_pretrained_transforms",
12
+ "select_features_by_shap"
13
+ ]
14
+
15
+ def info():
16
+ _imprimir_disponibles(_GRUPOS)