From 82adfa45cc02000e972cf2430252fa300b3b60bd Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Mon, 15 Aug 2022 21:09:37 +0800 Subject: [PATCH 1/8] add regression functions --- .../bigdl/chronos/metric/forecast_metrics.py | 92 +++++++++++-------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py index b51b12126a2..e63c2b7d151 100644 --- a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py +++ b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py @@ -14,13 +14,8 @@ # limitations under the License. # -import torch -import numpy as np -from torch import Tensor from numpy import ndarray -from functools import partial -from torchmetrics.functional import mean_squared_error, mean_absolute_error,\ - mean_absolute_percentage_error, r2_score +import numpy as np from bigdl.nano.utils.log4Error import invalidInputError from timeit import repeat @@ -28,23 +23,54 @@ EPSILON = 1e-10 -# implemented this metric to keep up with orca.automl -def symmetric_mean_absolute_percentage_error(preds: Tensor, target: Tensor) -> Tensor: - abs_diff = torch.abs(preds - target) - abs_per_error = abs_diff / (torch.abs(preds) + torch.abs(target) + EPSILON) - sum_abs_per_error = 100 * torch.sum(abs_per_error) - num_obs = target.numel() - return sum_abs_per_error / num_obs +def mae(y_label, y_predict): + """ + Calculate the mean absolute error (MAE). + .. math:: + \\text{MAE} = \\frac{1}{n}\\sum_{t=1}^n |y_t-\\hat{y_t}| + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + A non-negative floating point value (the best value is 0.0), or an + array of floating point values, one for each individual target. + """ + y_label=np.array(y_label) + y_predict=np.array(y_predict) + result= np.mean(np.abs(y_label-y_predict)) + return result + + +def mse(y_label, y_predict): + y_label=np.array(y_label) + y_predict=np.array(y_predict) + result= np.mean((y_label-y_predict)**2) + return result + + +def rmse(y_label, y_predict): + return np.sqrt(mse(y_label, y_predict)) + +def mape(y_label, y_predict): + y_label, y_predict = np.array(y_label), np.array(y_predict) + return np.mean(np.abs((y_label - y_predict) / y_label)) -TORCHMETRICS_REGRESSION_MAP = { - 'mae': mean_absolute_error, - 'mse': mean_squared_error, - 'rmse': partial(mean_squared_error, squared=False), - 'mape': mean_absolute_percentage_error, - 'smape': symmetric_mean_absolute_percentage_error, - 'r2': r2_score, -} + +def smape(y_label, y_predict): + abs_diff = np.abs(y_predict - y_label) + abs_per_error = abs_diff / (np.abs(y_predict) + np.abs(y_label) + EPSILON) + sum_abs_per_error = np.mean(abs_per_error) + return sum_abs_per_error * 100 + + +def r2(y_label, y_predict): + y_label, y_predict = np.array(y_label), np.array(y_predict) + return 1 - np.sum((y_label - y_predict)**2) / np.sum((y_label - np.mean(y_label))**2) + + +REGRESSION_MAP = {'mae', 'mse', 'rmse', 'mape', 'smape', 'r2'} def _standard_input(metrics, y_true, y_pred): @@ -57,13 +83,12 @@ def _standard_input(metrics, y_true, y_pred): metrics = [metrics] if isinstance(metrics[0], str): metrics = list(map(lambda x: x.lower(), metrics)) - invalidInputError(all(metric in TORCHMETRICS_REGRESSION_MAP.keys() for metric in metrics), - f"metric should be one of {TORCHMETRICS_REGRESSION_MAP.keys()}," + invalidInputError(all(metric in REGRESSION_MAP for metric in metrics), + f"metric should be one of {REGRESSION_MAP}," f" but get {metrics}.") invalidInputError(type(y_true) is type(y_pred) and isinstance(y_pred, ndarray), "y_pred and y_true type must be numpy.ndarray," f" but found {type(y_pred)} and {type(y_true)}.") - y_true, y_pred = torch.from_numpy(y_true), torch.from_numpy(y_pred) invalidInputError(y_true.shape == y_pred.shape, "y_true and y_pred should have the same shape, " @@ -91,7 +116,6 @@ class Evaluator(object): def evaluate(metrics, y_true, y_pred, aggregate='mean'): """ Evaluate a specific metrics for y_true and y_pred. - :param metrics: String or list in ['mae', 'mse', 'rmse', 'r2', 'mape', 'smape'] for built-in metrics. If callable function, it signature should be func(y_true, y_pred), where y_true and y_pred are numpy ndarray. @@ -100,7 +124,6 @@ def evaluate(metrics, y_true, y_pred, aggregate='mean'): :param aggregate: aggregation method. Currently, "mean" and None are supported, 'mean' represents aggregating by mean, while None will return the element-wise result. The value defaults to 'mean'. - :return: Float or ndarray of floats. A floating point value, or an array of floating point values, one for each individual target. @@ -109,26 +132,15 @@ def evaluate(metrics, y_true, y_pred, aggregate='mean'): res_list = [] for metric in metrics: - if callable(metric): - metric_func = metric - else: - metric_func = TORCHMETRICS_REGRESSION_MAP[metric] if len(original_shape) in [2, 3] and aggregate is None: res = torch.zeros(y_true.shape[-1]) for i in range(y_true.shape[-1]): - if callable(metric): - res[i] = torch.from_numpy(metric_func(y_true[..., i], y_pred[..., i])) - else: - res[i] = metric_func(y_pred[..., i], y_true[..., i]) + res[i] = eval(metric)(y_true[..., i], y_pred[..., i]) res = res.reshape(original_shape[1:]) res_list.append(res.numpy()) else: - if callable(metric): - res = metric_func(y_true, y_pred) - res_list.append(res) - else: - res = metric_func(y_pred, y_true) - res_list.append(res.numpy()) + res = eval(metric)(y_true, y_pred) + res_list.append(res) return res_list def get_latency(func, *args, num_running=100, **kwargs): From f2e681e16ed3993f92803586d66ba3e983bac3be Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Tue, 16 Aug 2022 09:45:32 +0800 Subject: [PATCH 2/8] delete unexpected import --- python/chronos/src/bigdl/chronos/metric/forecast_metrics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py index e63c2b7d151..a70f511d115 100644 --- a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py +++ b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py @@ -133,11 +133,11 @@ def evaluate(metrics, y_true, y_pred, aggregate='mean'): res_list = [] for metric in metrics: if len(original_shape) in [2, 3] and aggregate is None: - res = torch.zeros(y_true.shape[-1]) + res = np.zeros(y_true.shape[-1]) for i in range(y_true.shape[-1]): res[i] = eval(metric)(y_true[..., i], y_pred[..., i]) res = res.reshape(original_shape[1:]) - res_list.append(res.numpy()) + res_list.append(res) else: res = eval(metric)(y_true, y_pred) res_list.append(res) From de59d8c19e533be67bcc7e846c96789032e94d56 Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Thu, 18 Aug 2022 00:43:18 +0800 Subject: [PATCH 3/8] add function api --- .../bigdl/chronos/metric/forecast_metrics.py | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py index a70f511d115..29fb3cbf7ae 100644 --- a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py +++ b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py @@ -33,8 +33,7 @@ def mae(y_label, y_predict): :param y_predict: Array-like of shape = (n_samples, \*). Estimated target values. :return: Ndarray of floats. - A non-negative floating point value (the best value is 0.0), or an - array of floating point values, one for each individual target. + An array of non-negative floating point values (the best value is 0.0). """ y_label=np.array(y_label) y_predict=np.array(y_predict) @@ -43,6 +42,17 @@ def mae(y_label, y_predict): def mse(y_label, y_predict): + """ + Calculate the mean squared error (MSE). + .. math:: + \\text{MSE} = \\frac{1}{n}\\sum_{t=1}^n (y_t-\\hat{y_t})^2 + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + An array of non-negative floating point values (the best value is 0.0). + """ y_label=np.array(y_label) y_predict=np.array(y_predict) result= np.mean((y_label-y_predict)**2) @@ -50,15 +60,48 @@ def mse(y_label, y_predict): def rmse(y_label, y_predict): + """ + Calculate square root of the mean squared error (RMSE). + .. math:: + \\text{RMSE} = \\sqrt{(\\frac{1}{n}\\sum_{t=1}^n (y_t-\\hat{y_t})^2)} + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + An array of non-negative floating point values (the best value is 0.0). + """ return np.sqrt(mse(y_label, y_predict)) def mape(y_label, y_predict): + """ + Calculate mean absolute percentage error (MAPE). + .. math:: + \\text{MAPE} = \\frac{100\%}{n}\\sum_{t=1}^n |\\frac{y_t-\\hat{y_t}}{y_t}| + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + An array of non-negative floating point values (the best value is 0.0). + """ y_label, y_predict = np.array(y_label), np.array(y_predict) return np.mean(np.abs((y_label - y_predict) / y_label)) def smape(y_label, y_predict): + """ + Calculate Symmetric mean absolute percentage error (sMAPE). + .. math:: + \\text{sMAPE} = \\frac{100\%}{n} \\sum_{t=1}^n \\frac{|y_t-\\hat{y_t}|}{|y_t|+|\\hat{y_t}|} + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + An array of non-negative floating point values (the best value is 0.0). + """ abs_diff = np.abs(y_predict - y_label) abs_per_error = abs_diff / (np.abs(y_predict) + np.abs(y_label) + EPSILON) sum_abs_per_error = np.mean(abs_per_error) @@ -66,6 +109,17 @@ def smape(y_label, y_predict): def r2(y_label, y_predict): + """ + Calculate the r2 score. + .. math:: + R^2 = 1-\\frac{\\sum_{t=1}^n (y_t-\\hat{y_t})^2}{\\sum_{t=1}^n (y_t-\\bar{y})^2} + :param y_label: Array-like of shape = (n_samples, \*). + Ground truth (correct) target values. + :param y_predict: Array-like of shape = (n_samples, \*). + Estimated target values. + :return: Ndarray of floats. + An array of non-negative floating point values (the best value is 1.0). + """ y_label, y_predict = np.array(y_label), np.array(y_predict) return 1 - np.sum((y_label - y_predict)**2) / np.sum((y_label - np.mean(y_label))**2) From 15940d6d8c68ae0876a132aaa6ef15069120dca7 Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Fri, 19 Aug 2022 08:39:28 +0800 Subject: [PATCH 4/8] remove eval function --- .../bigdl/chronos/metric/forecast_metrics.py | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py index 29fb3cbf7ae..9f78d396cbf 100644 --- a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py +++ b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py @@ -35,9 +35,9 @@ def mae(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 0.0). """ - y_label=np.array(y_label) - y_predict=np.array(y_predict) - result= np.mean(np.abs(y_label-y_predict)) + y_label = np.array(y_label) + y_predict = np.array(y_predict) + result= np.mean(np.abs(y_label - y_predict)) return result @@ -53,9 +53,9 @@ def mse(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 0.0). """ - y_label=np.array(y_label) - y_predict=np.array(y_predict) - result= np.mean((y_label-y_predict)**2) + y_label = np.array(y_label) + y_predict = np.array(y_predict) + result = np.mean((y_label - y_predict) ** 2) return result @@ -124,7 +124,14 @@ def r2(y_label, y_predict): return 1 - np.sum((y_label - y_predict)**2) / np.sum((y_label - np.mean(y_label))**2) -REGRESSION_MAP = {'mae', 'mse', 'rmse', 'mape', 'smape', 'r2'} +REGRESSION_MAP = { + 'mae': mae, + 'mse': mse, + 'rmse': rmse, + 'mape': mape, + 'smape': smape, + 'r2': r2, +} def _standard_input(metrics, y_true, y_pred): @@ -137,8 +144,8 @@ def _standard_input(metrics, y_true, y_pred): metrics = [metrics] if isinstance(metrics[0], str): metrics = list(map(lambda x: x.lower(), metrics)) - invalidInputError(all(metric in REGRESSION_MAP for metric in metrics), - f"metric should be one of {REGRESSION_MAP}," + invalidInputError(all(metric in REGRESSION_MAP.keys() for metric in metrics), + f"metric should be one of {REGRESSION_MAP.keys()}," f" but get {metrics}.") invalidInputError(type(y_true) is type(y_pred) and isinstance(y_pred, ndarray), "y_pred and y_true type must be numpy.ndarray," @@ -186,14 +193,15 @@ def evaluate(metrics, y_true, y_pred, aggregate='mean'): res_list = [] for metric in metrics: + metric_func = REGRESSION_MAP[metric] if len(original_shape) in [2, 3] and aggregate is None: res = np.zeros(y_true.shape[-1]) for i in range(y_true.shape[-1]): - res[i] = eval(metric)(y_true[..., i], y_pred[..., i]) + res[i] = metric_func(y_true[..., i], y_pred[..., i]) res = res.reshape(original_shape[1:]) res_list.append(res) else: - res = eval(metric)(y_true, y_pred) + res = metric_func(y_true, y_pred) res_list.append(res) return res_list From 1e9737918c4c3503caef5ddf6dbceabc167ae9b6 Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Tue, 23 Aug 2022 03:02:31 +0800 Subject: [PATCH 5/8] revised the problems mentioned --- .../src/bigdl/chronos/metric/forecast_metrics.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py index 9f78d396cbf..ea1dc03705c 100644 --- a/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py +++ b/python/chronos/src/bigdl/chronos/metric/forecast_metrics.py @@ -35,9 +35,7 @@ def mae(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 0.0). """ - y_label = np.array(y_label) - y_predict = np.array(y_predict) - result= np.mean(np.abs(y_label - y_predict)) + result = np.mean(np.abs(y_label - y_predict)) return result @@ -53,8 +51,6 @@ def mse(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 0.0). """ - y_label = np.array(y_label) - y_predict = np.array(y_predict) result = np.mean((y_label - y_predict) ** 2) return result @@ -86,8 +82,7 @@ def mape(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 0.0). """ - y_label, y_predict = np.array(y_label), np.array(y_predict) - return np.mean(np.abs((y_label - y_predict) / y_label)) + return np.mean(np.abs((y_label - y_predict) / (y_label + EPSILON))) def smape(y_label, y_predict): @@ -120,7 +115,6 @@ def r2(y_label, y_predict): :return: Ndarray of floats. An array of non-negative floating point values (the best value is 1.0). """ - y_label, y_predict = np.array(y_label), np.array(y_predict) return 1 - np.sum((y_label - y_predict)**2) / np.sum((y_label - np.mean(y_label))**2) @@ -193,7 +187,10 @@ def evaluate(metrics, y_true, y_pred, aggregate='mean'): res_list = [] for metric in metrics: - metric_func = REGRESSION_MAP[metric] + if callable(metric): + metric_func = metric + else: + metric_func = REGRESSION_MAP[metric] if len(original_shape) in [2, 3] and aggregate is None: res = np.zeros(y_true.shape[-1]) for i in range(y_true.shape[-1]): From 6e114b4691279e42a7d926a3e4a6211ccd944387 Mon Sep 17 00:00:00 2001 From: Xinyi Zhang Date: Thu, 25 Aug 2022 03:46:07 +0800 Subject: [PATCH 6/8] Modify files imported TORCHMETRICS_REGRESSION_MAP --- python/chronos/src/bigdl/chronos/autots/tspipeline.py | 4 ++-- .../src/bigdl/chronos/forecaster/autoformer_forecaster.py | 4 ++-- .../chronos/src/bigdl/chronos/forecaster/base_forecaster.py | 4 ++-- python/chronos/src/bigdl/chronos/forecaster/utils_hpo.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/autots/tspipeline.py b/python/chronos/src/bigdl/chronos/autots/tspipeline.py index f77ba398171..6407ee8242c 100644 --- a/python/chronos/src/bigdl/chronos/autots/tspipeline.py +++ b/python/chronos/src/bigdl/chronos/autots/tspipeline.py @@ -501,9 +501,9 @@ def quantize(self, calib_data = preprocess_quantize_data(self, calib_data) # map metric str to function - from bigdl.chronos.metric.forecast_metrics import TORCHMETRICS_REGRESSION_MAP + from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP if isinstance(metric, str): - metric = TORCHMETRICS_REGRESSION_MAP[metric] + metric = REGRESSION_MAP[metric] # init acc criterion accuracy_criterion = None diff --git a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py index 427c0741abb..a2834782455 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py @@ -438,6 +438,6 @@ def save(self, checkpoint_file): def _str2metric(metric): # map metric str to function if isinstance(metric, str): - from bigdl.chronos.metric.forecast_metrics import TORCHMETRICS_REGRESSION_MAP - metric = TORCHMETRICS_REGRESSION_MAP[metric] + from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP + metric = REGRESSION_MAP[metric] return metric diff --git a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py index 7ac87ecfbe3..7c8dafd58f4 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py @@ -1161,6 +1161,6 @@ def check_time_steps(tsdataset, past_seq_len, future_seq_len): def _str2metric(metric): # map metric str to function if isinstance(metric, str): - from bigdl.chronos.metric.forecast_metrics import TORCHMETRICS_REGRESSION_MAP - metric = TORCHMETRICS_REGRESSION_MAP[metric] + from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP + metric = REGRESSION_MAP[metric] return metric diff --git a/python/chronos/src/bigdl/chronos/forecaster/utils_hpo.py b/python/chronos/src/bigdl/chronos/forecaster/utils_hpo.py index b13c7c88582..b81ee101cea 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/utils_hpo.py +++ b/python/chronos/src/bigdl/chronos/forecaster/utils_hpo.py @@ -303,8 +303,8 @@ def _format_metric_str(prefix, metric): metrics.append(_format_metric_str(prefix, target_metric)) return metrics if isinstance(metric, str): - from bigdl.chronos.metric.forecast_metrics import TORCHMETRICS_REGRESSION_MAP - metric_func = TORCHMETRICS_REGRESSION_MAP.get(metric, None) + from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP + metric_func = REGRESSION_MAP.get(metric, None) invalidInputError(metric_func is not None, "{} is not found in available metrics.".format(metric)) return _format_metric(prefix, metric_func) From b28a6bcf09bc8ad6dfaced0a6724b0a261672540 Mon Sep 17 00:00:00 2001 From: theaperdeng Date: Thu, 1 Sep 2022 16:37:07 +0800 Subject: [PATCH 7/8] fix bug caused by numpy function --- python/chronos/src/bigdl/chronos/autots/tspipeline.py | 6 +++++- .../src/bigdl/chronos/forecaster/autoformer_forecaster.py | 8 +++++++- .../src/bigdl/chronos/forecaster/base_forecaster.py | 8 +++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/python/chronos/src/bigdl/chronos/autots/tspipeline.py b/python/chronos/src/bigdl/chronos/autots/tspipeline.py index 6407ee8242c..78ef5f7e52f 100644 --- a/python/chronos/src/bigdl/chronos/autots/tspipeline.py +++ b/python/chronos/src/bigdl/chronos/autots/tspipeline.py @@ -503,7 +503,11 @@ def quantize(self, # map metric str to function from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP if isinstance(metric, str): - metric = REGRESSION_MAP[metric] + metric_func = REGRESSION_MAP[metric] + def metric(y_label, y_predict): + y_label = y_label.numpy() + y_predict = y_predict.numpy() + return metric_func(y_label, y_predict) # init acc criterion accuracy_criterion = None diff --git a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py index a2834782455..c1d1a0b3254 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py @@ -438,6 +438,12 @@ def save(self, checkpoint_file): def _str2metric(metric): # map metric str to function if isinstance(metric, str): + metric_name = metric from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP - metric = REGRESSION_MAP[metric] + metric_func = REGRESSION_MAP[metric_name] + def metric(y_label, y_predict): + y_label = y_label.numpy() + y_predict = y_predict.numpy() + return metric_func(y_label, y_predict) + metric.__name__ = metric_name return metric diff --git a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py index 7c8dafd58f4..0daa893d674 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py @@ -1161,6 +1161,12 @@ def check_time_steps(tsdataset, past_seq_len, future_seq_len): def _str2metric(metric): # map metric str to function if isinstance(metric, str): + metric_name = metric from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP - metric = REGRESSION_MAP[metric] + metric_func = REGRESSION_MAP[metric_name] + def metric(y_label, y_predict): + y_label = y_label.numpy() + y_predict = y_predict.numpy() + return metric_func(y_label, y_predict) + metric.__name__ = metric_name return metric From 08da2161a3f342f65b36ad1de9ef342cd6fbe119 Mon Sep 17 00:00:00 2001 From: theaperdeng Date: Thu, 1 Sep 2022 16:42:38 +0800 Subject: [PATCH 8/8] fix pep8 --- python/chronos/src/bigdl/chronos/autots/tspipeline.py | 1 + .../src/bigdl/chronos/forecaster/autoformer_forecaster.py | 1 + python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py | 1 + 3 files changed, 3 insertions(+) diff --git a/python/chronos/src/bigdl/chronos/autots/tspipeline.py b/python/chronos/src/bigdl/chronos/autots/tspipeline.py index 78ef5f7e52f..528daccaf2b 100644 --- a/python/chronos/src/bigdl/chronos/autots/tspipeline.py +++ b/python/chronos/src/bigdl/chronos/autots/tspipeline.py @@ -504,6 +504,7 @@ def quantize(self, from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP if isinstance(metric, str): metric_func = REGRESSION_MAP[metric] + def metric(y_label, y_predict): y_label = y_label.numpy() y_predict = y_predict.numpy() diff --git a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py index c1d1a0b3254..cdc4fe25ba5 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/autoformer_forecaster.py @@ -441,6 +441,7 @@ def _str2metric(metric): metric_name = metric from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP metric_func = REGRESSION_MAP[metric_name] + def metric(y_label, y_predict): y_label = y_label.numpy() y_predict = y_predict.numpy() diff --git a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py index 0daa893d674..1c6d622c8b9 100644 --- a/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py +++ b/python/chronos/src/bigdl/chronos/forecaster/base_forecaster.py @@ -1164,6 +1164,7 @@ def _str2metric(metric): metric_name = metric from bigdl.chronos.metric.forecast_metrics import REGRESSION_MAP metric_func = REGRESSION_MAP[metric_name] + def metric(y_label, y_predict): y_label = y_label.numpy() y_predict = y_predict.numpy()