-3

I am fitting a very simple curve having three points. with leastsq method, following all the rules. But still I am getting error. I cannot understand. Can anyone help. Thank you so much

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq

x = np.array([2.0,30.2,15.0])
y = np.array([45.0,56.2,30.0])

print(x)
print(y)

# model
def t(x,a,b,c):
    return a*x**2 + b*x + c

#residual fucntion
def residual_t(x,y,a,b,c):
    return y-t(x,a,b,c)


#initial parameters
g0 = np.array([0.0,0.0,0.0])

#leastsq method
coeffs, cov = leastsq(residual_t, g0, args=(x,y))
plt.plot(x,t(x,*coeffs),'r')
plt.plot(x,y,'b')
plt.show()

#finding out Rsquared and Radj squared value
absError = residual_t(y,x,*coeffs)
se = np.square(absError) # squared errors
Rsquared = 1.0 - (np.var(absError) / np.var(y))
n = len(x)
k = len(coeffs)
Radj_sq = (1-((1-Rsquared)/(n-1)))/(n-k-1)
print (f'Rsquared value: {Rsquared}   adjusted R saquared value: {Radj_sq}')

TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'

Why?? coeffs is already a array containing best it values of a, b,c. coeffs is also showing undefined and residual_t is also showing problem. Could you please help me to understand.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
Esha
  • 1
  • 2

1 Answers1

1

With a copy-n-paste of your code (including the *coeffs change), I get

1135:~/mypy$ python3 stack58206395.py 
[ 2.  30.2 15. ]
[45.  56.2 30. ]
Traceback (most recent call last):
  File "stack58206395.py", line 24, in <module>
    coeffs, cov = leastsq(residual_t, g0, args=(x,y))
  File "/usr/local/lib/python3.6/dist-packages/scipy/optimize/minpack.py", line 383, in leastsq
    shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
  File "/usr/local/lib/python3.6/dist-packages/scipy/optimize/minpack.py", line 26, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'

That is the error is in the use of residual_t within the leastsq call.

If I add

residual_t(g0, x, y)

right after the g0 definition I get the same error:

1136:~/mypy$ python3 stack58206395.py 
[ 2.  30.2 15. ]
[45.  56.2 30. ]
Traceback (most recent call last):
  File "stack58206395.py", line 23, in <module>
    residual_t(g0, x, y)
TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'

So you need to define residual_t to work with a call like this. I'm not going to take a guess as to what you really want, so I'll leave the fix up to you.

Just remember that residual_t will be called with the x0, spliced with the args tuple. This is typical usage for scipy.optimize functions. Review the docs if necessary.

edit

Defining the function as:

def residual_t(abc, x, y):
    a,b,c = abc
    return y-t(x,a,b,c)

runs without error.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • I did not understand your answer. As per I know the scipy function leastsq, it require a function, initial guess and x,y arguments. These three things are compulsory. from array initial guess it takes the values and substitute in the argument of the function. Kindly check me if I am wrong. In my case g0 is my guess array which contains value of a, b,c argument. I did not understand why there is type error saying missing of values of b and c only. – Esha Oct 03 '19 at 09:04
  • 1
    In Python an argument list like `(x,y,a,b,c)` is positional. `leastsq` is passing `(g0, x, y)`, the first 3 positions. `b,c` are unfilled positions. You should define `residual_t(abc, x, y)` to match the `scipy` calling convention. – hpaulj Oct 03 '19 at 15:57
  • Thank you everyone ..it is working now. But I did not understand the concept. I will be grateful if anyone can explain. – Esha Oct 07 '19 at 10:51
  • leastsq is a function which needs a residual function, initial guess where the first values of your variable will be stored and args=(x,y) your data. Why scipy is taking the values stored in g0 as one value whereas there are three values in same g0? – Esha Oct 07 '19 at 10:59