Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python scikit学习类实例上的Monkey补丁魔术方法_Python_Scikit Learn_Monkeypatching_Magic Methods - Fatal编程技术网

Python scikit学习类实例上的Monkey补丁魔术方法

Python scikit学习类实例上的Monkey补丁魔术方法,python,scikit-learn,monkeypatching,magic-methods,Python,Scikit Learn,Monkeypatching,Magic Methods,我试图构建一个名为SafeModel的工厂类,它的generate方法接受一个scikit学习类的实例,更改它的一些属性,并返回相同的实例。具体地说,对于本例,我想访问返回模型的coef\u属性,在案例1)中,如果基础scikit学习类包含coef\u,则返回该类“coef\u,在案例2中,如果基础scikit学习类包含功能重要性,返回该类“功能\u重要性” 我成功地修补了Python类实例的属性。我在修补Python类实例的神奇方法方面没有那么成功。我的案例需要注意的是:在scikit学习类实

我试图构建一个名为
SafeModel
的工厂类,它的
generate
方法接受一个scikit学习类的实例,更改它的一些属性,并返回相同的实例。具体地说,对于本例,我想访问返回模型的
coef\u
属性,在案例1)中,如果基础scikit学习类包含
coef\u
,则返回该类“
coef\u
,在案例2中,如果基础scikit学习类包含
功能重要性
,返回该类“
功能\u重要性”

我成功地修补了Python类实例的属性。我在修补Python类实例的神奇方法方面没有那么成功。我的案例需要注意的是:在scikit学习类实例化时,属性
coef\u
feature\u importances
从未定义过;相反,它们仅在对各自的类调用
fit
方法后定义。因此,我无法覆盖属性定义本身

from types import MethodType


class SafeModel:

    FALLBACK_ATTRIBUTES = {
        'coef_': ['feature_importances_'],
    }

    @classmethod
    def generate(cls, model):
        safe_model = cls._secure_attributes(model)
        return safe_model

    @classmethod
    def _secure_attributes(cls, model):
        def __secure_getattr__(self, name):
            for fallback_attribute in cls.FALLBACK_ATTRIBUTES[name]:
                try:
                    return getattr(self, fallback_attribute)
                except:
                    continue
        model.__getattr__ = MethodType(__secure_getattr__, model)
        return model


    from sklearn.ensemble import RandomForestClassifier

    model = SafeModel.generate(RandomForestClassifier())
    model.coef_  # AttributeError: 'RandomForestClassifier' object has no attribute 'coef_'

我无法确定你的代码有什么问题。不过,我发现了一种可能适用于您的用例的解决方法。
我使用了一种不同的策略,因为我只是使用了
SafeModel.\uuu getattr\uuuu
作为模型
getattr
方法的包装,而不是猴子补丁

from sklearn.utils.validation import NotFittedError
from sklearn.ensemble import RandomForestClassifier

class SafeModel(object):

    def __init__(self, model):
        self.FALLBACK_ATTRIBUTES = {
        'coef_': ['feature_importances_'],
    }
        self.model = model

    def __getattr__(self, name):
        try:
            return getattr(self.model, name)
        except AttributeError:
            pass
        for fallback_attribute in self.FALLBACK_ATTRIBUTES[name]:
            try:
                return getattr(self.model, fallback_attribute)
            except NotFittedError as e:
                # NotFittedError inherits AttributeError.
                raise e
            except AttributeError:
                continue
        else:
            raise AttributeError(
                "{} object has no attribute {}.".format(
                    self.__class__.__name__, name) + 
                " Could not retrieve any fallback attribute.")                    


model = SafeModel(RandomForestClassifier())
model.coef_   
输出:

NotFittedError: Estimator not fitted, call `fit` before `feature_importances_`.
请注意,这是正常的行为,正如您所提到的,在适应随机林之前,您无法访问
功能\u重要性

诚然,异常捕获在这里相当脆弱(您需要添加一组可能引发的异常),但是如果您在尝试访问属性时不关心引发适当的异常,那么应该可以


如果对你有效,请告诉我。如果你知道你发布的代码是怎么回事,我也会对解释感兴趣

不幸的是,我希望使用
SafeModel
作为工厂,比如
model=SafeModel.generate(RandomForestClassifier())
,它返回sk learn对象的修改实例。上面,我们只剩下一个
SafeModel
的实例。难道你就不能将它用作装饰器吗?然后,您的模型不是
SafeModel
实例,而是用
\uu getattr\uuu
@cavaunpeu Ok修饰的。仅供参考,我试图将打印语句放在“secure_getattr”中,但它们从未显示。我甚至无法在getattr上应用一个简单的装饰程序。查伦索伊斯:如果你能做到这一点,我很想看到一个解决方案。@user3914041我尝试了同样的方法,但没有效果。我认为Python调用magic方法的方式与调用非magic方法的方式根本不同(通过访问相关实例的dict属性)。@cavaunpeu也许,我能够使用您的代码覆盖fit。但无法让神奇的方法发挥作用。