Moral88 0.3.0__py3-none-any.whl → 0.5.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.
Moral88/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ from .regression import mean_absolute_error, mean_squared_error, r_squared
Moral88/regression.py CHANGED
@@ -1,145 +1,4 @@
1
1
  import numpy as np
2
-
3
- def validate_inputs(y_true, y_pred):
4
- """
5
- Validate the inputs for type and length.
6
- """
7
- if not isinstance(y_true, (list, tuple, np.ndarray)) or not isinstance(y_pred, (list, tuple, np.ndarray)):
8
- raise TypeError("Both y_true and y_pred must be lists, tuples, or numpy arrays.")
9
-
10
- y_true = np.array(y_true)
11
- y_pred = np.array(y_pred)
12
-
13
- if y_true.shape != y_pred.shape:
14
- raise ValueError("Shapes of y_true and y_pred must be the same.")
15
-
16
- if not np.issubdtype(y_true.dtype, np.number) or not np.issubdtype(y_pred.dtype, np.number):
17
- raise TypeError("All elements in y_true and y_pred must be numeric.")
18
-
19
- def mean_absolute_error(y_true, y_pred, normalize=True, threshold=None, method='mean', library='Moral88', flatten=True):
20
- """
21
- Calculate Mean Absolute Error (MAE) for single or multi-dimensional data.
22
- """
23
- validate_inputs(y_true, y_pred)
24
-
25
- # y_true = np.array(y_true)
26
- # y_pred = np.array(y_pred)
27
-
28
- if flatten:
29
- y_true = y_true.ravel()
30
- y_pred = y_pred.ravel()
31
-
32
- if library == 'Moral88':
33
- if threshold is not None:
34
- y_pred = np.clip(y_pred, threshold[0], threshold[1])
35
-
36
- absolute_errors = np.abs(y_true - y_pred)
37
-
38
- if method == 'mean':
39
- result = np.mean(absolute_errors)
40
- elif method == 'sum':
41
- result = np.sum(absolute_errors)
42
- elif method == 'none':
43
- result = absolute_errors
44
- else:
45
- raise ValueError("Invalid method. Choose from {'mean', 'sum', 'none'}.")
46
-
47
- if normalize and method != 'none':
48
- range_y = np.ptp(y_true)
49
- result = result / max(abs(range_y), 1)
50
-
51
- return result
52
-
53
- elif library == 'sklearn':
54
- from sklearn.metrics import mean_absolute_error as sklearn_mae
55
- return sklearn_mae(y_true, y_pred)
56
-
57
- elif library == 'torch':
58
- import torch
59
- y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
60
- y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
61
- return torch.mean(torch.abs(y_true_tensor - y_pred_tensor)).item()
62
-
63
- elif library == 'tensorflow':
64
- import tensorflow as tf
65
- y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
66
- y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
67
- return tf.reduce_mean(tf.abs(y_true_tensor - y_pred_tensor)).numpy()
68
-
69
- else:
70
- raise ValueError(f"Invalid library: {library}. Choose from {'Moral88', 'sklearn', 'torch', 'tensorflow'}.")
71
-
72
- def mean_squared_error(y_true, y_pred, normalize=True, threshold=None, method='mean', library='Moral88', flatten=True):
73
- """
74
- Calculate Mean Squared Error (MSE) for single or multi-dimensional data.
75
- """
76
- validate_inputs(y_true, y_pred)
77
-
78
- # y_true = np.array(y_true)
79
- # y_pred = np.array(y_pred)
80
-
81
- if flatten:
82
- y_true = y_true.ravel()
83
- y_pred = y_pred.ravel()
84
-
85
- if library == 'Moral88':
86
- if threshold is not None:
87
- y_pred = np.clip(y_pred, threshold[0], threshold[1])
88
-
89
- squared_errors = (y_true - y_pred) ** 2
90
-
91
- if method == 'mean':
92
- result = np.mean(squared_errors)
93
- elif method == 'sum':
94
- result = np.sum(squared_errors)
95
- elif method == 'none':
96
- result = squared_errors
97
- else:
98
- raise ValueError("Invalid method. Choose from {'mean', 'sum', 'none'}.")
99
-
100
- if normalize and method != 'none':
101
- range_y = np.ptp(y_true)
102
- result = result / max(abs(range_y), 1)
103
-
104
- return result
105
-
106
- elif library == 'sklearn':
107
- from sklearn.metrics import mean_squared_error as sklearn_mse
108
- return sklearn_mse(y_true, y_pred)
109
-
110
- elif library == 'torch':
111
- import torch
112
- y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
113
- y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
114
- return torch.mean((y_true_tensor - y_pred_tensor) ** 2).item()
115
-
116
- elif library == 'tensorflow':
117
- import tensorflow as tf
118
- y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
119
- y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
120
- return tf.reduce_mean(tf.square(y_true_tensor - y_pred_tensor)).numpy()
121
-
122
- else:
123
- raise ValueError(f"Invalid library: {library}. Choose from {'Moral88', 'sklearn', 'torch', 'tensorflow'}.")
124
-
125
- def r_squared(y_true, y_pred, flatten=True):
126
- """
127
- Compute R-Squared for single or multi-dimensional data.
128
- """
129
- validate_inputs(y_true, y_pred)
130
-
131
- y_true = np.array(y_true)
132
- y_pred = np.array(y_pred)
133
-
134
- if flatten:
135
- y_true = y_true.ravel()
136
- y_pred = y_pred.ravel()
137
-
138
- ss_total = np.sum((y_true - np.mean(y_true)) ** 2)
139
- ss_residual = np.sum((y_true - y_pred) ** 2)
140
- return 1 - (ss_residual / ss_total)
141
-
142
- import numpy as np
143
2
  import warnings
