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.
Files changed (219) hide show
  1. {dragon_ml_toolbox-19.14.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.14.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 -1909
  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.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/WHEEL +0 -0
  217. {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE +0 -0
  218. {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/licenses/LICENSE-THIRD-PARTY.md +0 -0
  219. {dragon_ml_toolbox-19.14.0.dist-info → dragon_ml_toolbox-20.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,134 @@
1
+ import torch
2
+ from torch import nn
3
+ from typing import Any
4
+
5
+ from ._base_mlp_attention import _BaseMLP, _BaseAttention, _AttentionLayer, _MultiHeadAttentionLayer
6
+
7
+
8
+ __all__ = [
9
+ "DragonMLP",
10
+ "DragonAttentionMLP",
11
+ "DragonMultiHeadAttentionNet",
12
+ ]
13
+
14
+
15
+ class DragonMLP(_BaseMLP):
16
+ """
17
+ Creates a versatile Multilayer Perceptron (MLP) for regression or classification tasks.
18
+ """
19
+ def __init__(self, in_features: int, out_targets: int,
20
+ hidden_layers: list[int] = [256, 128], drop_out: float = 0.2) -> None:
21
+ """
22
+ Args:
23
+ in_features (int): The number of input features (e.g., columns in your data).
24
+ out_targets (int): The number of output targets. For regression, this is
25
+ typically 1. For classification, it's the number of classes.
26
+ hidden_layers (list[int]): A list where each integer represents the
27
+ number of neurons in a hidden layer.
28
+ drop_out (float): The dropout probability for neurons in each hidden
29
+ layer. Must be between 0.0 and 1.0.
30
+
31
+ ### Rules of thumb:
32
+ - Choose a number of hidden neurons between the size of the input layer and the size of the output layer.
33
+ - The number of hidden neurons should be 2/3 the size of the input layer, plus the size of the output layer.
34
+ - The number of hidden neurons should be less than twice the size of the input layer.
35
+ """
36
+ super().__init__(in_features, out_targets, hidden_layers, drop_out)
37
+
38
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
39
+ """Defines the forward pass of the model."""
40
+ x = self.mlp(x)
41
+ logits = self.output_layer(x)
42
+ return logits
43
+
44
+ def __repr__(self) -> str:
45
+ """Returns the developer-friendly string representation of the model."""
46
+ # Extracts the number of neurons from each nn.Linear layer
47
+ layer_sizes = [str(layer.in_features) for layer in self.mlp if isinstance(layer, nn.Linear)]
48
+
49
+ return self._repr_helper(name="DragonMLP", mlp_layers=layer_sizes)
50
+
51
+
52
+ class DragonAttentionMLP(_BaseAttention):
53
+ """
54
+ A Multilayer Perceptron (MLP) that incorporates an Attention layer to dynamically weigh input features.
55
+
56
+ In inference mode use `forward_attention()` to get a tuple with `(output, attention_weights)`
57
+ """
58
+ def __init__(self, in_features: int, out_targets: int,
59
+ hidden_layers: list[int] = [256, 128], drop_out: float = 0.2) -> None:
60
+ """
61
+ Args:
62
+ in_features (int): The number of input features (e.g., columns in your data).
63
+ out_targets (int): The number of output targets. For regression, this is
64
+ typically 1. For classification, it's the number of classes.
65
+ hidden_layers (list[int]): A list where each integer represents the
66
+ number of neurons in a hidden layer.
67
+ drop_out (float): The dropout probability for neurons in each hidden
68
+ layer. Must be between 0.0 and 1.0.
69
+ """
70
+ super().__init__(in_features, out_targets, hidden_layers, drop_out)
71
+ # Attention
72
+ self.attention = _AttentionLayer(in_features)
73
+ self.has_interpretable_attention = True
74
+
75
+ def __repr__(self) -> str:
76
+ """Returns the developer-friendly string representation of the model."""
77
+ # Start with the input features and the attention marker
78
+ arch = [str(self.in_features), "[Attention]"]
79
+
80
+ # Find all other linear layers in the MLP
81
+ for layer in self.mlp[1:]: # type: ignore
82
+ if isinstance(layer, nn.Linear):
83
+ arch.append(str(layer.in_features))
84
+
85
+ return self._repr_helper(name="DragonAttentionMLP", mlp_layers=arch)
86
+
87
+
88
+ class DragonMultiHeadAttentionNet(_BaseAttention):
89
+ """
90
+ An MLP that incorporates a standard `nn.MultiheadAttention` layer to process
91
+ the input features.
92
+
93
+ In inference mode use `forward_attention()` to get a tuple with `(output, attention_weights)`.
94
+ """
95
+ def __init__(self, in_features: int, out_targets: int,
96
+ hidden_layers: list[int] = [256, 128], drop_out: float = 0.2,
97
+ num_heads: int = 4, attention_dropout: float = 0.1) -> None:
98
+ """
99
+ Args:
100
+ in_features (int): The number of input features.
101
+ out_targets (int): The number of output targets.
102
+ hidden_layers (list[int]): A list of neuron counts for each hidden layer.
103
+ drop_out (float): The dropout probability for the MLP layers.
104
+ num_heads (int): The number of attention heads.
105
+ attention_dropout (float): Dropout probability in the attention layer.
106
+ """
107
+ super().__init__(in_features, out_targets, hidden_layers, drop_out)
108
+ self.num_heads = num_heads
109
+ self.attention_dropout = attention_dropout
110
+
111
+ self.attention = _MultiHeadAttentionLayer(
112
+ num_features=in_features,
113
+ num_heads=num_heads,
114
+ dropout=attention_dropout
115
+ )
116
+
117
+ def get_architecture_config(self) -> dict[str, Any]:
118
+ """Returns the full configuration of the model."""
119
+ config = super().get_architecture_config()
120
+ config['num_heads'] = self.num_heads
121
+ config['attention_dropout'] = self.attention_dropout
122
+ return config
123
+
124
+ def __repr__(self) -> str:
125
+ """Returns the developer-friendly string representation of the model."""
126
+ mlp_part = " -> ".join(
127
+ [str(self.in_features)] +
128
+ [str(h) for h in self.hidden_layers] +
129
+ [str(self.out_targets)]
130
+ )
131
+ arch_str = f"{self.in_features} -> [MultiHead(h={self.num_heads})] -> {mlp_part}"
132
+
133
+ return f"DragonMultiHeadAttentionNet(arch: {arch_str})"
134
+
@@ -5,7 +5,7 @@ from torch.autograd import Function
5
5
  import math
6
6
  import random
7
7
  import numpy as np
8
- from typing import Optional, Tuple, List, Callable
8
+ from typing import Optional, Callable
9
9
 
10
10
  # HELPER module for ML_models_advanced
11
11
  # SOURCE CODE: Adapted and modified from:
@@ -183,7 +183,7 @@ def entmoid15(input):
183
183
  def sparsemoid(input):
184
184
  return (0.5 * input + 0.5).clamp_(0, 1)
185
185
 
186
- def t_softmax(input: torch.Tensor, t: torch.Tensor = None, dim: int = -1) -> torch.Tensor:
186
+ def t_softmax(input: torch.Tensor, t: torch.Tensor = None, dim: int = -1) -> torch.Tensor: # type: ignore
187
187
  if t is None:
188
188
  t = torch.tensor(0.5, device=input.device)
189
189
  maxes = torch.max(input, dim=dim, keepdim=True).values
@@ -250,7 +250,7 @@ class Embedding1dLayer(nn.Module):
250
250
  def __init__(
251
251
  self,
252
252
  continuous_dim: int,
253
- categorical_embedding_dims: List[Tuple[int, int]],
253
+ categorical_embedding_dims: list[tuple[int, int]],
254
254
  embedding_dropout: float = 0.0,
255
255
  batch_norm_continuous_input: bool = False,
256
256
  virtual_batch_size: Optional[int] = None,
@@ -297,7 +297,7 @@ class Embedding1dLayer(nn.Module):
297
297
 
298
298
  if self.embd_dropout is not None:
299
299
  embed = self.embd_dropout(embed)
300
- return embed
300
+ return embed # type: ignore
301
301
 
302
302
  class GatedFeatureLearningUnit(nn.Module):
303
303
  def __init__(
@@ -408,14 +408,14 @@ class NeuralDecisionStump(nn.Module):
408
408
  feature_mask = self.feature_mask_function(self.feature_mask)
409
409
 
410
410
  # Repeat W for each batch size using broadcasting
411
- W = torch.ones(x.size(0), 1, 1, device=x.device) * self.W
411
+ W = torch.ones(x.size(0), 1, 1, device=x.device) * self.W # type: ignore
412
412
  # Binning features
413
413
  # x: (B, Features) -> (B, Features, 1) -> bmm -> (B, Features, Cutpoints+1)
414
414
  x_out = torch.bmm(x.unsqueeze(-1), W) - self.cut_points.unsqueeze(0)
415
415
  x_out = self.binning_activation(x_out)
416
416
  x_out = x_out * self.leaf_responses.unsqueeze(0)
417
417
  x_out = (x_out * feature_mask.reshape(1, -1, 1)).sum(dim=1)
418
- return x_out, feature_mask
418
+ return x_out, feature_mask # type: ignore
419
419
 
420
420
  class NeuralDecisionTree(nn.Module):
421
421
  def __init__(
@@ -455,14 +455,14 @@ class NeuralDecisionTree(nn.Module):
455
455
  layer_nodes_list = []
456
456
  layer_feature_masks = []
457
457
  for n in range(max(2 ** (d), 1)):
458
- leaf_nodes, feature_mask = self._modules[f"decision_stump_{d}_{n}"](tree_input)
458
+ leaf_nodes, feature_mask = self._modules[f"decision_stump_{d}_{n}"](tree_input) # type: ignore
459
459
  layer_nodes_list.append(leaf_nodes)
460
460
  layer_feature_masks.append(feature_mask)
461
461
  layer_nodes = torch.cat(layer_nodes_list, dim=1)
462
462
  tree_input = torch.cat([x, layer_nodes], dim=1)
463
463
  feature_masks.append(layer_feature_masks)
464
464
 
465
- return self.dropout(layer_nodes), feature_masks
465
+ return self.dropout(layer_nodes), feature_masks # type: ignore
466
466
 
467
467
  class ODST(nn.Module):
468
468
  def __init__(
@@ -569,7 +569,7 @@ class SimpleLinearHead(nn.Module):
569
569
  super().__init__()
570
570
  layers = [nn.Linear(in_units, output_dim)]
571
571
  if dropout > 0:
572
- layers.append(nn.Dropout(dropout))
572
+ layers.append(nn.Dropout(dropout)) # type: ignore
573
573
  self.main = nn.Sequential(*layers)
574
574
 
575
575
  def forward(self, x):
@@ -649,7 +649,7 @@ class DenseODSTBlock(nn.Sequential):
649
649
 
650
650
  # Initialize the specific ODST layer
651
651
  if hasattr(layer, 'initialize'):
652
- layer.initialize(layer_inp)
652
+ layer.initialize(layer_inp) # type: ignore
653
653
 
654
654
  # Compute output to feed the next layer in the dense block
655
655
  h = layer(layer_inp)
@@ -696,7 +696,7 @@ class Embedding2dLayer(nn.Module):
696
696
  def __init__(
697
697
  self,
698
698
  continuous_dim: int,
699
- categorical_cardinality: List[int],
699
+ categorical_cardinality: list[int],
700
700
  embedding_dim: int,
701
701
  shared_embedding_strategy: Optional[str] = None,
702
702
  frac_shared_embed: float = 0.25,
@@ -813,7 +813,7 @@ class Embedding2dLayer(nn.Module):
813
813
  if self.embd_dropout is not None:
814
814
  embed = self.embd_dropout(embed)
815
815
 
816
- return embed
816
+ return embed # type: ignore
817
817
 
818
818
 
819
819
 
@@ -1007,7 +1007,7 @@ class _GateHead(nn.Module):
1007
1007
  else:
1008
1008
  # Apply separate linear layers
1009
1009
  y_hat = torch.cat(
1010
- [h(backbone_features[:, :, i]).unsqueeze(1) for i, h in enumerate(self.head)],
1010
+ [h(backbone_features[:, :, i]).unsqueeze(1) for i, h in enumerate(self.head)], # type: ignore
1011
1011
  dim=1,
1012
1012
  )
1013
1013
 
@@ -0,0 +1,10 @@
1
+ from ._sequence_models import (
2
+ DragonSequenceLSTM
3
+ )
4
+
5
+ from ._imprimir import info
6
+
7
+
8
+ __all__ = [
9
+ "DragonSequenceLSTM",
10
+ ]
@@ -0,0 +1,8 @@
1
+ from .._core import _imprimir_disponibles
2
+
3
+ _GRUPOS = [
4
+ "DragonSequenceLSTM",
5
+ ]
6
+
7
+ def info():
8
+ _imprimir_disponibles(_GRUPOS)
@@ -2,13 +2,13 @@ import torch
2
2
  from torch import nn
3
3
  from typing import Literal
4
4
 
5
- from ._logger import get_logger
6
- from ._script_info import _script_info
7
- from ._keys import MLTaskKeys
8
- from ._ML_models import _ArchitectureHandlerMixin
5
+ from .._core import get_logger
6
+ from ..keys._keys import MLTaskKeys
9
7
 
8
+ from ..ML_models._base_save_load import _ArchitectureHandlerMixin
10
9
 
11
- _LOGGER = get_logger("DragonModel")
10
+
11
+ _LOGGER = get_logger("DragonSequenceLSTM")
12
12
 
13
13
 
14
14
  __all__ = [
@@ -137,6 +137,3 @@ class DragonSequenceLSTM(nn.Module, _ArchitectureHandlerMixin):
137
137
  f"recurrent_layers={self.lstm.num_layers}), "
138
138
  f"mode='{self.prediction_mode}')")
139
139
 
140
-
141
- def info():
142
- _script_info(__all__)
@@ -0,0 +1,29 @@
1
+ from ._image_classification import (
2
+ DragonResNet,
3
+ DragonEfficientNet,
4
+ DragonVGG,
5
+ )
6
+
7
+ from ._image_segmentation import (
8
+ DragonFCN,
9
+ DragonDeepLabv3
10
+ )
11
+
12
+ from ._object_detection import (
13
+ DragonFastRCNN,
14
+ )
15
+
16
+ from ._imprimir import info
17
+
18
+
19
+ __all__ = [
20
+ # Image Classification
21
+ "DragonResNet",
22
+ "DragonEfficientNet",
23
+ "DragonVGG",
24
+ # Image Segmentation
25
+ "DragonFCN",
26
+ "DragonDeepLabv3",
27
+ # Object Detection
28
+ "DragonFastRCNN",
29
+ ]
@@ -0,0 +1,254 @@
1
+ import torch
2
+ from torch import nn
3
+ import torchvision.models as vision_models
4
+ from typing import Any, Optional
5
+ from abc import ABC, abstractmethod
6
+
7
+ from ..ML_models._base_save_load import _ArchitectureHandlerMixin
8
+
9
+ from .._core import get_logger
10
+
11
+
12
+ _LOGGER = get_logger("DragonVisionModel")
13
+
14
+
15
+ __all__ = [
16
+ "_BaseVisionWrapper",
17
+ "_BaseSegmentationWrapper",
18
+ ]
19
+
20
+
21
+ class _BaseVisionWrapper(nn.Module, _ArchitectureHandlerMixin, ABC):
22
+ """
23
+ Abstract base class for torchvision model wrappers.
24
+
25
+ Handles common logic for:
26
+ - Model instantiation (with/without pretrained weights)
27
+ - Input layer modification (for custom in_channels)
28
+ - Output layer modification (for custom num_classes)
29
+ - Architecture saving/loading and representation
30
+ """
31
+ def __init__(self,
32
+ num_classes: int,
33
+ in_channels: int,
34
+ model_name: str,
35
+ init_with_pretrained: bool,
36
+ weights_enum_name: Optional[str] = None):
37
+ super().__init__()
38
+
39
+ # --- 1. Validation and Configuration ---
40
+ if not hasattr(vision_models, model_name):
41
+ _LOGGER.error(f"'{model_name}' is not a valid model name in torchvision.models.")
42
+ raise ValueError()
43
+
44
+ self.num_classes = num_classes
45
+ self.in_channels = in_channels
46
+ self.model_name = model_name
47
+ self._pretrained_default_transforms = None
48
+
49
+ # --- 2. Instantiate the base model ---
50
+ if init_with_pretrained:
51
+ weights_enum = getattr(vision_models, weights_enum_name, None) if weights_enum_name else None
52
+ weights = weights_enum.IMAGENET1K_V1 if weights_enum else None
53
+
54
+ # Save transformations for pretrained models
55
+ if weights:
56
+ self._pretrained_default_transforms = weights.transforms()
57
+
58
+ if weights is None and init_with_pretrained:
59
+ _LOGGER.warning(f"Could not find modern weights for {model_name}. Using 'pretrained=True' legacy fallback.")
60
+ self.model = getattr(vision_models, model_name)(pretrained=True)
61
+ else:
62
+ self.model = getattr(vision_models, model_name)(weights=weights)
63
+ else:
64
+ self.model = getattr(vision_models, model_name)(weights=None)
65
+
66
+ # --- 3. Modify the input layer (using abstract method) ---
67
+ if in_channels != 3:
68
+ original_conv1 = self._get_input_layer()
69
+
70
+ new_conv1 = nn.Conv2d(
71
+ in_channels,
72
+ original_conv1.out_channels,
73
+ kernel_size=original_conv1.kernel_size, # type: ignore
74
+ stride=original_conv1.stride, # type: ignore
75
+ padding=original_conv1.padding, # type: ignore
76
+ bias=(original_conv1.bias is not None)
77
+ )
78
+
79
+ # (Optional) Average original weights if starting from pretrained
80
+ if init_with_pretrained and original_conv1.in_channels == 3:
81
+ with torch.no_grad():
82
+ avg_weights = torch.mean(original_conv1.weight, dim=1, keepdim=True)
83
+ new_conv1.weight[:] = avg_weights.repeat(1, in_channels, 1, 1)
84
+
85
+ self._set_input_layer(new_conv1)
86
+
87
+ # --- 4. Modify the output layer (using abstract method) ---
88
+ original_fc = self._get_output_layer()
89
+ if original_fc is None: # Handle case where layer isn't found
90
+ _LOGGER.error(f"Model '{model_name}' has an unexpected classifier structure. Cannot replace final layer.")
91
+ raise AttributeError("Could not find final classifier layer.")
92
+
93
+ num_filters = original_fc.in_features
94
+ self._set_output_layer(nn.Linear(num_filters, num_classes))
95
+
96
+ @abstractmethod
97
+ def _get_input_layer(self) -> nn.Conv2d:
98
+ """Returns the first convolutional layer of the model."""
99
+ raise NotImplementedError
100
+
101
+ @abstractmethod
102
+ def _set_input_layer(self, layer: nn.Conv2d):
103
+ """Sets the first convolutional layer of the model."""
104
+ raise NotImplementedError
105
+
106
+ @abstractmethod
107
+ def _get_output_layer(self) -> Optional[nn.Linear]:
108
+ """Returns the final fully-connected layer of the model."""
109
+ raise NotImplementedError
110
+
111
+ @abstractmethod
112
+ def _set_output_layer(self, layer: nn.Linear):
113
+ """Sets the final fully-connected layer of the model."""
114
+ raise NotImplementedError
115
+
116
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
117
+ """Defines the forward pass of the model."""
118
+ return self.model(x)
119
+
120
+ def get_architecture_config(self) -> dict[str, Any]:
121
+ """
122
+ Returns the structural configuration of the model.
123
+ The 'init_with_pretrained' flag is intentionally omitted,
124
+ as .load() should restore the architecture, not the weights.
125
+ """
126
+ return {
127
+ 'num_classes': self.num_classes,
128
+ 'in_channels': self.in_channels,
129
+ 'model_name': self.model_name
130
+ }
131
+
132
+ def __repr__(self) -> str:
133
+ """Returns the developer-friendly string representation of the model."""
134
+ return (
135
+ f"{self.__class__.__name__}(model='{self.model_name}', "
136
+ f"in_channels={self.in_channels}, "
137
+ f"num_classes={self.num_classes})"
138
+ )
139
+
140
+
141
+ # Image segmentation
142
+ class _BaseSegmentationWrapper(nn.Module, _ArchitectureHandlerMixin, ABC):
143
+ """
144
+ Abstract base class for torchvision segmentation model wrappers.
145
+
146
+ Handles common logic for:
147
+ - Model instantiation (with/without pretrained weights and custom num_classes)
148
+ - Input layer modification (for custom in_channels)
149
+ - Forward pass dictionary unpacking (returns 'out' tensor)
150
+ - Architecture saving/loading and representation
151
+ """
152
+ def __init__(self,
153
+ num_classes: int,
154
+ in_channels: int,
155
+ model_name: str,
156
+ init_with_pretrained: bool,
157
+ weights_enum_name: Optional[str] = None):
158
+ super().__init__()
159
+
160
+ # --- 1. Validation and Configuration ---
161
+ if not hasattr(vision_models.segmentation, model_name):
162
+ _LOGGER.error(f"'{model_name}' is not a valid model name in torchvision.models.segmentation.")
163
+ raise ValueError()
164
+
165
+ self.num_classes = num_classes
166
+ self.in_channels = in_channels
167
+ self.model_name = model_name
168
+ self._pretrained_default_transforms = None
169
+
170
+ # --- 2. Instantiate the base model ---
171
+ model_kwargs = {
172
+ 'num_classes': num_classes,
173
+ 'weights': None
174
+ }
175
+ model_constructor = getattr(vision_models.segmentation, model_name)
176
+
177
+ if init_with_pretrained:
178
+ weights_enum = getattr(vision_models.segmentation, weights_enum_name, None) if weights_enum_name else None
179
+ weights = weights_enum.DEFAULT if weights_enum else None
180
+
181
+ # save pretrained model transformations
182
+ if weights:
183
+ self._pretrained_default_transforms = weights.transforms()
184
+
185
+ if weights is None:
186
+ _LOGGER.warning(f"Could not find modern weights for {model_name}. Using 'pretrained=True' legacy fallback.")
187
+ # Legacy models used 'pretrained=True' and num_classes was separate
188
+ self.model = model_constructor(pretrained=True, **model_kwargs)
189
+ else:
190
+ # Modern way: weights object implies pretraining
191
+ model_kwargs['weights'] = weights
192
+ self.model = model_constructor(**model_kwargs)
193
+ else:
194
+ self.model = model_constructor(**model_kwargs)
195
+
196
+ # --- 3. Modify the input layer (using abstract method) ---
197
+ if in_channels != 3:
198
+ original_conv1 = self._get_input_layer()
199
+
200
+ new_conv1 = nn.Conv2d(
201
+ in_channels,
202
+ original_conv1.out_channels,
203
+ kernel_size=original_conv1.kernel_size, # type: ignore
204
+ stride=original_conv1.stride, # type: ignore
205
+ padding=original_conv1.padding, # type: ignore
206
+ bias=(original_conv1.bias is not None)
207
+ )
208
+
209
+ # (Optional) Average original weights if starting from pretrained
210
+ if init_with_pretrained and original_conv1.in_channels == 3:
211
+ with torch.no_grad():
212
+ avg_weights = torch.mean(original_conv1.weight, dim=1, keepdim=True)
213
+ new_conv1.weight[:] = avg_weights.repeat(1, in_channels, 1, 1)
214
+
215
+ self._set_input_layer(new_conv1)
216
+
217
+ @abstractmethod
218
+ def _get_input_layer(self) -> nn.Conv2d:
219
+ """Returns the first convolutional layer of the model (in the backbone)."""
220
+ raise NotImplementedError
221
+
222
+ @abstractmethod
223
+ def _set_input_layer(self, layer: nn.Conv2d):
224
+ """Sets the first convolutional layer of the model (in the backbone)."""
225
+ raise NotImplementedError
226
+
227
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
228
+ """
229
+ Defines the forward pass.
230
+ Returns the 'out' tensor from the segmentation model's output dict.
231
+ """
232
+ output_dict = self.model(x)
233
+ return output_dict['out'] # Key for standard torchvision seg models
234
+
235
+ def get_architecture_config(self) -> dict[str, Any]:
236
+ """
237
+ Returns the structural configuration of the model.
238
+ The 'init_with_pretrained' flag is intentionally omitted,
239
+ as .load() should restore the architecture, not the weights.
240
+ """
241
+ return {
242
+ 'num_classes': self.num_classes,
243
+ 'in_channels': self.in_channels,
244
+ 'model_name': self.model_name
245
+ }
246
+
247
+ def __repr__(self) -> str:
248
+ """Returns the developer-friendly string representation of the model."""
249
+ return (
250
+ f"{self.__class__.__name__}(model='{self.model_name}', "
251
+ f"in_channels={self.in_channels}, "
252
+ f"num_classes={self.num_classes})"
253
+ )
254
+