@@ -16,7 +16,7 @@ def _check_sample_weight(sample_weight: Optional[ArrayLike]):
1616def _check_reg_targets (
1717 y_true : ArrayLike , y_pred : ArrayLike , multioutput : Optional [str ]
1818):
19- if multioutput != "uniform_average" :
19+ if multioutput is not None and multioutput != "uniform_average" :
2020 raise NotImplementedError ("'multioutput' must be 'uniform_average'" )
2121
2222 if y_true .ndim == 1 :
@@ -40,12 +40,12 @@ def mean_squared_error(
4040 _check_sample_weight (sample_weight )
4141 output_errors = ((y_pred - y_true ) ** 2 ).mean (axis = 0 )
4242
43- if isinstance (multioutput , str ):
43+ if isinstance (multioutput , str ) or multioutput is None :
4444 if multioutput == "raw_values" :
45- return output_errors
46- elif multioutput == "uniform_average" :
47- # pass None as weights to np.average: uniform mean
48- multioutput = None
45+ if compute :
46+ return output_errors . compute ()
47+ else :
48+ return output_errors
4949 else :
5050 raise ValueError ("Weighted 'multioutput' not supported." )
5151 result = output_errors .mean ()
@@ -67,12 +67,75 @@ def mean_absolute_error(
6767 _check_sample_weight (sample_weight )
6868 output_errors = abs (y_pred - y_true ).mean (axis = 0 )
6969
70- if isinstance (multioutput , str ):
70+ if isinstance (multioutput , str ) or multioutput is None :
7171 if multioutput == "raw_values" :
72- return output_errors
73- elif multioutput == "uniform_average" :
74- # pass None as weights to np.average: uniform mean
75- multioutput = None
72+ if compute :
73+ return output_errors .compute ()
74+ else :
75+ return output_errors
76+ else :
77+ raise ValueError ("Weighted 'multioutput' not supported." )
78+ result = output_errors .mean ()
79+ if compute :
80+ result = result .compute ()
81+ return result
82+
83+
84+ def mean_absolute_percentage_error (
85+ y_true : ArrayLike ,
86+ y_pred : ArrayLike ,
87+ sample_weight : Optional [ArrayLike ] = None ,
88+ multioutput : Optional [str ] = "uniform_average" ,
89+ compute : bool = True ,
90+ ) -> ArrayLike :
91+ """Mean absolute percentage error regression loss.
92+
93+ Note here that we do not represent the output as a percentage in range
94+ [0, 100]. Instead, we represent it in range [0, 1/eps]. Read more in
95+ https://scikit-learn.org/stable/modules/model_evaluation.html#mean-absolute-percentage-error
96+
97+ Parameters
98+ ----------
99+ y_true : array-like of shape (n_samples,) or (n_samples, n_outputs)
100+ Ground truth (correct) target values.
101+ y_pred : array-like of shape (n_samples,) or (n_samples, n_outputs)
102+ Estimated target values.
103+ sample_weight : array-like of shape (n_samples,), default=None
104+ Sample weights.
105+ multioutput : {'raw_values', 'uniform_average'} or array-like
106+ Defines aggregating of multiple output values.
107+ Array-like value defines weights used to average errors.
108+ If input is list then the shape must be (n_outputs,).
109+ 'raw_values' :
110+ Returns a full set of errors in case of multioutput input.
111+ 'uniform_average' :
112+ Errors of all outputs are averaged with uniform weight.
113+ compute : bool
114+ Whether to compute this result (default ``True``)
115+
116+ Returns
117+ -------
118+ loss : float or array-like of floats in the range [0, 1/eps]
119+ If multioutput is 'raw_values', then mean absolute percentage error
120+ is returned for each output separately.
121+ If multioutput is 'uniform_average' or ``None``, then the
122+ equally-weighted average of all output errors is returned.
123+ MAPE output is non-negative floating point. The best value is 0.0.
124+ But note the fact that bad predictions can lead to arbitarily large
125+ MAPE values, especially if some y_true values are very close to zero.
126+ Note that we return a large value instead of `inf` when y_true is zero.
127+ """
128+ _check_sample_weight (sample_weight )
129+ epsilon = np .finfo (np .float64 ).eps
130+ mape = abs (y_pred - y_true ) / da .maximum (y_true , epsilon )
131+ output_errors = mape .mean (axis = 0 )
132+
133+ if isinstance (multioutput , str ) or multioutput is None :
134+ if multioutput == "raw_values" :
135+ if compute :
136+ return output_errors .compute ()
137+ else :
138+ return output_errors
76139 else :
77140 raise ValueError ("Weighted 'multioutput' not supported." )
78141 result = output_errors .mean ()
@@ -90,7 +153,7 @@ def r2_score(
90153 compute : bool = True ,
91154) -> ArrayLike :
92155 _check_sample_weight (sample_weight )
93- _ , y_true , y_pred , multioutput = _check_reg_targets (y_true , y_pred , multioutput )
156+ _ , y_true , y_pred , _ = _check_reg_targets (y_true , y_pred , multioutput )
94157 weight = 1.0
95158
96159 numerator = (weight * (y_true - y_pred ) ** 2 ).sum (axis = 0 , dtype = "f8" )
0 commit comments