144
3
  from typing import Union, List, Tuple
145
4
  from scipy import sparse
@@ -231,17 +90,61 @@ class DataValidator:
231
90
  sample_weight = self.is_1d_array(sample_weight)
232
91
  return y_true, y_pred, sample_weight
233
92
 
93
+ def validate_mae_mse_inputs(self, y_true, y_pred, library=None):
94
+ """
95
+ Ensures inputs for MAE and MSE computation are valid.
96
+ """
97
+ y_true, y_pred = self.validate_regression_targets(y_true, y_pred)
98
+ if library not in {None, 'sklearn', 'torch', 'tensorflow', 'Moral88'}:
99
+ raise ValueError(f"Invalid library: {library}. Choose from {{'Moral88', 'sklearn', 'torch', 'tensorflow'}}.")
100
+ return y_true, y_pred
101
+
234
102
 
235
103
  class Metrics:
104
+ def mean_bias_deviation(self, y_true, y_pred, library=None):
105
+ """
106
+ Computes Mean Bias Deviation (MBD).
107
+ """
108
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
109
+
110
+ if library == 'sklearn':
111
+ # Sklearn does not have a direct implementation for MBD
112
+ raise NotImplementedError("Mean Bias Deviation is not implemented in sklearn.")
113
+
114
+ if library == 'torch':
115
+ import torch
116
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
117
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
118
+ bias = torch.mean(y_pred_tensor - y_true_tensor).item()
119
+ return bias
120
+
121
+ if library == 'tensorflow':
122
+ import tensorflow as tf
123
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
124
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
125
+ bias = tf.reduce_mean(y_pred_tensor - y_true_tensor).numpy()
126
+ return bias
127
+
128
+ # Default implementation
129
+ return np.mean(y_pred - y_true)
236
130
  def __init__(self):
237
131
  self.validator = DataValidator()
238
132
 
239
- def r2_score(self, y_true, y_pred, sample_weight=None):
133
+ def r2_score(self, y_true, y_pred, sample_weight=None, library=None):
240
134
  """
241
135
  Computes R2 score.
242
136
  """
243
137
  y_true, y_pred, sample_weight = self.validator.validate_r2_score_inputs(y_true, y_pred, sample_weight)
244
138
 
139
+ if library == 'sklearn':
140
+ from sklearn.metrics import r2_score as sklearn_r2
141
+ return sklearn_r2(y_true, y_pred, sample_weight=sample_weight)
142
+
143
+ if library == 'statsmodels':
144
+ import statsmodels.api as sm
145
+ model = sm.OLS(y_true, sm.add_constant(y_pred)).fit()
146
+ return model.rsquared
147
+
245
148
  numerator = np.sum((y_true - y_pred) ** 2)
246
149
  denominator = np.sum((y_true - np.mean(y_true)) ** 2)
247
150
 
@@ -249,6 +152,179 @@ class Metrics:
249
152
  return 0.0
250
153
  return 1 - (numerator / denominator)
251
154
 
