Pyspark MLlib 中的自定义算法:“函数”对象没有属性“_input_kwargs”

Posted

技术标签:

【中文标题】Pyspark MLlib 中的自定义算法:“函数”对象没有属性“_input_kwargs”【英文标题】:Custom algorithm in Pyspark MLlib: 'function' object has no attribute '_input_kwargs' 【发布时间】:2017-07-19 11:27:54 【问题描述】:

我正在尝试在 Pyspark 中推出我自己的 MLlib 管道算法,但我无法克服以下错误:

'function' object has no attribute '_input_kwargs'

我已将我的代码简化为:

from pyspark import keyword_only
from pyspark.ml.param import Params

class SimpleAlgorithm(Params):

    @keyword_only
    def __init__(self, threshold=2.0):

        super(SimpleAlgorithm, self).__init__()
        kwargs = self.__init__._input_kwargs
        self.setParams(**kwargs)

    @keyword_only
    def setParams(self, threshold=2.0):

        kwargs = self.setParams._input_kwargs
        return self._set(**kwargs)

但是当我这样做时:

test_alg = SimpleAlgorithm()

我收到上面显示的错误。请问有谁知道我做错了什么? (我看到了一个明显相关的问题here,但作为一个 Python 新手,我不确定我是否理解答案或它是否与我相关。)

编辑如果有帮助的话,这里是在 Spark 2.1 Databricks 集群上运行错误后的完整堆栈跟踪:

----> 1 test_alg = SimpleAlgorithm()

/databricks/spark/python/pyspark/__init__.py in wrapper(self, *args, **kwargs)
     99             raise TypeError("Method %s forces keyword arguments." % func.__name__)
    100         self._input_kwargs = kwargs
--> 101         return func(self, **kwargs)
    102     return wrapper
    103 

<ipython-input-12-dcb888c97487> in __init__(self, threshold)
      8 
      9         #super(SimpleAlgorithm, self).__init__()
---> 10         kwargs = self.__init__._input_kwargs
     11         self.setParams(**kwargs)
     12 

AttributeError: 'function' object has no attribute '_input_kwargs'

【问题讨论】:

【参考方案1】:

问题出在这一行:

kwargs = self.__init__._input_kwargs

您正在尝试访问不存在的 function 对象 self.__init__ 上的属性 _input_kwargs

如果您只是想设置threshold 属性,我通常会这样做:

class SimpleAlgorithm(Params):

    @keyword_only
    def __init__(self, threshold=2.0):
        super(SimpleAlgorithm, self).__init__()
        self.threshold = threshold

编辑:

我检查了您链接的源代码,并注意到 keyword_only 包装器的实现从 Spark 2.1 更改为 Spark 2.2。您的代码确实应该适用于 Spark 2.1,但如果您使用的是 Spark 2.2,则应将其替换为:

from pyspark import keyword_only
from pyspark.ml.param import Params

class SimpleAlgorithm(Params):

    @keyword_only
    def __init__(self, threshold=2.0):

        super(SimpleAlgorithm, self).__init__()
        kwargs = self._input_kwargs
        self.setParams(**kwargs)

    @keyword_only
    def setParams(self, threshold=2.0):

        kwargs = self._input_kwargs
        return self._set(**kwargs)

Link to v2.2 keyword_only implementation

Link to v2.2 example usage

【讨论】:

谢谢。我最终可能会按照您的建议进行操作,但我希望具有 MLlib 代码特定知识的人会做出回应。因为应该是 @keyword_only 装饰器创建 _input_args;见github.com/apache/spark/blob/v2.1.0/python/pyspark/…。另外,我正在尝试遵循其他 PySpark 算法使用的模式(例如here),所以我不明白为什么我的代码(此处简化)不起作用,而他们的代码却起作用。 @snark 啊,我明白了。我已经用解释更新了我的答案。 谢谢@timchap!好地方!看起来代码更改是在 SPARK-19438 中的 Spark 2.1.0 和 2.1.1 之间进行的。 Databricks 集群使用 2.1.1,因此您的代码更改工作。奇怪的是,它们似乎也可以在我正在使用的另一个集群上工作,该集群正在运行 Spark 2.1.0。不知道为什么,但我会同意的。感谢您的帮助! 以下是有关 keyword_only 在 2.1.0 和 2.1.1 之间更改的更多信息:github.com/apache/spark/commit/…【参考方案2】:

我想为@timchap 回答做出贡献。如果您正在使用 Zeppelin 0.7.3 使用 Spark 2.1.0 但您的代码在 spark 2.2.0 上运行,您可以检查版本并以这种方式获取兼容版本

from pyspark import keyword_only
from pyspark.ml.param import Params

class SimpleAlgorithm(Params):

    @keyword_only
    def __init__(self, threshold=2.0):

        super(SimpleAlgorithm, self).__init__()
        if spark.version.startswith('2.1'):
            kwargs = self.__init__._input_kwargs
        else:
            kwargs = self._input_kwargs
        self.setParams(**kwargs)

    @keyword_only
    def setParams(self, threshold=2.0):

        if spark.version.startswith('2.1'):
            kwargs = self.__init__._input_kwargs
        else:
            kwargs = self._input_kwargs
        return self._set(**kwargs)

【讨论】:

以上是关于Pyspark MLlib 中的自定义算法:“函数”对象没有属性“_input_kwargs”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PySpark 中的自定义函数在同一 ML 管道中传递分桶器?

pyspark 数据框上的自定义函数

PySpark 和 MLLib:随机森林预测的类概率

pyspark_mllib_classifier—(SVM)

PySpark 和 MLLib:随机森林特征的重要性

在 PySpark mllib 中使用随机森林的非法参数异常