likelihood 1.3.0__tar.gz → 1.3.1__tar.gz

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 (25) hide show
  1. {likelihood-1.3.0 → likelihood-1.3.1}/PKG-INFO +9 -7
  2. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/deep/autoencoders.py +197 -21
  3. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/tools/tools.py +4 -2
  4. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood.egg-info/PKG-INFO +9 -7
  5. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood.egg-info/requires.txt +8 -6
  6. {likelihood-1.3.0 → likelihood-1.3.1}/LICENSE +0 -0
  7. {likelihood-1.3.0 → likelihood-1.3.1}/README.md +0 -0
  8. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/__init__.py +0 -0
  9. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/graph/__init__.py +0 -0
  10. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/graph/graph.py +0 -0
  11. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/graph/nn.py +0 -0
  12. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/main.py +0 -0
  13. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/__init__.py +0 -0
  14. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/deep/__init__.py +0 -0
  15. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/hmm.py +0 -0
  16. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/regression.py +0 -0
  17. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/simulation.py +0 -0
  18. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/models/utils.py +0 -0
  19. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/tools/__init__.py +0 -0
  20. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood/tools/numeric_tools.py +0 -0
  21. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood.egg-info/SOURCES.txt +0 -0
  22. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood.egg-info/dependency_links.txt +0 -0
  23. {likelihood-1.3.0 → likelihood-1.3.1}/likelihood.egg-info/top_level.txt +0 -0
  24. {likelihood-1.3.0 → likelihood-1.3.1}/setup.cfg +0 -0
  25. {likelihood-1.3.0 → likelihood-1.3.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: likelihood
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: A package that performs the maximum likelihood algorithm.
5
5
  Home-page: https://github.com/jzsmoreno/likelihood/
6
6
  Author: J. A. Moreno-Guerra
@@ -14,14 +14,16 @@ Requires-Python: >=3.10
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: black[jupyter]>=24.3.0
17
- Requires-Dist: mypy-extensions==1.0.0
18
- Requires-Dist: types-openpyxl==3.1.0.15
19
- Requires-Dist: pydocstyle==6.3.0
20
- Requires-Dist: flake8==6.0.0
21
- Requires-Dist: isort==5.12.0
22
- Requires-Dist: mypy==1.4.1
17
+ Requires-Dist: mypy-extensions>=1.0.0
18
+ Requires-Dist: types-openpyxl>=3.1.0.15
19
+ Requires-Dist: pydocstyle>=6.3.0
20
+ Requires-Dist: flake8>=6.0.0
21
+ Requires-Dist: isort>=5.12.0
22
+ Requires-Dist: mypy>=1.4.1
23
23
  Requires-Dist: numpy<2.0.0
24
+ Requires-Dist: pydot==2.0.0
24
25
  Requires-Dist: matplotlib
26
+ Requires-Dist: graphviz
25
27
  Requires-Dist: pyyaml
26
28
  Requires-Dist: pandas
27
29
  Requires-Dist: corner
@@ -19,8 +19,10 @@ from functools import wraps
19
19
 
20
20
  import keras_tuner
21
21
  import tensorflow as tf
22
+ from keras.src.engine.input_layer import InputLayer
22
23
  from pandas.core.frame import DataFrame
23
24
  from sklearn.manifold import TSNE
25
+ from tensorflow.keras.regularizers import l2
24
26
 
25
27
  from likelihood.tools import OneHotEncoder
26
28
 
@@ -81,6 +83,8 @@ class AutoClassifier(tf.keras.Model):
81
83
  The number of hidden layers in the classifier. Default is 1.
82
84
  dropout : `float`
83
85
  The dropout rate to use in the classifier. Default is None.
86
+ l2_reg : `float`
87
+ The L2 regularization parameter. Default is 0.0.
84
88
  """
85
89
  super(AutoClassifier, self).__init__()
86
90
  self.input_shape_parm = input_shape_parm
@@ -94,32 +98,68 @@ class AutoClassifier(tf.keras.Model):
94
98
  self.classifier_activation = kwargs.get("classifier_activation", "softmax")
95
99
  self.num_layers = kwargs.get("num_layers", 1)
96
100
  self.dropout = kwargs.get("dropout", None)
101
+ self.l2_reg = kwargs.get("l2_reg", 0.0)
97
102
 
98
103
  def build(self, input_shape):
99
- self.encoder = tf.keras.Sequential(
100
- [
101
- tf.keras.layers.Dense(units=self.units, activation=self.activation),
102
- tf.keras.layers.Dense(units=int(self.units / 2), activation=self.activation),
103
- ]
104
+ # Encoder with L2 regularization
105
+ self.encoder = (
106
+ tf.keras.Sequential(
107
+ [
108
+ tf.keras.layers.Dense(
109
+ units=self.units,
110
+ activation=self.activation,
111
+ kernel_regularizer=l2(self.l2_reg),
112
+ ),
113
+ tf.keras.layers.Dense(
114
+ units=int(self.units / 2),
115
+ activation=self.activation,
116
+ kernel_regularizer=l2(self.l2_reg),
117
+ ),
118
+ ]
119
+ )
120
+ if not self.encoder
121
+ else self.encoder
104
122
  )
105
123
 
106
- self.decoder = tf.keras.Sequential(
107
- [
108
- tf.keras.layers.Dense(units=self.units, activation=self.activation),
109
- tf.keras.layers.Dense(units=self.input_shape_parm, activation=self.activation),
110
- ]
124
+ # Decoder with L2 regularization
125
+ self.decoder = (
126
+ tf.keras.Sequential(
127
+ [
128
+ tf.keras.layers.Dense(
129
+ units=self.units,
130
+ activation=self.activation,
131
+ kernel_regularizer=l2(self.l2_reg),
132
+ ),
133
+ tf.keras.layers.Dense(
134
+ units=self.input_shape_parm,
135
+ activation=self.activation,
136
+ kernel_regularizer=l2(self.l2_reg),
137
+ ),
138
+ ]
139
+ )
140
+ if not self.decoder
141
+ else self.decoder
111
142
  )
112
143
 
144
+ # Classifier with L2 regularization
113
145
  self.classifier = tf.keras.Sequential()
114
146
  if self.num_layers > 1:
115
147
  for _ in range(self.num_layers - 1):
116
148
  self.classifier.add(
117
- tf.keras.layers.Dense(units=self.units, activation=self.activation)
149
+ tf.keras.layers.Dense(
150
+ units=self.units,
151
+ activation=self.activation,
152
+ kernel_regularizer=l2(self.l2_reg),
153
+ )
118
154
  )
119
155
  if self.dropout:
120
156
  self.classifier.add(tf.keras.layers.Dropout(self.dropout))
121
157
  self.classifier.add(
122
- tf.keras.layers.Dense(units=self.num_classes, activation=self.classifier_activation)
158
+ tf.keras.layers.Dense(
159
+ units=self.num_classes,
160
+ activation=self.classifier_activation,
161
+ kernel_regularizer=l2(self.l2_reg),
162
+ )
123
163
  )
124
164
 
125
165
  def call(self, x):
@@ -129,6 +169,84 @@ class AutoClassifier(tf.keras.Model):
129
169
  classification = self.classifier(combined)
130
170
  return classification
131
171
 
172
+ def freeze_encoder_decoder(self):
173
+ """
174
+ Freezes the encoder and decoder layers to prevent them from being updated during training.
175
+ """
176
+ for layer in self.encoder.layers:
177
+ layer.trainable = False
178
+ for layer in self.decoder.layers:
179
+ layer.trainable = False
180
+
181
+ def unfreeze_encoder_decoder(self):
182
+ """
183
+ Unfreezes the encoder and decoder layers allowing them to be updated during training.
184
+ """
185
+ for layer in self.encoder.layers:
186
+ layer.trainable = True
187
+ for layer in self.decoder.layers:
188
+ layer.trainable = True
189
+
190
+ def set_encoder_decoder(self, source_model):
191
+ """
192
+ Sets the encoder and decoder layers from another AutoClassifier instance,
193
+ ensuring compatibility in dimensions.
194
+
195
+ Parameters:
196
+ -----------
197
+ source_model : AutoClassifier
198
+ The source model to copy the encoder and decoder layers from.
199
+
200
+ Raises:
201
+ -------
202
+ ValueError
203
+ If the input shape or units of the source model do not match.
204
+ """
205
+ if not isinstance(source_model, AutoClassifier):
206
+ raise ValueError("Source model must be an instance of AutoClassifier.")
207
+
208
+ # Check compatibility in input shape and units
209
+ if self.input_shape_parm != source_model.input_shape_parm:
210
+ raise ValueError(
211
+ f"Incompatible input shape. Expected {self.input_shape_parm}, got {source_model.input_shape_parm}."
212
+ )
213
+ if self.units != source_model.units:
214
+ raise ValueError(
215
+ f"Incompatible number of units. Expected {self.units}, got {source_model.units}."
216
+ )
217
+ self.encoder, self.decoder = tf.keras.Sequential(), tf.keras.Sequential()
218
+ # Copy the encoder layers
219
+ for i, layer in enumerate(source_model.encoder.layers):
220
+ if isinstance(layer, tf.keras.layers.Dense): # Make sure it's a Dense layer
221
+ dummy_input = tf.convert_to_tensor(tf.random.normal([1, layer.input_shape[1]]))
222
+ dense_layer = tf.keras.layers.Dense(
223
+ units=layer.units,
224
+ activation=self.activation,
225
+ kernel_regularizer=l2(self.l2_reg),
226
+ )
227
+ dense_layer.build(dummy_input.shape)
228
+ self.encoder.add(dense_layer)
229
+ # Set the weights correctly
230
+ self.encoder.layers[i].set_weights(layer.get_weights())
231
+ elif not isinstance(layer, InputLayer):
232
+ raise ValueError(f"Layer type {type(layer)} not supported for copying.")
233
+
234
+ # Copy the decoder layers
235
+ for i, layer in enumerate(source_model.decoder.layers):
236
+ if isinstance(layer, tf.keras.layers.Dense): # Ensure it's a Dense layer
237
+ dummy_input = tf.convert_to_tensor(tf.random.normal([1, layer.input_shape[1]]))
238
+ dense_layer = tf.keras.layers.Dense(
239
+ units=layer.units,
240
+ activation=self.activation,
241
+ kernel_regularizer=l2(self.l2_reg),
242
+ )
243
+ dense_layer.build(dummy_input.shape)
244
+ self.decoder.add(dense_layer)
245
+ # Set the weights correctly
246
+ self.decoder.layers[i].set_weights(layer.get_weights())
247
+ elif not isinstance(layer, InputLayer):
248
+ raise ValueError(f"Layer type {type(layer)} not supported for copying.")
249
+
132
250
  def get_config(self):
133
251
  config = {
134
252
  "input_shape_parm": self.input_shape_parm,
@@ -138,6 +256,7 @@ class AutoClassifier(tf.keras.Model):
138
256
  "classifier_activation": self.classifier_activation,
139
257
  "num_layers": self.num_layers,
140
258
  "dropout": self.dropout,
259
+ "l2_reg": self.l2_reg,
141
260
  }
142
261
  base_config = super(AutoClassifier, self).get_config()
143
262
  return dict(list(base_config.items()) + list(config.items()))
@@ -152,6 +271,7 @@ class AutoClassifier(tf.keras.Model):
152
271
  classifier_activation=config["classifier_activation"],
153
272
  num_layers=config["num_layers"],
154
273
  dropout=config["dropout"],
274
+ l2_reg=config["l2_reg"],
155
275
  )
156
276
 
157
277
 
@@ -189,6 +309,7 @@ def call_existing_code(
189
309
  The AutoClassifier instance.
190
310
  """
191
311
  dropout = kwargs.get("dropout", None)
312
+ l2_reg = kwargs.get("l2_reg", 0.0)
192
313
  model = AutoClassifier(
193
314
  input_shape_parm=input_shape_parm,
194
315
  num_classes=num_classes,
@@ -196,6 +317,7 @@ def call_existing_code(
196
317
  activation=activation,
197
318
  num_layers=num_layers,
198
319
  dropout=dropout,
320
+ l2_reg=l2_reg,
199
321
  )
200
322
  model.compile(
201
323
  optimizer=optimizer,
@@ -242,32 +364,65 @@ def build_model(
242
364
  step=2,
243
365
  )
244
366
  if "units" not in hyperparameters_keys
245
- else hyperparameters["units"]
367
+ else (
368
+ hp.Choice("units", hyperparameters["units"])
369
+ if isinstance(hyperparameters["units"], list)
370
+ else hyperparameters["units"]
371
+ )
246
372
  )
247
373
  activation = (
248
374
  hp.Choice("activation", ["sigmoid", "relu", "tanh", "selu", "softplus", "softsign"])
249
375
  if "activation" not in hyperparameters_keys
250
- else hyperparameters["activation"]
376
+ else (
377
+ hp.Choice("activation", hyperparameters["activation"])
378
+ if isinstance(hyperparameters["activation"], list)
379
+ else hyperparameters["activation"]
380
+ )
251
381
  )
252
382
  optimizer = (
253
383
  hp.Choice("optimizer", ["sgd", "adam", "adadelta", "rmsprop", "adamax", "adagrad"])
254
384
  if "optimizer" not in hyperparameters_keys
255
- else hyperparameters["optimizer"]
385
+ else (
386
+ hp.Choice("optimizer", hyperparameters["optimizer"])
387
+ if isinstance(hyperparameters["optimizer"], list)
388
+ else hyperparameters["optimizer"]
389
+ )
256
390
  )
257
391
  threshold = (
258
392
  hp.Float("threshold", min_value=0.1, max_value=0.9, sampling="log")
259
393
  if "threshold" not in hyperparameters_keys
260
- else hyperparameters["threshold"]
394
+ else (
395
+ hp.Choice("threshold", hyperparameters["threshold"])
396
+ if isinstance(hyperparameters["threshold"], list)
397
+ else hyperparameters["threshold"]
398
+ )
261
399
  )
262
400
  num_layers = (
263
401
  hp.Int("num_layers", min_value=1, max_value=10, step=1)
264
402
  if "num_layers" not in hyperparameters_keys
265
- else hyperparameters["num_layers"]
403
+ else (
404
+ hp.Choice("num_layers", hyperparameters["num_layers"])
405
+ if isinstance(hyperparameters["num_layers"], list)
406
+ else hyperparameters["num_layers"]
407
+ )
266
408
  )
267
409
  dropout = (
268
410
  hp.Float("dropout", min_value=0.1, max_value=0.9, sampling="log")
269
411
  if "dropout" not in hyperparameters_keys
270
- else hyperparameters["dropout"]
412
+ else (
413
+ hp.Choice("dropout", hyperparameters["dropout"])
414
+ if isinstance(hyperparameters["dropout"], list)
415
+ else hyperparameters["dropout"]
416
+ )
417
+ )
418
+ l2_reg = (
419
+ hp.Float("l2_reg", min_value=1e-6, max_value=0.1, sampling="log")
420
+ if "l2_reg" not in hyperparameters_keys
421
+ else (
422
+ hp.Choice("l2_reg", hyperparameters["l2_reg"])
423
+ if isinstance(hyperparameters["l2_reg"], list)
424
+ else hyperparameters["l2_reg"]
425
+ )
271
426
  )
272
427
 
273
428
  model = call_existing_code(
@@ -279,6 +434,7 @@ def build_model(
279
434
  num_classes=num_classes,
280
435
  num_layers=num_layers,
281
436
  dropout=dropout,
437
+ l2_reg=l2_reg,
282
438
  )
283
439
  return model
284
440
 
@@ -477,11 +633,31 @@ class GetInsights:
477
633
  )
478
634
  self.data["class"] = self.classification
479
635
  self.data_input["class"] = self.classification
480
- radviz(self.data, "class", color=self.colors)
636
+
637
+ self.data_normalized = self.data.copy(deep=True)
638
+ self.data_normalized.iloc[:, :-1] = (
639
+ 2.0
640
+ * (self.data_normalized.iloc[:, :-1] - self.data_normalized.iloc[:, :-1].min())
641
+ / (self.data_normalized.iloc[:, :-1].max() - self.data_normalized.iloc[:, :-1].min())
642
+ - 1
643
+ )
644
+ radviz(self.data_normalized, "class", color=self.colors)
481
645
  plt.title("Radviz Visualization of Latent Space")
482
646
  plt.show()
483
-
484
- radviz(self.data_input, "class", color=self.colors)
647
+ self.data_input_normalized = self.data_input.copy(deep=True)
648
+ self.data_input_normalized.iloc[:, :-1] = (
649
+ 2.0
650
+ * (
651
+ self.data_input_normalized.iloc[:, :-1]
652
+ - self.data_input_normalized.iloc[:, :-1].min()
653
+ )
654
+ / (
655
+ self.data_input_normalized.iloc[:, :-1].max()
656
+ - self.data_input_normalized.iloc[:, :-1].min()
657
+ )
658
+ - 1
659
+ )
660
+ radviz(self.data_input_normalized, "class", color=self.colors)
485
661
  plt.title("Radviz Visualization of Input Data")
486
662
  plt.show()
487
663
  return self._statistics(self.data_input)
@@ -979,6 +979,7 @@ class PerformanceMeasures:
979
979
  def f_mean(self, y_true: np.ndarray, y_pred: np.ndarray, labels: List[int]) -> float:
980
980
  F_vec = self._f1_score(y_true, y_pred, labels)
981
981
  mean_f_measure = np.mean(F_vec)
982
+ mean_f_measure = np.around(mean_f_measure, decimals=4)
982
983
 
983
984
  for label, f_measure in zip(labels, F_vec):
984
985
  print(f"F-measure of label {label} -> {f_measure}")
@@ -1005,9 +1006,9 @@ class PerformanceMeasures:
1005
1006
 
1006
1007
  def _summary_pred(self, y_true: np.ndarray, y_pred: np.ndarray, labels: List[int]) -> None:
1007
1008
  count_mat = self._confu_mat(y_true, y_pred, labels)
1008
- print(" ", " | ".join(f"--{label}--" for label in labels))
1009
+ print(" " * 6, " | ".join(f"--{label}--" for label in labels))
1009
1010
  for i, label_i in enumerate(labels):
1010
- row = [f" {int(count_mat[i, j])} " for j in range(len(labels))]
1011
+ row = [f" {int(count_mat[i, j]):5d} " for j in range(len(labels))]
1011
1012
  print(f"--{label_i}--|", " | ".join(row))
1012
1013
 
1013
1014
  def _f1_score(self, y_true: np.ndarray, y_pred: np.ndarray, labels: List[int]) -> np.ndarray:
@@ -1023,6 +1024,7 @@ class PerformanceMeasures:
1023
1024
  count_mat.diagonal(), sum_rows, out=np.zeros_like(sum_rows), where=sum_rows != 0
1024
1025
  )
1025
1026
  f1_vec = 2 * ((precision * recall) / (precision + recall))
1027
+ f1_vec = np.around(f1_vec, decimals=4)
1026
1028
 
1027
1029
  return f1_vec
1028
1030
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: likelihood
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: A package that performs the maximum likelihood algorithm.
5
5
  Home-page: https://github.com/jzsmoreno/likelihood/
6
6
  Author: J. A. Moreno-Guerra
@@ -14,14 +14,16 @@ Requires-Python: >=3.10
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: black[jupyter]>=24.3.0
17
- Requires-Dist: mypy-extensions==1.0.0
18
- Requires-Dist: types-openpyxl==3.1.0.15
19
- Requires-Dist: pydocstyle==6.3.0
20
- Requires-Dist: flake8==6.0.0
21
- Requires-Dist: isort==5.12.0
22
- Requires-Dist: mypy==1.4.1
17
+ Requires-Dist: mypy-extensions>=1.0.0
18
+ Requires-Dist: types-openpyxl>=3.1.0.15
19
+ Requires-Dist: pydocstyle>=6.3.0
20
+ Requires-Dist: flake8>=6.0.0
21
+ Requires-Dist: isort>=5.12.0
22
+ Requires-Dist: mypy>=1.4.1
23
23
  Requires-Dist: numpy<2.0.0
24
+ Requires-Dist: pydot==2.0.0
24
25
  Requires-Dist: matplotlib
26
+ Requires-Dist: graphviz
25
27
  Requires-Dist: pyyaml
26
28
  Requires-Dist: pandas
27
29
  Requires-Dist: corner
@@ -1,12 +1,14 @@
1
1
  black[jupyter]>=24.3.0
2
- mypy-extensions==1.0.0
3
- types-openpyxl==3.1.0.15
4
- pydocstyle==6.3.0
5
- flake8==6.0.0
6
- isort==5.12.0
7
- mypy==1.4.1
2
+ mypy-extensions>=1.0.0
3
+ types-openpyxl>=3.1.0.15
4
+ pydocstyle>=6.3.0
5
+ flake8>=6.0.0
6
+ isort>=5.12.0
7
+ mypy>=1.4.1
8
8
  numpy<2.0.0
9
+ pydot==2.0.0
9
10
  matplotlib
11
+ graphviz
10
12
  pyyaml
11
13
  pandas
12
14
  corner
File without changes
File without changes
File without changes
File without changes