【问题标题】:ImportError when importing metric from sklearn从 sklearn 导入指标时出现 ImportError
【发布时间】:2022-02-22 03:58:28
【问题描述】:

当我尝试从 sklearn 导入指标时,我收到以下错误:

from sklearn.metrics import mean_absolute_percentage_error

ImportError: cannot import name 'mean_absolute_percentage_error' from 'sklearn.metrics'

/Users/carter/opt/anaconda3/lib/python3.8/site-packages/sklearn/metrics/__init__.py)

我已经使用 conda update all,并重新安装了 scikit-learn 无济于事。还有其他可能发生这种情况的原因和解决方案吗?

【问题讨论】:

    标签: python scikit-learn


    【解决方案1】:

    函数 mean_absolute_percentage_error 是 scikit-learn 0.24 版中的新功能,如文档中所述。

    截至 2020 年 12 月,Anaconda 提供的 scikit-learn 的最新版本是 v0.23.2,这就是您无法导入 mean_absolute_percentage_error 的原因。

    您可以尝试安装最新版本的from source,或者自己实现您需要的功能。如果您想看一下,可以使用here 获取源代码。

    【讨论】:

    • 现在 (2021/7/26),“mean_absolute_percentage_error”在 Google Collaboratory 中不可用。 skear 版本是 0.22.2.post1
    【解决方案2】:

    上面的答案是正确的。对于那些无法从源代码升级/安装的人,下面是所需的代码。

    函数本身依赖于其他函数 - 一个在同一模块中定义,另一个来自 sklearn.utils.validation。

    这是我从源代码中提取的所需代码 - 如果有人需要它(我希望我没有违反任何许可):

    from sklearn.utils.validation import check_consistent_length, check_array
    
    def mean_absolute_percentage_error(y_true, y_pred,
                                       sample_weight=None,
                                       multioutput='uniform_average'):
        """Mean absolute percentage error regression loss.
        Note here that we do not represent the output as a percentage in range
        [0, 100]. Instead, we represent it in range [0, 1/eps]. Read more in the
        :ref:`User Guide <mean_absolute_percentage_error>`.
        .. versionadded:: 0.24
        Parameters
        ----------
        y_true : array-like of shape (n_samples,) or (n_samples, n_outputs)
            Ground truth (correct) target values.
        y_pred : array-like of shape (n_samples,) or (n_samples, n_outputs)
            Estimated target values.
        sample_weight : array-like of shape (n_samples,), default=None
            Sample weights.
        multioutput : {'raw_values', 'uniform_average'} or array-like
            Defines aggregating of multiple output values.
            Array-like value defines weights used to average errors.
            If input is list then the shape must be (n_outputs,).
            'raw_values' :
                Returns a full set of errors in case of multioutput input.
            'uniform_average' :
                Errors of all outputs are averaged with uniform weight.
        Returns
        -------
        loss : float or ndarray of floats in the range [0, 1/eps]
            If multioutput is 'raw_values', then mean absolute percentage error
            is returned for each output separately.
            If multioutput is 'uniform_average' or an ndarray of weights, then the
            weighted average of all output errors is returned.
            MAPE output is non-negative floating point. The best value is 0.0.
            But note the fact that bad predictions can lead to arbitarily large
            MAPE values, especially if some y_true values are very close to zero.
            Note that we return a large value instead of `inf` when y_true is zero.
        Examples
        --------
        >>> from sklearn.metrics import mean_absolute_percentage_error
        >>> y_true = [3, -0.5, 2, 7]
        >>> y_pred = [2.5, 0.0, 2, 8]
        >>> mean_absolute_percentage_error(y_true, y_pred)
        0.3273...
        >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
        >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
        >>> mean_absolute_percentage_error(y_true, y_pred)
        0.5515...
        >>> mean_absolute_percentage_error(y_true, y_pred, multioutput=[0.3, 0.7])
        0.6198...
        """
        y_type, y_true, y_pred, multioutput = _check_reg_targets(
            y_true, y_pred, multioutput)
        check_consistent_length(y_true, y_pred, sample_weight)
        epsilon = np.finfo(np.float64).eps
        mape = np.abs(y_pred - y_true) / np.maximum(np.abs(y_true), epsilon)
        output_errors = np.average(mape,
                                   weights=sample_weight, axis=0)
        if isinstance(multioutput, str):
            if multioutput == 'raw_values':
                return output_errors
            elif multioutput == 'uniform_average':
                # pass None as weights to np.average: uniform mean
                multioutput = None
    
        return np.average(output_errors, weights=multioutput)
    
    def _check_reg_targets(y_true, y_pred, multioutput, dtype="numeric"):
        """Check that y_true and y_pred belong to the same regression task.
        Parameters
        ----------
        y_true : array-like
        y_pred : array-like
        multioutput : array-like or string in ['raw_values', uniform_average',
            'variance_weighted'] or None
            None is accepted due to backward compatibility of r2_score().
        Returns
        -------
        type_true : one of {'continuous', continuous-multioutput'}
            The type of the true target data, as output by
            'utils.multiclass.type_of_target'.
        y_true : array-like of shape (n_samples, n_outputs)
            Ground truth (correct) target values.
        y_pred : array-like of shape (n_samples, n_outputs)
            Estimated target values.
        multioutput : array-like of shape (n_outputs) or string in ['raw_values',
            uniform_average', 'variance_weighted'] or None
            Custom output weights if ``multioutput`` is array-like or
            just the corresponding argument if ``multioutput`` is a
            correct keyword.
        dtype : str or list, default="numeric"
            the dtype argument passed to check_array.
        """
        check_consistent_length(y_true, y_pred)
        y_true = check_array(y_true, ensure_2d=False, dtype=dtype)
        y_pred = check_array(y_pred, ensure_2d=False, dtype=dtype)
    
        if y_true.ndim == 1:
            y_true = y_true.reshape((-1, 1))
    
        if y_pred.ndim == 1:
            y_pred = y_pred.reshape((-1, 1))
    
        if y_true.shape[1] != y_pred.shape[1]:
            raise ValueError("y_true and y_pred have different number of output "
                             "({0}!={1})".format(y_true.shape[1], y_pred.shape[1]))
    
        n_outputs = y_true.shape[1]
        allowed_multioutput_str = ('raw_values', 'uniform_average',
                                   'variance_weighted')
        if isinstance(multioutput, str):
            if multioutput not in allowed_multioutput_str:
                raise ValueError("Allowed 'multioutput' string values are {}. "
                                 "You provided multioutput={!r}".format(
                                     allowed_multioutput_str,
                                     multioutput))
        elif multioutput is not None:
            multioutput = check_array(multioutput, ensure_2d=False)
            if n_outputs == 1:
                raise ValueError("Custom weights are useful only in "
                                 "multi-output cases.")
            elif n_outputs != len(multioutput):
                raise ValueError(("There must be equally many custom weights "
                                  "(%d) as outputs (%d).") %
                                 (len(multioutput), n_outputs))
        y_type = 'continuous' if n_outputs == 1 else 'continuous-multioutput'
    
        return y_type, y_true, y_pred, multioutput
    

    【讨论】:

      【解决方案3】:

      您可以选择以下两种解决方案之一:

      1. 升级您的 sklearn 版本
      !pip install scikit-learn==0.24
      

      那么,

      from sklearn.metrics import mean_absolute_percentage_error
      
      1. 构建您自己的函数来计算 MAPE
      def MAPE(y_true, y_pred): 
          y_true, y_pred = np.array(y_true), np.array(y_pred)
          return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
      

      但上述函数的问题在于,当您拥有 (0) 真值时,您的 MAPE 将变为 (inf)。所以,为了解决这个问题,我们使用,

      def MAPE(y_true, y_pred): 
        y_true, y_pred = np.array(y_true), np.array(y_pred)
        return np.mean(np.abs((y_true - y_pred) / np.maximum(np.ones(len(y_true)), np.abs(y_true))))*100
      

      【讨论】:

        【解决方案4】:

        刚刚遇到同样的问题。访问 Anaconda Prompt 以获取正在处理和运行的环境

        pip install scikit-learn
        

        解决了问题。

        它更新了 scikit-learn 的版本(此时它已升级到版本 1.0.2,但它存在于从 0.24 开始的版本中。),现在可以导入和运行 sklearn.metrics.mean_absolute_percentage_error

        这是一个示例 (Source):

        >>> from sklearn.metrics import mean_absolute_percentage_error
        >>> y_true = [3, -0.5, 2, 7]
        >>> y_pred = [2.5, 0.0, 2, 8]
        >>> mean_absolute_percentage_error(y_true, y_pred)
        0.3273...
        

        注意:您可能需要记住,MAPE 可能会出现问题,因为它可能会导致除以零 (see my answer here)。

        【讨论】:

          猜你喜欢
          • 2013-02-22
          • 1970-01-01
          • 2020-07-04
          • 1970-01-01
          • 2020-05-18
          • 1970-01-01
          • 2016-01-16
          相关资源
          最近更新 更多