简体   繁体   中英

call a function as argument in least_squares return “ TypeError: 'numpy.ndarray' object is not callable ”

I want to create a function 'residual' which computes the residual of another function of interest. When calling the 'residual' function with least_squares, I get the error "TypeError: 'numpy.ndarray' object is not callable"

Here is what I have tried:

import numpy as np
from scipy.optimize import least_squares

### define my function of interest
def linear(x,params):
    a=params[0]
    b=params[1]
    y=a*x+b
    return y

#### define function for computing residual
def residual(func,x,y,params):
    args=(x,params)        
    func_x =  func(*args)
    return func_x - y    

#### initialize variables
data_x=np.arange(1,11)
data_y=np.array([3,4,7,9,12,14,16,19,18,21])
init_params=[2,1]

### option 1: calculate the computing residual of 'linear' using 'residual':
res1=residual(linear,data_x,data_y,init_params)

### option 2: call 'residual' with least_squares including the 'linear function in the arguments:
fit_result= least_squares(residual, init_params, args=(linear,data_x,data_y))
# 

When I try option 1, the function residual works just fine. However, in the option 2, where I want to call 'residual' with 'least_squares', I get the error "TypeError: 'numpy.ndarray' object is not callable".

I was stumped as well and the documentation on least_squares was making my head spin. But apparently you just had an issue with the arrangement of the arguments in your function definitions. I modified it a little bit and the error disappeared:

import numpy as np
from scipy.optimize import least_squares

### define my function of interest
#def linear(x,params):
def linear(params,x):
    a=params[0]
    b=params[1]
    y=a*x+b
    return y

#### define function for computing residual
# def residual(func,x,y,params):
def residual(params,func,x,y):
    args=(params,x)
    # args=(x,params)        
    func_x =  func(*args)
    return func_x - y    

#### initialize variables
data_x=np.arange(1,11)
data_y=np.array([3,4,7,9,12,14,16,19,18,21])
init_params=[2,1]

def callable_params(input):
    return float(input)

data_linear = linear(data_x,init_params)

print(data_x)
print(data_y)
print(data_linear)

### option 1: calculate the computing residual of 'linear' using 'residual':
res1=residual(init_params,linear,data_x,data_y)
print(res1)


### option 2: call 'residual' with least_squares including the 'linear function in the arguments:
fit_result= least_squares(fun=residual, x0=init_params, args=(linear,data_x,data_y))
print(fit_result)

# fit_result= least_squares(residual, init_params, args=(linear,data_x,data_y))
# 

And the output (Windows command line) running the script:

[ 1  2  3  4  5  6  7  8  9 10]
[ 3  4  7  9 12 14 16 19 18 21]
[4 3]
[ 0  1  0  0 -1 -1 -1 -2  1  0]
 active_mask: array([0., 0.])
        cost: 3.793939393939392
         fun: array([-0.05454545,  1.02424242,  0.1030303 ,  0.18181818, -0.73939394,
       -0.66060606, -0.58181818, -1.5030303 ,  1.57575758,  0.65454545])
        grad: array([-3.45811628e-08, -4.44089210e-15])
         jac: array([[ 1.00000001,  1.        ],
       [ 2.        ,  1.        ],
       [ 2.99999999,  1.        ],
       [ 4.        ,  1.        ],
       [ 5.00000001,  1.        ],
       [ 5.99999997,  1.        ],
       [ 6.99999999,  1.        ],
       [ 8.        ,  1.        ],
       [ 8.99999996,  1.        ],
       [10.00000003,  1.        ]])
     message: '`xtol` termination condition is satisfied.'
        nfev: 3
        njev: 2
  optimality: 3.458116282217816e-08
      status: 3
     success: True
           x: array([2.07878788, 0.86666667])

Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM