When treating a scalar problem, leastsq needlessly appends an extra dimension to the argument of the function to be minimized as well as the result. MCVE:
from scipy.optimize import leastsq
def f(x):
print(x.shape)
return x
out = leastsq(f, 0.0)
print(out)
print()
leastsq(f, [0.0])
print(out)
Output:
(1,)
(1,)
(1,)
(1,)
(array([0.]), 4)
(1,)
(1,)
(1,)
(1,)
(array([0.]), 4)
Expected output:
()
()
()
()
(array(0.), 4)
(1,)
(1,)
(1,)
(1,)
(array([0.]), 4)
As a consequence of this, many codes have to select the "first" element in a scalar problem
out, _ = leastsq(f, 0.0)
theta = out[0] # this should be unnecessary
I personally ran into this when trying to clean up my f(x) which involves dots and such, and wondered why things like
array = something()
def f(theta):
sc = numpy.array([numpy.sin(theta), numpy.cos(theta)])
return numpy.dot(sc, array)
wouldn't work. (It was the superfluous dimension in theta that had the dot product fail.)
I think this is due to the conversion of x0 i.e (The starting estimate for the minimization) into a numpy.array in method leastsq, should this be handled if x0 has only one value or add appropriate documentation for inputs of func in method leastsq
At this point, I would favor simply documentation-only fix as no doubt there is code out there relying on the current behavior, so it cannot just be changed.
The issue is that in general these routines work only on 1D vectors and don't preserve the input shape, so the current behavior is not immediately considered a bug. If they generally preserved the input shape one could argue differently, but this is not the case.
Ah, you're right: It's the flatten() at https://github.com/scipy/scipy/blob/master/scipy/optimize/minpack.py#L377.
I think some change required in line 279 also, may be similar to this
diff --git a/scipy/optimize/minpack.py b/scipy/optimize/minpack.py
index a39bc15..5812e9e 100644
--- a/scipy/optimize/minpack.py
+++ b/scipy/optimize/minpack.py
@@ -275,7 +275,7 @@ def leastsq(func, x0, args=(), Dfun=None, full_output=0,
Parameters
----------
func : callable
- should take at least one (possibly length N vector) argument and
+ should take at least one (possibly length N vector) argument of type 1D numpy.array and
returns M floating point numbers. It must not return NaNs or
fitting might fail.
x0 : ndarray
This is being addressed in #8666