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 管道中传递分桶器?