检查sklearn.base
,更具体地说是BaseEstimator
,以及不同的mixin,很明显,一些mixin依赖于调用.fit
或.predict
的能力。
例如,如果我们查看RegressorMixin
就会发现它依赖于.predict
方法。
我的问题是为什么没有实现这些方法的接口/抽象类?
我希望有类似BaseRegressor
的东西,它.predict()
为抽象方法,BaseClassifier
具有.predict_proba()
和.predict()
- 或类似的东西
有几件事可以更清楚地说明为什么在像scikit-learn
这样的包中完成事情,就像它们一样:
鸭子打字与继承:你可以找到很长的争论,关于哪一个是更好的方法,虽然它们都有其优点和缺点,但归根结底,这取决于社区中的人们习惯了什么。作为一个现在做了很多Python的人,我喜欢鸭子打字,而且我很舒服。同时,15年前,我喜欢抽象类和OOP之类的,我不明白为什么你会以其他方式做事。我想说的是,Python中的人喜欢鸭子类型,这就是为什么你经常在它的一些核心包中看到这种模式的部分原因。
鸭子类型,贡献包和扩展:有时检查输入,我们可以检查其类型,或者鸭子类型以具有某些功能。如果我们检查类型,这意味着该方法的任何输入实际上都应该继承自这些类,而如果你躲避它们,它们可以简单地实现这些方法,它们很好。这很重要,因为如果开发人员在
scikit-learn
之外编写一个估计器,例如,他们希望与scikit-learn
的某些部分兼容,他们不必依赖scikit-learn
作为依赖项(因为这就是他们从包中继承某个类的方式),并简单地实现这些方法。如果开发人员有约束来保持他们的包和他们的依赖项是轻量级的,这变得相关(我们已经在scikit-learn
看到了这些确切的问题)。Mixin
类:Mixin
类背后的思想并不是子类应该继承它们并实现它们的方法;而是更多的是通过它们向现有类添加功能,而无需复制/粘贴或重新实现任何方法。例如,TransformerMixin
将fit_transform
方法添加到对象中,假设它已经具有fit
和transform
,而不关心天气,对象是估计器或转换器。同样,你可以争辩说OOP的某种设计模式在这里可能更好,但这是一个永无止境的争论,这种方法有效,开发人员对此感到满意。
python 中常见的成语是"鸭子打字"——如果它的行为像鸭子,那就是鸭子,如果它实现了fit
或任何其他相关功能,它就是 sklearn 的模型
还有抽象基类的概念,但它的用法不太常见
在此处查看更多内容: https://en.wikipedia.org/wiki/Duck_typing