Re: _minimize_bfgs throws error: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Robert Kern <[email protected]> Mon, 5 Oct 2020 11:26:18 -0400
Newsgroups gmane.comp.python.scientific.user
Message-ID <CAF6FJitfrNzyuiTLjyFbn3KiyzA11hk7n0OmhmdR=uUMMCbWVQ@mail.gmail.com>
You can and should remove the `np.any()` from `ellipse_func()`; that's not
what the error message is asking for. That line is expecting `rhok` to be a
scalar and thus `isinf(rhok)` to be a scalar boolean. Because of an error
in the construction of the parameter vector, `rhok` ended up being an array
rather than a scalar, making `isinf(rhok)` a boolean array, which does not
have a consistent truth value that can be used in the `if` statement. We
make a recommendation in the error message that is usually helpful for the
common mistakes that end up like this, at least for people who are writing
the `if` statement. However, you are just using the function that has this
`if` statement, and the advice does not apply to the code outside of the
`if` statement.

Instead, you need to make the parameter vector `x` (and `p0`, of course) a
1D vector of floats, not an object array mixing arrays and scalars. All of
the minimizers are expecting functions that map 1D parameter vectors of
floats to scalars. You will have to pack and unpack this parameter vector
to get the different vectors and scalars you use to compute the error in
`ellipse_func()`.

On Mon, Oct 5, 2020 at 10:56 AM Schuldei, Andreas <
[email protected]> wrote:

> I seem to trigger an internal error in scipy.optimize.minimize, somehow.
>
>
> This is the code that triggers the problem:
>
>
>     import numpy as np
>     from scipy.optimize import minimize
>
>
>     def find_vector_of_minor_axis_from_chunk(data):
>         n = 20  # number of points
>         guess_center_point = data.mean(1)
>         guess_center_point = guess_center_point[np.newaxis, :].transpose()
>         guess_a_phase = 0.0
>         guess_b_phase = 0.0
>         guess_a_axis_vector = np.array([[1.0], [0.0], [0.0]])
>         guess_b_axis_vector = np.array([[0.0], [1.0], [0.0]])
>
>         p0 = np.array([guess_center_point,
>                        guess_a_axis_vector, guess_a_phase,
>                        guess_b_axis_vector, guess_b_phase])
>
>         def ellipse_func(x, data):
>             center_point = x[0]
>             a_axis_vector = x[1]
>             a_phase = x[2]
>             b_axis_vector = x[3]
>             b_phase = x[4]
>             t = np.linspace(0, 2 * np.pi, n)
>             error = center_point + a_axis_vector * np.sin(t * a_phase) +
> b_axis_vector * np.sin(t + b_phase) - data
>             error_sum = np.sum(error ** 2)
>             return np.any(error_sum)
>
>         popt, pcov = minimize(ellipse_func, p0, args=data)
>         center_point, a_axis_vector, a_phase, b_axis_vector, b_phase = popt
>
>         print(str(a_axis_vector + ", " + b_axis_vector))
>         shorter_vector = a_axis_vector
>         if np.abs(a_axis_vector) > np.aps(b_axis_vector):
>             shorter_vector = b_axis_vector
>         return shorter_vector
>
>
>     def main():
>         data = np.array([[-4.62767933, -4.6275775, -4.62735346,
> -4.62719652, -4.62711625, -4.62717975,
>                           -4.62723845, -4.62722407, -4.62713901,
> -4.62708749, -4.62703238, -4.62689101,
>                           -4.62687185, -4.62694013, -4.62701082,
> -4.62700483, -4.62697488, -4.62686825,
>                           -4.62675683, -4.62675204],
>                          [-1.58625998, -1.58625039, -1.58619648,
> -1.58617611, -1.58620606, -1.5861833,
>                           -1.5861821, -1.58619169, -1.58615814,
> -1.58616893, -1.58613179, -1.58615934,
>                           -1.58611262, -1.58610782, -1.58613179,
> -1.58614017, -1.58613059, -1.58612699,
>                           -1.58607428, -1.58610183],
>                          [-0.96714786, -0.96713827, -0.96715984,
> -0.96715145, -0.96716703, -0.96712869,
>                           -0.96716104, -0.96713228, -0.96719698,
> -0.9671838, -0.96717062, -0.96717062,
>                           -0.96715744, -0.96707717, -0.96709275,
> -0.96706519, -0.96715026, -0.96711791,
>                           -0.96713588, -0.96714786]])
>
>         print(str(find_vector_of_minor_axis_from_chunk(data)))
>
>
>     if __name__ == '__main__':
>         main()
>
> and this is the traceback for it:
>
>     "C:\Users\X\PycharmProjects\lissajous-achse\venv\Scripts\python.exe"
> "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py"
>     Traceback (most recent call last):
>       File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py",
> line 57, in <module>
>         main()
>       File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py",
> line 53, in main
>         print(str(find_vector_of_minor_axis_from_chunk(data)))
>       File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py",
> line 29, in find_vector_of_minor_axis_from_chunk
>         popt, pcov = minimize(ellipse_func, p0, args=data)
>       File
> "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\_minimize.py",
> line 604, in minimize
>         return _minimize_bfgs(fun, x0, args, jac, callback, **options)
>       File
> "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\optimize.py",
> line 1063, in _minimize_bfgs
>         if isinf(rhok):  # this is patch for numpy
>     ValueError: The truth value of an array with more than one element is
> ambiguous. Use a.any() or a.all()
>
>     Process finished with exit code 1
>
> I tried to take the suggestion in the traceback (to use `np.any()` or
> `np.all()`) on the return value of the `ellipse_func`, but just got the
> next internal scipy error.
>
> What can I do to get my optimization running? I am open to using other
> functions besides `minimize()`.
>
>
> _______________________________________________
> SciPy-User mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/scipy-user
>


-- 
Robert Kern

_______________________________________________
SciPy-User mailing list
[email protected]
https://mail.python.org/mailman/listinfo/scipy-user