Scipy: leastsq needlessly appends extra dimension for scalar problems

Created on 7 Mar 2018  路  5Comments  路  Source: scipy/scipy

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.)

defect scipy.optimize

All 5 comments

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.

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alonemanuel picture alonemanuel  路  4Comments

fakekarma picture fakekarma  路  3Comments

StefanTheWiz picture StefanTheWiz  路  4Comments

NicolasHug picture NicolasHug  路  4Comments

tomogwen picture tomogwen  路  3Comments