machinegnostics 0.0.1__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 (93) hide show
  1. __init__.py +0 -0
  2. machinegnostics/__init__.py +24 -0
  3. machinegnostics/magcal/__init__.py +37 -0
  4. machinegnostics/magcal/characteristics.py +460 -0
  5. machinegnostics/magcal/criteria_eval.py +268 -0
  6. machinegnostics/magcal/criterion.py +140 -0
  7. machinegnostics/magcal/data_conversion.py +381 -0
  8. machinegnostics/magcal/gcor.py +64 -0
  9. machinegnostics/magcal/gdf/__init__.py +2 -0
  10. machinegnostics/magcal/gdf/base_df.py +39 -0
  11. machinegnostics/magcal/gdf/base_distfunc.py +1202 -0
  12. machinegnostics/magcal/gdf/base_egdf.py +823 -0
  13. machinegnostics/magcal/gdf/base_eldf.py +830 -0
  14. machinegnostics/magcal/gdf/base_qgdf.py +1234 -0
  15. machinegnostics/magcal/gdf/base_qldf.py +1019 -0
  16. machinegnostics/magcal/gdf/cluster_analysis.py +456 -0
  17. machinegnostics/magcal/gdf/data_cluster.py +975 -0
  18. machinegnostics/magcal/gdf/data_intervals.py +853 -0
  19. machinegnostics/magcal/gdf/data_membership.py +536 -0
  20. machinegnostics/magcal/gdf/der_egdf.py +243 -0
  21. machinegnostics/magcal/gdf/distfunc_engine.py +841 -0
  22. machinegnostics/magcal/gdf/egdf.py +324 -0
  23. machinegnostics/magcal/gdf/eldf.py +297 -0
  24. machinegnostics/magcal/gdf/eldf_intv.py +609 -0
  25. machinegnostics/magcal/gdf/eldf_ma.py +627 -0
  26. machinegnostics/magcal/gdf/homogeneity.py +1218 -0
  27. machinegnostics/magcal/gdf/intv_engine.py +1523 -0
  28. machinegnostics/magcal/gdf/marginal_intv_analysis.py +558 -0
  29. machinegnostics/magcal/gdf/qgdf.py +289 -0
  30. machinegnostics/magcal/gdf/qldf.py +296 -0
  31. machinegnostics/magcal/gdf/scedasticity.py +197 -0
  32. machinegnostics/magcal/gdf/wedf.py +181 -0
  33. machinegnostics/magcal/gdf/z0_estimator.py +1047 -0
  34. machinegnostics/magcal/layer_base.py +42 -0
  35. machinegnostics/magcal/layer_history_base.py +74 -0
  36. machinegnostics/magcal/layer_io_process_base.py +238 -0
  37. machinegnostics/magcal/layer_param_base.py +448 -0
  38. machinegnostics/magcal/mg_weights.py +36 -0
  39. machinegnostics/magcal/sample_characteristics.py +532 -0
  40. machinegnostics/magcal/scale_optimization.py +185 -0
  41. machinegnostics/magcal/scale_param.py +313 -0
  42. machinegnostics/magcal/util/__init__.py +0 -0
  43. machinegnostics/magcal/util/dis_docstring.py +18 -0
  44. machinegnostics/magcal/util/logging.py +24 -0
  45. machinegnostics/magcal/util/min_max_float.py +34 -0
  46. machinegnostics/magnet/__init__.py +0 -0
  47. machinegnostics/metrics/__init__.py +28 -0
  48. machinegnostics/metrics/accu.py +61 -0
  49. machinegnostics/metrics/accuracy.py +67 -0
  50. machinegnostics/metrics/auto_correlation.py +183 -0
  51. machinegnostics/metrics/auto_covariance.py +204 -0
  52. machinegnostics/metrics/cls_report.py +130 -0
  53. machinegnostics/metrics/conf_matrix.py +93 -0
  54. machinegnostics/metrics/correlation.py +178 -0
  55. machinegnostics/metrics/cross_variance.py +167 -0
  56. machinegnostics/metrics/divi.py +82 -0
  57. machinegnostics/metrics/evalmet.py +109 -0
  58. machinegnostics/metrics/f1_score.py +128 -0
  59. machinegnostics/metrics/gmmfe.py +108 -0
  60. machinegnostics/metrics/hc.py +141 -0
  61. machinegnostics/metrics/mae.py +72 -0
  62. machinegnostics/metrics/mean.py +117 -0
  63. machinegnostics/metrics/median.py +122 -0
  64. machinegnostics/metrics/mg_r2.py +167 -0
  65. machinegnostics/metrics/mse.py +78 -0
  66. machinegnostics/metrics/precision.py +119 -0
  67. machinegnostics/metrics/r2.py +122 -0
  68. machinegnostics/metrics/recall.py +108 -0
  69. machinegnostics/metrics/rmse.py +77 -0
  70. machinegnostics/metrics/robr2.py +119 -0
  71. machinegnostics/metrics/std.py +144 -0
  72. machinegnostics/metrics/variance.py +101 -0
  73. machinegnostics/models/__init__.py +2 -0
  74. machinegnostics/models/classification/__init__.py +1 -0
  75. machinegnostics/models/classification/layer_history_log_reg.py +121 -0
  76. machinegnostics/models/classification/layer_io_process_log_reg.py +98 -0
  77. machinegnostics/models/classification/layer_mlflow_log_reg.py +107 -0
  78. machinegnostics/models/classification/layer_param_log_reg.py +275 -0
  79. machinegnostics/models/classification/mg_log_reg.py +273 -0
  80. machinegnostics/models/cross_validation.py +118 -0
  81. machinegnostics/models/data_split.py +106 -0
  82. machinegnostics/models/regression/__init__.py +2 -0
  83. machinegnostics/models/regression/layer_histroy_rob_reg.py +139 -0
  84. machinegnostics/models/regression/layer_io_process_rob_rig.py +88 -0
  85. machinegnostics/models/regression/layer_mlflow_rob_reg.py +134 -0
  86. machinegnostics/models/regression/layer_param_rob_reg.py +212 -0
  87. machinegnostics/models/regression/mg_lin_reg.py +253 -0
  88. machinegnostics/models/regression/mg_poly_reg.py +258 -0
  89. machinegnostics-0.0.1.dist-info/METADATA +246 -0
  90. machinegnostics-0.0.1.dist-info/RECORD +93 -0
  91. machinegnostics-0.0.1.dist-info/WHEEL +5 -0
  92. machinegnostics-0.0.1.dist-info/licenses/LICENSE +674 -0
  93. machinegnostics-0.0.1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,268 @@