155
+ def mean_absolute_error(self, y_true, y_pred, normalize=True, threshold=None, method='mean', library='Moral88', flatten=True):
156
+ """
157
+ Computes Mean Absolute Error (MAE).
158
+ """
159
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
160
+
161
+ if flatten:
162
+ y_true = y_true.ravel()
163
+ y_pred = y_pred.ravel()
164
+
165
+ if library == 'Moral88':
166
+ if threshold is not None:
167
+ y_pred = np.clip(y_pred, threshold[0], threshold[1])
168
+
169
+ absolute_errors = np.abs(y_true - y_pred)
170
+
171
+ if method == 'mean':
172
+ result = np.mean(absolute_errors)
173
+ elif method == 'sum':
174
+ result = np.sum(absolute_errors)
175
+ elif method == 'none':
176
+ result = absolute_errors
177
+ else:
178
+ raise ValueError("Invalid method. Choose from {'mean', 'sum', 'none'}.")
179
+
180
+ if normalize and method != 'none':
181
+ range_y = np.ptp(y_true)
182
+ result = result / max(abs(range_y), 1)
183
+
184
+ return result
185
+
186
+ elif library == 'sklearn':
187
+ from sklearn.metrics import mean_absolute_error as sklearn_mae
188
+ return sklearn_mae(y_true, y_pred)
189
+
190
+ elif library == 'torch':
191
+ import torch
192
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
193
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
194
+ return torch.mean(torch.abs(y_true_tensor - y_pred_tensor)).item()
195
+
196
+ elif library == 'tensorflow':
197
+ import tensorflow as tf
198
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
199
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
200
+ return tf.reduce_mean(tf.abs(y_true_tensor - y_pred_tensor)).numpy()
201
+
202
+ def mean_squared_error(self, y_true, y_pred, normalize=True, threshold=None, method='mean', library='Moral88', flatten=True):
203
+ """
204
+ Computes Mean Squared Error (MSE).
205
+ """
206
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
207
+
208
+ if flatten:
209
+ y_true = y_true.ravel()
210
+ y_pred = y_pred.ravel()
211
+
212
+ if library == 'Moral88':
213
+ if threshold is not None:
214
+ y_pred = np.clip(y_pred, threshold[0], threshold[1])
215
+
216
+ squared_errors = (y_true - y_pred) ** 2
217
+
218
+ if method == 'mean':
219
+ result = np.mean(squared_errors)
220
+ elif method == 'sum':
221
+ result = np.sum(squared_errors)
222
+ elif method == 'none':
223
+ result = squared_errors
224
+ else:
225
+ raise ValueError("Invalid method. Choose from {'mean', 'sum', 'none'}.")
226
+
227
+ if normalize and method != 'none':
228
+ range_y = np.ptp(y_true)
229
+ result = result / max(abs(range_y), 1)
230
+
231
+ return result
232
+
233
+ elif library == 'sklearn':
234
+ from sklearn.metrics import mean_squared_error as sklearn_mse
235
+ return sklearn_mse(y_true, y_pred)
236
+
237
+ elif library == 'torch':
238
+ import torch
239
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
240
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
241
+ return torch.mean((y_true_tensor - y_pred_tensor) ** 2).item()
242
+
243
+ elif library == 'tensorflow':
244
+ import tensorflow as tf
245
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
246
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
247
+ return tf.reduce_mean(tf.square(y_true_tensor - y_pred_tensor)).numpy()
248
+
249
+ def root_mean_squared_error(self, y_true, y_pred, library=None):
250
+ """
251
+ Computes Root Mean Squared Error (RMSE).
252
+ """
253
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
254
+
255
+ if library == 'sklearn':
256
+ from sklearn.metrics import mean_squared_error as sklearn_mse
257
+ return np.sqrt(sklearn_mse(y_true, y_pred))
258
+
259
+ if library == 'torch':
260
+ import torch
261
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
262
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
263
+ return torch.sqrt(torch.mean((y_true_tensor - y_pred_tensor) ** 2)).item()
264
+
265
+ if library == 'tensorflow':
266
+ import tensorflow as tf
267
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
268
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
269
+ return tf.sqrt(tf.reduce_mean(tf.square(y_true_tensor - y_pred_tensor))).numpy()
270
+
271
+ mse = self.mean_squared_error(y_true, y_pred)
272
+ return np.sqrt(mse)
273
+
274
+ def mean_absolute_percentage_error(self, y_true, y_pred, library=None):
275
+ """
276
+ Computes Mean Absolute Percentage Error (MAPE).
277
+ """
278
+ y_true, y_pred = self.validator.validate_regression_targets(y_true, y_pred)
279
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
280
+
281
+ if library == 'sklearn':
282
+ from sklearn.metrics import mean_absolute_percentage_error as sklearn_mape
283
+ return sklearn_mape(y_true, y_pred) * 100
284
+
285
+ if library == 'torch':
286
+ import torch
287
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
288
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
289
+ return torch.mean(torch.abs((y_true_tensor - y_pred_tensor) / torch.clamp(y_true_tensor, min=1e-8))).item() * 100
290
+
291
+ if library == 'tensorflow':
292
+ import tensorflow as tf
293
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
294
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
295
+ return tf.reduce_mean(tf.abs((y_true_tensor - y_pred_tensor) / tf.clip_by_value(y_true_tensor, 1e-8, tf.float32.max))).numpy() * 100
296
+
297
+ return np.mean(np.abs((y_true - y_pred) / np.clip(y_true, 1e-8, None))) * 100
298
+
299
+ def explained_variance_score(self, y_true, y_pred, library=None):
300
+ """
301
+ Computes Explained Variance Score.
302
+ """
303
+ y_true, y_pred = self.validator.validate_mae_mse_inputs(y_true, y_pred, library)
304
+
305
+ if library == 'sklearn':
306
+ from sklearn.metrics import explained_variance_score as sklearn_evs
307
+ return sklearn_evs(y_true, y_pred)
308
+
309
+ if library == 'torch':
310
+ import torch
311
+ y_true_tensor = torch.tensor(y_true, dtype=torch.float32)
312
+ y_pred_tensor = torch.tensor(y_pred, dtype=torch.float32)
313
+ variance_residual = torch.var(y_true_tensor - y_pred_tensor)
314
+ variance_y = torch.var(y_true_tensor)
315
+ return 1 - variance_residual / variance_y if variance_y != 0 else 0
316
+
317
+ if library == 'tensorflow':
318
+ import tensorflow as tf
319
+ y_true_tensor = tf.convert_to_tensor(y_true, dtype=tf.float32)
320
+ y_pred_tensor = tf.convert_to_tensor(y_pred, dtype=tf.float32)
321
+ variance_residual = tf.math.reduce_variance(y_true_tensor - y_pred_tensor)
322
+ variance_y = tf.math.reduce_variance(y_true_tensor)
323
+ return 1 - variance_residual / variance_y if variance_y != 0 else 0
324
+
325
+ numerator = np.var(y_true - y_pred)
326
+ denominator = np.var(y_true)
327
+ return 1 - numerator / denominator if denominator != 0 else 0
252
328
 
