Python子类从任意父类继承和重写

2024-07-04 17:00:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用sklearn估计器,它继承自sklearn.base.BaseEstimator,具有相当标准的接口。我想做的一个例子是重写.fit()和.predict()方法,以根据日志转换的目标进行回归,如下所示:

Estimator = sklearn.some_regression_estimator

class LogFit(Estimator):
    """subclass the sklearn regression estimator to fit and predict using 
       log-transformed target variable
    """

    def __init__(self, **kwargs):
        super().__init__(kwargs)

    def fit(X, y=None, **kwargs):
        super().fit(X, np.log(y), **kwargs)
        return self

    def predict(X):
       return np.exp(super().predict(X))

我不一定事先知道将使用哪个估计器,只知道它将根据sklearn估计器惯例进行操作。我也不想为每个可能的估计器重新编写上面的子类,而且多重继承似乎是不正确的,因为LogFit的每个实例只从一个单亲继承

我发现我可以编写一个包装类(然后使用过度使用的fit()和predict()方法将其子类it),例如:

class EstimatorWrapper():
    """Wrapper class that has an estimator as a property"""

    def __init__(self, estimator_instance):
        self.estimator = estimator_instance
    
    def fit(self, X, y=None, **kwargs):
        self.fit(X, y, **kwargs)
        return self
   ...

但在这一点上,我现在必须承担起确保EstimatorWrapper类的行为与基本estimator类一样的责任,这样我就可以使用fit()和predict()的LogFit版本,而不用让sklearn的其他机器知道它们之间的区别。在这里,如果我不知道在每个可能的estimator_实例中存在哪些特定的方法/属性,那么我似乎必须设法让estimator Wrapper()动态定义其属性,而我真正想做的就是调整fit()和predict()函数的行为

我是否缺少一种简单的方法来编写一个直到实例化才知道其父类的子类,或者根本不允许这样做?我找不到任何关于如何做前者的例子


Tags: 实例方法selfreturninitdefsklearnpredict
1条回答
网友
1楼 · 发布于 2024-07-04 17:00:44

它绕过了这个问题,但是这里有第三个选项可能是很好的探索:^{},它包装了一个回归器,允许您定义正向反向变换函数以应用于目标变量

下面是一个使用np.log1p和反向np.expm1的示例:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.compose import TransformedTargetRegressor

X = np.array([-0.890,-0.798,-0.610,-0.502,-0.450,-0.382,-0.342,-0.282,-0.226,-0.158,-0.0500,0.106,0.202,0.322,0.418,0.482,0.530,0.590,0.666,0.754,0.834,0.914,0.970,-0.694,-0.762,-0.782,-0.854,-0.850,-0.658,-0.666,-0.482,-0.506,-0.398,-0.478,-0.350,-0.410,-0.334,-0.378,-0.314,-0.346,-0.230,-0.250,-0.150,-0.146,-0.0500,-0.0700,0.0180,0.0300,0.110,0.178,0.214,0.290,0.318,0.406,0.422,0.482,0.478,0.486,0.546,0.566,0.674,0.658,0.702,0.726,0.838,0.882,0.950,0.934,0.882,0.786,0.786,0.718,0.682,0.570,0.502,0.426,0.234,-0.470,-0.430,-0.390,-0.354]).reshape(-1, 1)
y = np.array([0.663,0.679,0.675,0.627,0.535,0.331,0.171,0.0111,-0.169,-0.273,-0.421,-0.497,-0.505,-0.457,-0.361,-0.237,-0.141,-0.0129,0.0751,0.127,0.143,0.147,0.143,0.691,0.723,0.671,0.707,0.611,0.727,0.595,0.683,0.567,0.571,0.375,0.391,0.255,0.255,0.0831,0.0991,-0.0689,-0.0729,-0.225,-0.217,-0.309,-0.293,-0.453,-0.417,-0.533,-0.433,-0.577,-0.393,-0.489,-0.341,-0.421,-0.313,-0.353,-0.109,-0.117,-0.169,-0.0369,-0.141,0.159,0.0991,0.139,0.155,0.0511,0.231,0.123,0.187,0.00707,0.139,-0.0249,-0.00893,-0.205,-0.121,-0.261,-0.417,0.527,0.491,0.391,0.0591]).ravel()
plt.scatter(X, y)
X_train, X_test, y_train, y_test = train_test_split(X, y)


for regressor in [DecisionTreeRegressor(max_depth=3), MLPRegressor(max_iter=500), SVR()]:

    regr = TransformedTargetRegressor(
        regressor=regressor,
        func=np.log1p,
        inverse_func=np.expm1,
    )
    regr.fit(X_train, y_train)
    score = round(regr.score(X_test, y_test), 3)

    # Some visualization
    data = np.linspace(X.min(), X.max(), num=250).reshape(-1, 1)
    reg_line = regr.predict(data)
    plt.plot(data, reg_line, label=f"R2={score}, {regr.regressor.__class__.__name__}")

plt.legend()
plt.show()

结果:

Plot showing regressors fit to 2D data using TransformedTargetRegressor

相关问题 更多 >

    热门问题