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

Schuldei, Andreas andreas.schuldei at th-luebeck.de
Mon Oct 5 15:22:19 EDT 2020


thank you for your help. Now i rewrote the packing and unpacking and it looks like this:


def find_vector_of_minor_axis_from_chunk(data):
    n = 20  # number of points
    center_point = data.mean(1)
    guess_center_point_x = center_point[0]
    guess_center_point_y = center_point[1]
    guess_center_point_z = center_point[2]

    guess_a_axis_vector_x = 1.0
    guess_a_axis_vector_y = 0.0
    guess_a_axis_vector_z = 0.0

    guess_b_axis_vector_x = 0.0
    guess_b_axis_vector_y = 1.0
    guess_b_axis_vector_z = 0.0

    guess_a_phase = 0.0
    guess_b_phase = 0.0

    p0 = np.array([guess_center_point_x, guess_center_point_y, guess_center_point_z,
                   guess_a_axis_vector_x, guess_a_axis_vector_y, guess_a_axis_vector_z,
                   guess_b_axis_vector_x, guess_b_axis_vector_y, guess_b_axis_vector_z,
                   guess_a_phase,
                   guess_b_phase])

    def ellipse_func(x, data):
        center_point = np.array([[x[0]], [x[1]], [x[2]]])
        a_axis_vector = np.array([[x[3]], [x[4]], [x[5]]])
        b_axis_vector = np.array([[x[6]], [x[7]], [x[8]]])
        a_phase = x[9]
        b_phase = x[10]
        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 error_sum

    res = minimize(ellipse_func, p0, args=data)
    center_point_x, center_point_y, center_point_z, a_axis_vector_x, a_axis_vector_y, a_axis_vector_z, b_axis_vector_x, b_axis_vector_y, b_axis_vector_z, a_phase, b_phase = res.x

    a_axis_vector = np.array([a_axis_vector_x, a_axis_vector_y, a_axis_vector_z])
    b_axis_vector = np.array([b_axis_vector_x, b_axis_vector_y, b_axis_vector_z])
    print(str(res.x))
    shorter_vector = a_axis_vector
    if np.all(np.abs(a_axis_vector) > np.abs(b_axis_vector)):
        shorter_vector = b_axis_vector
    return shorter_vector

(just to leave something working for posterity.) Is this as elegant as it gets?

________________________________
Von: SciPy-User <scipy-user-bounces+andreas.schuldei=th-luebeck.de at python.org> im Auftrag von Robert Kern <robert.kern at gmail.com>
Gesendet: Montag, 5. Oktober 2020 17:26:18
An: SciPy Users List
Betreff: Re: [SciPy-User] _minimize_bfgs throws error: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

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 <andreas.schuldei at th-luebeck.de<mailto:andreas.schuldei at th-luebeck.de>> 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
SciPy-User at python.org<mailto:SciPy-User at python.org>
https://mail.python.org/mailman/listinfo/scipy-user


--
Robert Kern
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scipy-user/attachments/20201005/ed7b2df2/attachment-0001.html>


More information about the SciPy-User mailing list