首页 > 解决方案 > 继承过程中如何避免init中的代码重复?扩展 xgb.XGBClassifier 以处理特征名称

问题描述

我对扩展类有具体的问题xgb.XGBClassifier,但它可以被视为一般的 OOP 问题。

我的实现基于:https ://github.com/dmlc/xgboost/blob/master/python-package/xgboost/sklearn.py

基本上,当提供的数据在 pandas DataFrame 中时,我想添加功能名称处理。

几点说明:

有用。

困扰我的是,__init__. 它是通过复制粘贴默认值完成的,每次xgb.Classifier更改时都必须更新。

有什么方法可以简洁地表达子类XGBClassifierN具有与父类相同的参数和默认值xgb.XGBClassifier并执行后续操作的想法clf = XGBClassifierN(n_jobs=-1)

我尝试只使用**kwargs但没有成功(解释器开始抱怨没有missing参数(没有双关语意图),并且要使其工作基本上你需要设置更多参数)。

import xgboost as xgb

class XGBClassifierN(xgb.XGBClassifier):
    def __init__(self, base_score=0.5, booster='gbtree', colsample_bylevel=1,
              colsample_bynode=1, colsample_bytree=1, gamma=0,
              learning_rate=0.1, max_delta_step=0, max_depth=3,
              min_child_weight=1, missing=None, n_estimators=100, n_jobs=1,
              nthread=None, objective='binary:logistic', random_state=0,
              reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
              silent=None, subsample=1, verbosity=1, **kwargs): 
        super().__init__(base_score=base_score, booster=booster, colsample_bylevel=colsample_bylevel,
              colsample_bynode=colsample_bynode, colsample_bytree=colsample_bytree, gamma=gamma,
              learning_rate=learning_rate, max_delta_step=max_delta_step, max_depth=max_depth,
              min_child_weight=min_child_weight, missing=missing, n_estimators=n_estimators, n_jobs=n_jobs,
              nthread=nthread, objective=objective, random_state=random_state,
              reg_alpha=reg_alpha, reg_lambda=reg_lambda, scale_pos_weight=scale_pos_weight, seed=seed,
              silent=silent, subsample=subsample, verbosity=verbosity, **kwargs)
        self.feature_names = None

    def fit(self, X, y=None):
        self.feature_names = list(X.columns)
        return super().fit(X, y)

    def get_feature_names(self):
        if not isinstance(self.feature_names, list):
            raise ValueError('Must fit data first!')
        else:
            return self.feature_names

    def get_feature_importances(self):
        return dict(zip(self.get_feature_names(), self.feature_importances_))

标签: pythonoopinheritance

解决方案


我尝试只使用 **kwargs ,但没有成功。

“不起作用”是对问题的最无用的描述。相反,您应该准确记录所有相关细节会发生什么。

话虽这么说,如果您的问题是“我如何避免重新输入完​​整的父方法签名等”,那么您实际上非常接近**kwargs,只是缺少位置 args 部分*args

def __init__(self, *args, **kwargs): 
    super().__init__(*args, **kwargs)
    self.feature_names = None

请注意,这会使签名对检查无用(pydoc、内置help()函数、IDE 自动完成等)。

编辑:实际上,可能有一种方法 - 至少,根据这个答案,可以functools.wraps()保留装饰函数的签名。还有提供相同服务的Michele Simionato 的“装饰器”库,因此您应该能够重用此代码来获得您的蛋糕并吃掉它!-)


推荐阅读