如何将不同类型的参数(例如数组)传递给函数类? [英] How can I pass different types of parameters (ex: array) into a functional class?

查看:131
本文介绍了如何将不同类型的参数(例如数组)传递给函数类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何按班级对功能进行分组。例如,我尝试编码一种广义最小二乘法,以找到一组(x,y)坐标之间的最佳拟合线的方程。对于我的特殊情况,我选择了一条简单的线 y = x + 5 ,因此斜率应接近 1 , y截距应接近 5 。在下面的编码解决方案中运行我的尝试会产生错误 TypeError:set_x()接受1个位置参数,但给出了2个,尽管我试图传递x点数组。我该如何避免此错误?

  import numpy as scipy.np 
从scipy.optimize import最小化


class GeneralizedLeastSquares:

def __init __(自我,残差=无,参数=无,x =无,y_true =无,y_fit =无,权重=无,方法=无):
self.residuals =残差
self.parameters =参数
self.x = x
self.y_true = y_true
self.y_fit = y_fit
self.weights =权重
self.method =方法

def set_residuals(自身,残差):
self.residuals =残差

def set_parameters (self,参数):
self.parameters =参数

def set_x(self,x):
self.x = x

def set_y_true (self,y_true):
self.y_true = y_true

def set_y_fit(self,y_fit):
self.y_fit = y_fit

def set_weights (自我,体重):
sel f.weights = weights

def set_method(self,method):
self.method = method

def get_residuals(self):
return [ (self.y_true [idx]-self.y_fit [idx])** 2,如果len(self.y_true)== len(self.y_fit)=(len(self.y_fit))

def get_parameters(self):
返回self.parameters

def get_x(self):
return self.x

def get_y_true (self):
return self.y_true

def get_y_fit(self):
return [self.parameters [0] * self.x [idx] + self.parameters [ 1]用于范围内的idx(len(self.x))]

def get_weights(self):
返回self.weights

def update_weights(self) :
inverse_residuals = [1 / self.residuals [idx] for范围内的idx(len(residuals))]
inverse_residuals_abs = [abs(inverse_residual)inverse_residual inverse_residuals]
(inverse_residuals_abs)
返回[inverse_residuals_abs [idx] / residual_abs_total范围内的idx(len(inverse_residuals_abs))]

def get_method(self):
返回self.method

def get_error_by_residuals(self):
返回总和([self.weights [idx] * self.residuals [idx] for范围内的idx(len(self.residuals))]))

def get_error_by_std_mean (自我):
return np.std(self.y_true)/np.sqrt(len(self.y_true))

def get_linear_fit(self):



如果self.parameters =='estimate':
lope_init =(self.y_true [-1]-self.y_true [0])/(self .x [-1]-self.x [0])
b_init = np.mean([self.y_true [-1] -lope_init * self.x [-1],self.y_true [0]- lope_init * self.x [0]])
self.parameters = [slope_init,b_init]
elif not isinstance(self.parameters,(list,np.ndarray)):
引发ValueError (参数='估计'或[斜率,y轴截距])
meths = ['residuals','std of mean']
funcs = [get_error_by_residuals,get_error_by_std_mean]
func = dict(zip(meths,funcs))[self.method]
res =最小化(func,x0 = self.parameters,args =(self,),method ='Nelder-Mead')
self.parameters = [res.x [0],res.x [1]]
self.y_fit = get_y_fit(self)
self.residuals = get_residuals(self)
self.weights = update_weights(self)
返回self.parameters,self.y_fit,self.residuals ,self.weights

x = np.linspace(0,4,5)
y_true = np.linspace(5,9,5)##使用斜率= 1,y-intercept = 5
y_actual = np.array([4.8,6.2,7,8.1,8.9])##测试数据
GLS = GeneralizedLeastSquares()
GLS.set_x(x)
GLS.set_y_true(y_actual)
GLS.set_weights(np.ones(len(x)))
GLS.set_parameters('estimate')
#GLS.set_parameters([1.2,4.9] )
GLS.set_method('residuals')
结果= GLS.get_linear_fit()
打印(结果)


解决方案

您的方法未使用参数。应该是:

  def set_x(self,x):
self.x = x

在get / set方法中包装属性是一种非常过时的Java方法。访问类外部的基础属性要容易得多。即而不是: GLS.set_x(12),请考虑使用更多Python语言: GLS.x = 12 。这样,您不必为每个属性编写get和set方法。



此外,对于对象的繁重工作方法 get_linear_fit 放在 __ call __ 方法中。这样,您可以通过键入 GLS()而不是 GLS.get_linear_fit()