1
+ '''
2
+ ManGo - Machine Gnostics Library
3
+ Copyright (C) 2025 ManGo Team
4
+
5
+ Author: Nirmal Parmar
6
+ Machine Gnostics
7
+ '''
8
+
9
+ import numpy as np
10
+ from machinegnostics.magcal.characteristics import GnosticsCharacteristics
11
+ from machinegnostics.magcal.sample_characteristics import GnosticCharacteristicsSample
12
+ import logging
13
+ from machinegnostics.magcal.util.logging import get_logger
14
+
15
+ class CriteriaEvaluator:
16
+ """
17
+ A class to evaluate the performance of a model's fit to data using various statistical and information-theoretic metrics.
18
+
19
+ This class computes several evaluation metrics, including:
20
+ - Robust R-squared (RobR2): A robust measure of the goodness of fit.
21
+ - Geometric Mean of Model Fit Error (GMMFE): A measure of the average relative error between the observed and fitted values.
22
+ - Divergence Information (DivI): A measure of the divergence between the distributions of observed and fitted values.
23
+ - Evaluation Metric (EvalMet): A composite metric combining RobR2, GMMFE, and DivI.
24
+
25
+ The class also provides a method to generate a report summarizing these metrics.
26
+
27
+ Attributes:
28
+ y (np.ndarray): The observed data (ground truth).
29
+ y_fit (np.ndarray): The fitted data (model predictions).
30
+ w (np.ndarray): Weights for the data points. Defaults to an array of ones if not provided.
31
+ robr2 (float): The computed Robust R-squared value. Initialized to None.
32
+ gmmfe (float): The computed Geometric Mean of Model Fit Error. Initialized to None.
33
+ divI (float): The computed Divergence Information value. Initialized to None.
34
+ evalmet (float): The computed Evaluation Metric. Initialized to None.
35
+ _report (dict): A dictionary containing the computed metrics. Initialized to an empty dictionary.
36
+
37
+ Methods:
38
+ __init__(y, y_fit, w=None):
39
+ Initializes the CriteriaEvaluator with observed data, fitted data, and optional weights.
40
+
41
+ _robr2():
42
+ Computes the Robust R-squared (RobR2) value. This metric measures the proportion of variance in the observed data
43
+ explained by the fitted data, with robustness to outliers.
44
+
45
+ _gmmfe():
46
+ Computes the Geometric Mean of Model Fit Error (GMMFE). This metric quantifies the average relative error between
47
+ the observed and fitted values on a logarithmic scale.
48
+
49
+ _divI():
50
+ Computes the Divergence Information (DivI). This metric measures the divergence between the distributions of the
51
+ observed and fitted values using gnostic characteristics.
52
+
53
+ _evalmet():
54
+ Computes the Evaluation Metric (EvalMet) as a composite measure combining RobR2, GMMFE, and DivI.
55
+
56
+ generate_report():
57
+ Generates a report summarizing all computed metrics (RobR2, GMMFE, DivI, and EvalMet) in a dictionary format.
58
+
59
+ Usage:
60
+ Example 1: Basic Usage
61
+ -----------------------
62
+ y = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
63
+ y_fit = np.array([1.1, 1.9, 3.2, 3.8, 5.1])
64
+ evaluator = CriteriaEvaluator(y, y_fit)
65
+
66
+ robr2 = evaluator._robr2()
67
+ print("Robust R-squared:", robr2)
68
+
69
+ gmmfe = evaluator._gmmfe()
70
+ print("Geometric Mean of Model Fit Error:", gmmfe)
71
+
72
+ divI = evaluator._divI()
73
+ print("Divergence Information:", divI)
74
+
75
+ evalmet = evaluator._evalmet()
76
+ print("Evaluation Metric:", evalmet)
77
+
78
+ report = evaluator.generate_report()
79
+ print("Report:", report)
80
+
81
+ Example 2: Using Weights
82
+ ------------------------
83
+ y = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
84
+ y_fit = np.array([1.1, 1.9, 3.2, 3.8, 5.1])
85
+ weights = np.array([1, 2, 1, 2, 1])
86
+ evaluator = CriteriaEvaluator(y, y_fit, w=weights)
87
+
88
+ robr2 = evaluator._robr2()
89
+ print("Weighted Robust R-squared:", robr2)
90
+
91
+ gmmfe = evaluator._gmmfe()
92
+ print("Weighted Geometric Mean of Model Fit Error:", gmmfe)
93
+
94
+ divI = evaluator._divI()
95
+ print("Weighted Divergence Information:", divI)
96
+
97
+ evalmet = evaluator._evalmet()
98
+ print("Weighted Evaluation Metric:", evalmet)
99
+
100
+ report = evaluator.generate_report()
101
+ print("Weighted Report:", report)
102
+
103
+ Notes:
104
+ - The class assumes that `y` and `y_fit` are non-negative and of the same shape.
105
+ - The methods `_robr2`, `_gmmfe`, `_divI`, and `_evalmet` are designed to be called internally, but they can be
106
+ invoked directly if needed.
107
+ - The `generate_report` method ensures that all metrics are computed before generating the report.
108
+ """
109
+ def __init__(self, y, y_fit, w=None, verbose: bool = False):
110
+ self.y = np.asarray(y)
111
+ self.y_fit = np.asarray(y_fit)
112
+ self.w = np.ones_like(self.y) if w is None else np.asarray(w)
113
+ self.robr2 = None
114
+ self.gmmfe = None
115
+ self.divI = None
116
+ self.evalmet = None
117
+ self._report = {}
118
+
119
+ # logger setup
120
+ self.logger = get_logger(self.__class__.__name__, logging.DEBUG if verbose else logging.WARNING)
121
+ self.logger.debug(f"{self.__class__.__name__} initialized:")
122
+
123
+ def _robr2(self):
124
+ """
125
+ Computes the Robust R-squared (RobR2) value.
126
+
127
+ This metric measures the proportion of variance in the observed data explained by the fitted data,
128
+ with robustness to outliers. It is calculated as:
129
+
130
+ RobR2 = 1 - (Weighted Sum of Squared Errors / Weighted Total Sum of Squares)
131
+
132
+ Returns:
133
+ float: The computed Robust R-squared value. A value closer to 1 indicates a better fit.
134
+ """
135
+ self.logger.info("Calculating Robust R-squared (RobR2).")
136
+ e = self.y - self.y_fit
137
+ e_bar = np.sum(self.w * e) / np.sum(self.w)
138
+ y_bar = np.sum(self.w * self.y) / np.sum(self.w)
139
+ num = np.sum(self.w * (e - e_bar) ** 2)
140
+ denom = np.sum(self.w * (self.y - y_bar) ** 2)
141
+ self.robr2 = 1 - num / denom if denom != 0 else 0.0
142
+ self.logger.info(f"Robust R-squared (RobR2) calculated: {self.robr2}")
143
+ return self.robr2
144
+
145
+ def _gmmfe(self):
146
+ """
147
+ Computes the Geometric Mean of Model Fit Error (GMMFE).
148
+
149
+ This metric quantifies the average relative error between the observed and fitted values on a logarithmic scale.
150
+ It is robust to outliers and provides a measure of the average multiplicative error.
151
+
152
+ Returns:
153
+ float: The computed GMMFE value. A value closer to 1 indicates a better fit.
154
+ """
155
+ self.logger.info("Calculating Geometric Mean of Model Fit Error (GMMFE).")
156
+ epsilon = 1e-10 # Small value to prevent division by zero
157
+ # avoid log failure
158
+ zz = self.y / (self.y_fit + epsilon)
159
+ zz = np.clip(zz, epsilon, None) # Clip values to avoid invalid log
160
+ log_ratios = np.abs(np.log(zz))
161
+ # avoid exp failure
162
+ log_ratios = np.clip(log_ratios, None, 100) # Clip values to avoid invalid exp
163
+ self.gmmfe = np.exp(np.mean(log_ratios))
164
+ self.logger.info(f"Geometric Mean of Model Fit Error (GMMFE) calculated: {self.gmmfe}")
165
+ return self.gmmfe
166
+
167
+ def _divI(self):
168
+ """
169
+ Computes the Divergence Information (DivI).
170
+
171
+ This metric measures the divergence between the distributions of the observed and fitted values using gnostic characteristics.
172
+ It involves calculating the gnostic characteristics of the observed and fitted data, and then computing the divergence
173
+ in their information content.
174
+
175
+ Returns:
176
+ float: The computed Divergence Information value. A lower value indicates less divergence and a better fit.
177
+ """
178
+ self.logger.info("Calculating Divergence Information (DivI).")
179
+ gcs_y = GnosticCharacteristicsSample(data=self.y)
180
+ gcs_y_fit = GnosticCharacteristicsSample(data=self.y_fit)
181
+
182
+ # y_median = gcs_y._gnostic_median(case='i').root
183
+ # y_fit_median = gcs_y_fit._gnostic_median(case='i').root
184
+
185
+ y_median = np.median(self.y) # Using numpy median for simplicity NOTE
186
+ y_fit_median = np.median(self.y_fit)
187
+
188
+ zy = self.y / y_median
189
+ zf = self.y_fit / y_fit_median
190
+
191
+ gc_y = GnosticsCharacteristics(zy)
192
+ gc_y_fit = GnosticsCharacteristics(zf)
193
+
194
+ qy, q1y = gc_y._get_q_q1()
195
+ qf, q1f = gc_y_fit._get_q_q1()
196
+
197
+ hi = gc_y._hi(q=qy, q1=q1y)
198
+ hi_fit = gc_y_fit._hi(q=qf, q1=q1f)
199
+
200
+ pi = gc_y._idistfun(hi)
201
+ pi_fit = gc_y_fit._idistfun(hi_fit)
202
+
203
+ epsilon = 1e-10 # Small value to prevent log(0)
204
+ pi = np.clip(pi, epsilon, 1 - epsilon) # Clip values to avoid invalid log
205
+ pi_fit = np.clip(pi_fit, epsilon, 1 - epsilon) # Clip values to avoid invalid log
206
+
207
+ Iy = gc_y._info_i(pi)
208
+ Iy_fit = gc_y_fit._info_i(pi_fit)
209
+
210
+ self.divI = np.mean(Iy / Iy_fit)
211
+ self.logger.info(f"Divergence Information (DivI) calculated: {self.divI}")
212
+ return self.divI
213
+
214
+ def _evalmet(self):
215
+ """
216
+ Computes the Evaluation Metric (EvalMet).
217
+
218
+ This is a composite metric that combines Robust R-squared (RobR2), Geometric Mean of Model Fit Error (GMMFE),
219
+ and Divergence Information (DivI). It is calculated as:
220
+
221
+ EvalMet = RobR2 / (GMMFE * DivI)
222
+
223
+ Returns:
224
+ float: The computed Evaluation Metric. A higher value indicates a better overall fit.
225
+ """
226
+ self.logger.info("Calculating Evaluation Metric (EvalMet).")
227
+ if self.robr2 is None:
228
+ self._robr2()
229
+ if self.gmmfe is None:
230
+ self._gmmfe()
231
+ if self.divI is None:
232
+ self._divI()
233
+ self.evalmet = self.robr2 / (self.gmmfe * self.divI)
234
+ self.logger.info(f"Evaluation Metric (EvalMet) calculated: {self.evalmet}")
235
+ return self.evalmet
236
+
237
+ def generate_report(self):
238
+ """
239
+ Generates a report summarizing all computed metrics.
240
+
241
+ This method ensures that all metrics (RobR2, GMMFE, DivI, and EvalMet) are computed before generating the report.
242
+ The report is returned as a dictionary containing the metric names and their corresponding values.
243
+
244
+ Returns:
245
+ dict: A dictionary containing the computed metrics:
246
+ - "RobR2": Robust R-squared value.
247
+ - "GMMFE": Geometric Mean of Model Fit Error.
248
+ - "DivI": Divergence Information.
249
+ - "EvalMet": Evaluation Metric.
250
+ """
251
+ self.logger.info("Generating evaluation report.")
252
+ if self.robr2 is None:
253
+ self._robr2()
254
+ if self.gmmfe is None:
255
+ self._gmmfe()
256
+ if self.divI is None:
257
+ self._divI()
258
+ if self.evalmet is None:
259
+ self._evalmet()
260
+
261
+ self._report = {
262
+ "RobR2": self.robr2,
263
+ "GMMFE": self.gmmfe,
264
+ "DivI": self.divI,
265
+ "EvalMet": self.evalmet
266
+ }
267
+ self.logger.info("Evaluation report generated.")
268
+ return self._report
@@ -0,0 +1,140 @@
1
+ '''
2
+ ManGo - Machine Gnostics Library
3
+ Copyright (C) 2025 ManGo Team
4
+
5
+ Author: Nirmal Parmar
6
+ '''
7
+ import numpy as np
8
+
9
+
10
+ class GnosticCriterion:
11
+ """
12
+ A class to compute Gnostic Error Functions for Machine Gnostics Regression.
13
+ Gnostic Error Functions for Machine Gnostics Regression.
14
+ Reference: TABLE 19.2, p. 19-4, in the provided reference.
15
+ """
16
+
17
+ @staticmethod
18
+ def _compute_error(case:str, f_j=None, f_i=None, h_j=None, h_i=None):
19
+ """
20
+ Compute the error function based on the specified case.
21
+
22
+ Args:
23
+ case (str): The case to compute the error for ('Q1', 'E1', 'Q2', 'E2', 'Q3', 'E3').
24
+ f_j (float): Filtering weight for J cases.
25
+ f_i (float): Filtering weight for I cases.
26
+ h_j (float): Error function input for J cases.
27
+ h_i (float): Error function input for I cases.
28
+
29
+ Returns:
30
+ float: The computed error function value.
31
+ """
32
+ if case == 'Q1':
33
+ if f_j is None:
34
+ raise ValueError("f_j is required for case Q1")
35
+ return f_j # h_j = f_j
36
+
37
+ elif case == 'E1':
38
+ if f_i is None:
39
+ raise ValueError("f_i is required for case E1")
40
+ return f_i # h_i = f_i
41
+
42
+ elif case == 'Q2':
43
+ if f_j is None or h_j is None:
44
+ raise ValueError("f_j and h_j are required for case Q2")
45
+ return f_j * np.arctan(h_j) # f_j * arctan(h_j)
46
+
47
+ elif case == 'E2':
48
+ if f_i is None or h_i is None:
49
+ raise ValueError("f_i and h_i are required for case E2")
50
+ return f_i * np.arctanh(h_i) # f_i * arctanh(h_i)
51
+
52
+ elif case == 'Q3':
53
+ if f_j is None or h_j is None:
54
+ raise ValueError("f_j and h_j are required for case Q3")
55
+ return np.sqrt(f_j) * h_j # sqrt(f_j) * h_j
56
+
57
+ elif case == 'E3':
58
+ if f_i is None or h_i is None:
59
+ raise ValueError("f_i and h_i are required for case E3")
60
+ return np.sqrt(f_i) * h_i # sqrt(f_i) * h_i
61
+
62
+ else:
63
+ raise ValueError(f"Invalid case: {case}. Valid cases are 'Q1', 'E1', 'Q2', 'E2', 'Q3', 'E3'.")
64
+
65
+ @staticmethod
66
+ def _get_filtering_weight(case:str, f_j=None, f_i=None):
67
+ """
68
+ Calculate the filtering weight based on the specified case.
69
+
70
+ Args:
71
+ case (str): The case to compute the filtering weight for ('Q1', 'E1', 'Q2', 'E2', 'Q3', 'E3').
72
+ f_j (float): Filtering weight for J cases.
73
+ f_i (float): Filtering weight for I cases.
74
+
75
+ Returns:
76
+ float: The computed filtering weight.
77
+ """
78
+ if case == 'Q1':
79
+ if f_j is None:
80
+ raise ValueError("f_j is required for case Q1")
81
+ return f_j # Filtering weight is f_j
82
+
83
+ elif case == 'E1':
84
+ if f_i is None:
85
+ raise ValueError("f_i is required for case E1")
86
+ return f_i**2 # Filtering weight is f_i^2
87
+
88
+ elif case == 'Q2':
89
+ return 1 # Filtering weight is 1
90
+
91
+ elif case == 'E2':
92
+ if f_i is None:
93
+ raise ValueError("f_i is required for case E2")
94
+ return f_i # Filtering weight is f_i
95
+
96
+ elif case == 'Q3':
97
+ if f_j is None:
98
+ raise ValueError("f_j is required for case Q3")
99
+ return 1 / np.sqrt(f_j) # Filtering weight is 1 / sqrt(f_j)
100
+
101
+ elif case == 'E3':
102
+ if f_i is None:
103
+ raise ValueError("f_i is required for case E3")
104
+ return 1 / np.sqrt(f_i) # Filtering weight is 1 / sqrt(f_i)
105
+
106
+ else:
107
+ raise ValueError(f"Invalid case: {case}. Valid cases are 'Q1', 'E1', 'Q2', 'E2', 'Q3', 'E3'.")
108
+
109
+ @staticmethod
110
+ def _get_gnostic_criterion(case:str, f_j=None, f_i=None, h_j=None, h_i=None, Ii=None, Ij=None):
111
+ """
112
+ Get the gnostic criterion based on the specified case.
113
+
114
+ Args:
115
+ case (str): The case to compute the gnostic criterion for ('Q1', 'E1', 'Q2', 'E2', 'Q3', 'E3').
116
+ f_j (float): Filtering weight for J cases.
117
+ f_i (float): Filtering weight for I cases.
118
+ h_j (float): Error function input for J cases.
119
+ h_i (float): Error function input for I cases.
120
+ Ii (float): Estimating information.
121
+ Ij (float): Quantifying information.
122
+
123
+ Returns:
124
+ float: The computed gnostic criterion value.
125
+
126
+ """
127
+ if case == 'Q1':
128
+ return h_i**2 / 2
129
+ elif case == 'E1':
130
+ return h_j**2 / 2
131
+ elif case == 'Q2':
132
+ return Ij
133
+ elif case == 'E2':
134
+ return Ii
135
+ elif case == 'Q3':
136
+ return f_j
137
+ elif case == 'E3':
138
+ return -f_i
139
+
140
+