3 python runtime-error subclass cython scikit-learn
我想扩展 scikit-learn 的ClassificationCriterion类,它被定义为内部模块中的 Cython 类sklearn.tree._criterion。我想在 Python 中做到这一点,因为通常我无法访问 sklearn 的 pyx/pxd 文件(所以我不能访问cimport它们)。但是,当我尝试扩展时ClassificationCriterion,出现错误TypeError: __cinit__() takes exactly 2 positional arguments (0 given)。下面的 MWE 重现了错误,并显示错误发生__new__在__init__.
有没有办法像这样扩展 Cython 类?
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree._criterion import ClassificationCriterion
class MaxChildPrecision(ClassificationCriterion):
def __new__(self, *args, **kwargs):
print('new')
super().__new__(MaxChildPrecision, *args, **kwargs)
def __init__(self, *args, **kwargs):
print('init')
super(MaxChildPrecision).__init__(*args, **kwargs)
clf = DecisionTreeClassifier(criterion=MaxChildPrecision())
Run Code Online (Sandbox Code Playgroud)
有两个问题。首先,ClassificationCriterion它的构造函数需要两个特定的参数,你没有传递它。您必须弄清楚这些参数代表什么并将它们传递给基类。
其次,有一个 Cython 问题。如果我们查看如何使用的描述,__cinit__那么我们会看到:
传递给构造函数的任何参数都将传递给
__cinit__()方法和__init__()方法。如果您期望在 Python 中对您的扩展类型进行子类化,您可能会发现提供__cinit__()方法*和**参数很有用,以便它可以接受和忽略额外的参数。否则,任何具有不同签名的init () 的Python 子类都必须覆盖__new__()以及__init__()
不幸的是,sklearn 的作者没有提供*和**参数,所以你必须覆盖__new__. 这样的事情应该工作:
class MaxChildPrecision(ClassificationCriterion):
def __init__(self,*args, **kwargs):
pass
def __new__(cls,*args,**kwargs):
# I have NO IDEA if these arguments make sense!
return super().__new__(cls,n_outputs=5,
n_classes=np.ones((2,),dtype=np.int))
Run Code Online (Sandbox Code Playgroud)
我将必要的参数传递给ClassificationCriterionin__new__并__init__按照我认为合适的方式处理其余的参数。我不需要调用基类__init__(因为基类没有定义__init__)。
| 归档时间: |
|
| 查看次数: |
3220 次 |
| 最近记录: |