0

问题

我有不同的数据分布,我想参数化。每个分布都定义为自己的类;这样,每个分布都可以共享属性名称(例如pdf概率分布或f其他)。例如,考虑两个数据集——一个遵循直线模型,而另一个遵循正态分布。我想要一个“主”类(因为没有更好的词),它可以继承所选分布的属性。我知道我可以super().__init__()在构造函数中使用从父类继承,但我不知道如何从所有父类继承。我宁愿没有代表不同分布的类相互继承。出于这个原因,我认为我可以使用setattr为此目的,但我收到以下错误:

line 54, in initialize_model
    setattr(self, attribute, getattr(model, attribute))
AttributeError: attribute '__weakref__' of 'NormalDistribution' objects is not writable

问题

什么是弱引用,为什么不可写?我的方法可以适应工作,还是有更好的方法?

我的尝试

## imports
import numpy as np
import matplotlib.pyplot as plt

## first distribution
class NormalDistribution():

    def __init__(self):
        self.nparams = 2

    @staticmethod
    def pdf(prms, x):
        return np.exp(- np.square((x - prms[0])/prms[1]) / 2) / (prms[1] * np.sqrt(2 * np.pi))

    @staticmethod
    def get_parameter_guess(x, **kwargs):
        mu, sigma = np.mean(x), np.std(x, **kwargs)
        return (mu, sigma)

## second distribution
class LinearEquation():

    def __init__(self):
        self.nparams = 2

    @staticmethod
    def f(prms, x):
        return prms[0] * x + prms[1]

    @staticmethod
    def get_parameter_guess(x, y):
        dy = y[-1] - y[0]
        dx = x[-1] - x[0]
        m = dy / dx
        b = np.mean([y[idx] - m * x[idx] for idx in (0, -1)])
        return (m, b)

## I want this to inherit methods/attributes
## specified by distribution_model
class DistributionModel():

    def __init__(self, distribution_model):
        self._distribution_model = None
        self.initialize_model(distribution_model)

    @property
    def available_distribution_models(self):
        result = {}
        result['linear equation'] = LinearEquation()
        result['normal distribution'] = NormalDistribution()
        return result

    def initialize_model(self, distribution_model):
        if distribution_model not in list(self.available_distribution_models.keys()):
            raise ValueError("invalid distribution_model: {}".format(distribution_model))
        self._distribution_model = distribution_model
        model = self.available_distribution_models[distribution_model]
        for attribute in dir(model):
            setattr(self, attribute, getattr(model, attribute))

打电话,

Model = DistributionModel('normal distribution')

np.random.seed(327)
prms = (50, 10)
data = np.random.normal(loc=prms[0], scale=prms[1], size=100).astype(int)
x = np.sort(data)
y = Model.f(prms, x)

fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
plt.close(fig)
4

1 回答 1

0

我找到了适合我的情况的解决方法。也许这对其他人有帮助,但也许有更好的方法?

LinearEquation我在and的类定义中添加了下面的函数NormalDistribution

def get_kwargs(self):
    result = {}
    result['pdf'] = self.pdf
    result['get_parameter_guess'] = self.get_parameter_guess
    return result

然后,initialize_model(distribution_model)类内部的函数DistributionModel更改为以下内容:

def initialize_model(self, distribution_model):
    if distribution_model not in list(self.available_distribution_models.keys()):
        raise ValueError("invalid distribution_model: {}".format(distribution_model))
    self._distribution_model = distribution_model
    model = self.available_distribution_models[distribution_model]
    for key, attribute in model.get_kwargs().items():
        setattr(self, key, attribute)
于 2020-01-05T07:56:19.803 回答