I am trying to learn how to group functions by class. As an example, I tried to code a generalized least squares method to find the equation of a best-fitting line between a set of (x,y) coordinates. For my particular case, I chose a simple line y = x + 5, so slope should be close to 1 and y-intercept should be close to 5. Running my attempt at a coded solution below produces the error TypeError: set_x() takes 1 positional argument but 2 were given, though I am trying to pass an array of x-points. How can I circumvent this error?

import numpy as np
from scipy.optimize import minimize


class GeneralizedLeastSquares:

    def __init__(self, residuals=None, parameters=None, x=None, y_true=None, y_fit=None, weights=None, method=None):
        self.residuals = residuals
        self.parameters = parameters
        self.x = x
        self.y_true = y_true
        self.y_fit = y_fit
        self.weights = weights
        self.method = method

    def set_residuals(self, residuals):
        self.residuals = residuals

    def set_parameters(self, parameters):
        self.parameters = parameters

    def set_x(self, x):
        self.x = x

    def set_y_true(self, y_true):
        self.y_true = y_true

    def set_y_fit(self, y_fit):
        self.y_fit = y_fit

    def set_weights(self, weights):
        self.weights = weights

    def set_method(self, method):
        self.method = method

    def get_residuals(self):
        return [(self.y_true[idx] - self.y_fit[idx])**2 for idx in range(len(self.y_true)) if len(self.y_true) == len(self.y_fit) ]

    def get_parameters(self):
        return self.parameters

    def get_x(self):
        return self.x

    def get_y_true(self):
        return self.y_true

    def get_y_fit(self):
        return [self.parameters[0] * self.x[idx] + self.parameters[1] for idx in range(len(self.x))]

    def get_weights(self):
        return self.weights

    def update_weights(self):
        inverse_residuals = [1/self.residuals[idx] for idx in range(len(residuals))]
        inverse_residuals_abs = [abs(inverse_residual) for inverse_residual in inverse_residuals]
        residual_abs_total = sum(inverse_residuals_abs)
        return [inverse_residuals_abs[idx]/residual_abs_total for idx in range(len(inverse_residuals_abs))]

    def get_method(self):
        return self.method

    def get_error_by_residuals(self):
        return sum([self.weights[idx] * self.residuals[idx] for idx in range(len(self.residuals))])

    def get_error_by_std_mean(self):
        return np.std(self.y_true)/np.sqrt(len(self.y_true))

    def get_linear_fit(self):
        """

        """
        if self.parameters == 'estimate':
            slope_init = (self.y_true[-1] - self.y_true[0]) / (self.x[-1] - self.x[0])
            b_init = np.mean([self.y_true[-1] - slope_init * self.x[-1], self.y_true[0] - slope_init * self.x[0]])
            self.parameters = [slope_init, b_init]
        elif not isinstance(self.parameters, (list, np.ndarray)):
            raise ValueError("parameters = 'estimate' or [slope, y-intercept]")
        meths = ['residuals', 'std of mean']
        funcs = [get_error_by_residuals, get_error_by_std_mean]
        func = dict(zip(meths, funcs))[self.method]
        res = minimize(func, x0=self.parameters, args=(self,), method='Nelder-Mead')
        self.parameters = [res.x[0], res.x[1]]
        self.y_fit = get_y_fit(self)
        self.residuals = get_residuals(self)
        self.weights = update_weights(self)
        return self.parameters, self.y_fit, self.residuals, self.weights

x = np.linspace(0, 4, 5)
y_true = np.linspace(5, 9, 5) ## using slope=1, y-intercept=5
y_actual = np.array([4.8, 6.2, 7, 8.1, 8.9]) ## test data
GLS = GeneralizedLeastSquares()
GLS.set_x(x)
GLS.set_y_true(y_actual)
GLS.set_weights(np.ones(len(x)))
GLS.set_parameters('estimate')
# GLS.set_parameters([1.2, 4.9])
GLS.set_method('residuals')
results = GLS.get_linear_fit()
print(results)

解决方案

Your method is not taking an argument. It should be:

def set_x(self, x):
    self.x = x

Wrapping properties in get/set methods is a very Java / outdated way of doing things. It is much easier to access the underlying property outside of your class. I.e. rather than: GLS.set_x(12), consider the more Pythonic: GLS.x = 12. This way you don't have to write a get and set method for each property.

Also, it might make more sense for the heavy lifting method of your object, get_linear_fit to be put in the __call__ method. This way, you can run the regression using by just typing GLS() rather than GLS.get_linear_fit()

这篇关于如何将不同类型的参数(例如数组)传递给函数类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