【问题标题】:Inherit Class of LabelBinarizer with "maximum recursion depth exceede" error继承具有“超出最大递归深度”错误的 LabelBinarizer 类
【发布时间】:2018-04-14 14:20:30
【问题描述】:

我从 LabelBinarizer 创建了一个自定义编码器类。这是它的样子

class my_lb(LabelBinarizer):

  def fit(self, X, y=None):
    self.fit(X)

  def transform(self, X, y=None):
    return self.transform(X)

  def fit_transform(self, X, y=None):
    return self.fit(X).transform(X)

而且我有“超出最大递归深度”错误,该错误发生在 fit 方法中。按照网上的一些说明,我能够做到这一点:

class my_lb(LabelBinarizer):

  def __init__(self):
    super().__init__()

  def fit(self, X, y=None):
    super().fit(X)

  def transform(self, X, y=None):
    return super().transform(X)

  def fit_transform(self, X, y=None):
    return super().fit(X).transform(X)

但我的问题是,它如何解决我的问题?我可以理解此处其他帖子中的原因(我可以看到正在构建一个显式的无限循环),但我阅读了 LabelBinarizer 的代码,它对我来说看起来很正常。我找不到任何可能导致无限循环的东西。

def fit(self, y): 
        self.y_type_ = type_of_target(y)
        if 'multioutput' in self.y_type_:
             raise ValueError("Multioutput target data is not supported with "
                              "label binarization")
        if _num_samples(y) == 0:
            raise ValueError('y has 0 samples: %r' % y)
        self.sparse_input_ = sp.issparse(y)
        self.classes_ = unique_labels(y)
        return self

谁能告诉我我在这里缺少什么?当我创建继承类时,它也将帮助我更好地了解何时需要 super。

【问题讨论】:

  • 如果你继承了一个类,并且你想使用它的方法之一不变,只是不要在你的类中重写它。删除你的方法版本,父类的版本会自动被调用。您调用 super 的版本似乎也不正确:您只是丢弃了 y 参数,而不是将其传递给父类的方法。
  • 第二个块旨在解决管道类中的一个常见问题,即编码器不能很好地与管道方法一起工作。这就是为什么你看到我的 call 方法除了调用相应的父函数之外什么都不做。这里的 y 参数只是一个占位符,与管道中的其他功能保持一致。

标签: python inheritance recursion scikit-learn pipeline


【解决方案1】:

在更改为调用super() 之前,调用显示的任何一种方法都会导致无限递归。 fittransform 很明显,它们只是调用自己,所以如果它们被调用,它们将永远不会返回,并且您将超过最大递归深度。

另一方面,fit_transform 正在调用self.fit(X).transform(X)。所以它做的第一件事就是调用self.fit(X),它只是一遍又一遍地调用自己,直到错误发生。

另一方面,修改后的版本通过对super()的调用将调用传递给fittransform的父类版本,因此它们不会调用自己。事实上,有了这些电话,您甚至不需要从fit_transform 拨打super()

但最好的解决方法是简单地删除派生类中fittransform 的定义,并从fit_transform 中删除对super() 的调用,这是不需要的。

【讨论】:

  • 啊,我明白了,从本质上讲,super 在我的示例中所做的是 self 将请求传递给父函数并收集分配给父对象的任何内容作为自己的。我这样想对吗?
  • 调用super() 是否总是实例化一个新的超类对象?
  • @fnosdy 是的,super() 只是让您直接访问父类的方法,绕过您的覆盖。
  • @VivekKumar super() 不实例化任何东西。它只是让您访问父类的方法。
  • 哦,好的。感谢您的澄清。 :)
猜你喜欢
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
  • 2018-12-03
  • 2017-07-18
  • 2021-12-11
  • 2019-07-03
  • 2020-09-30
  • 2017-08-24
相关资源
最近更新 更多