253
329
  if __name__ == '__main__':
254
330
  # Example usage
@@ -264,3 +340,7 @@ if __name__ == '__main__':
264
340
  y_true = [3, -0.5, 2, 7]
265
341
  y_pred = [2.5, 0.0, 2, 8]
266
342
  print("R2 Score:", metrics.r2_score(y_true, y_pred))
343
+
344
+ # Test MAE and MSE
345
+ print("Mean Absolute Error:", metrics.mean_absolute_error(y_true, y_pred))
346
+ print("Mean Squared Error:", metrics.mean_squared_error(y_true, y_pred))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Moral88
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: A library for regression evaluation metrics.
5
5
  Author: Morteza Alizadeh
6
6
  Author-email: alizadeh.c2m@gmail.com
@@ -0,0 +1,8 @@
1
+ Moral88/__init__.py,sha256=vb-aPc9ZbnYNSy9qq2fVESI63E10pYsCrDpnV8OHWkg,74
2
+ Moral88/regression.py,sha256=MjM3R1oqRWdlfo6Goc2NOT0UHeKGcQfdMyriqSvS5q4,14127
3
+ Moral88/segmentation.py,sha256=v0yqxdrKbM9LM7wVKLjJ4HrhrSrilNNeWS6-oK_27Ag,1363
4
+ Moral88-0.5.0.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ Moral88-0.5.0.dist-info/METADATA,sha256=7_93ZrGO0rFBargNBBe7qvQzQnFi2BFN7RGss26ux3I,407
6
+ Moral88-0.5.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
7
+ Moral88-0.5.0.dist-info/top_level.txt,sha256=-dyn5iTprnSUHbtMpvRO-prJsIoaRxao7wlfCHLSsv4,8
8
+ Moral88-0.5.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- Moral88/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- Moral88/regression.py,sha256=kfWQcdtdZVlHW_iIRbS9_rNrKJOYNiT9RaeYpVIvl7I,9355
3
- Moral88/segmentation.py,sha256=v0yqxdrKbM9LM7wVKLjJ4HrhrSrilNNeWS6-oK_27Ag,1363
4
- Moral88-0.3.0.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- Moral88-0.3.0.dist-info/METADATA,sha256=rKJtI5aX0pT3DSORLtFmsMPYB8fiAbGNQKmEndRNPtI,407
6
- Moral88-0.3.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
7
- Moral88-0.3.0.dist-info/top_level.txt,sha256=-dyn5iTprnSUHbtMpvRO-prJsIoaRxao7wlfCHLSsv4,8
8
- Moral88-0.3.0.dist-info/RECORD,,