-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Array scalar conversion deprecation #13864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Array scalar conversion deprecation #13864
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good but how about using .item()
instead of .flat[0]
for cases when the array can have multiple dimensions but one item? IMO, the former looks cleaner and preserves the behaviour of returning a Python float (compared to .flat[0]
which returns NumPy floats)
Sure, looks cleaner indeed. Let me make the changes. |
Done. |
@nschloe Thanks! The new error messages need tests. Can you please add them too? |
Co-authored-by: peterbell10 <peterbell10@live.co.uk>
Instead of fiddling around with the individual optimization methods, let me try and edit the function wrappers; perhaps the the changes will be more concise. |
I think the PR is in better shape now. I essentially moved the scalar conversion to into |
I've not had much time to spend on scipy over the last few months, and don't think I'll be able to look before the branch point. |
I don't think my concern has been addressed: If NumPy is redefining what is acceptable to treat as a scalar, shouldn't it be up to the user-provided functions to conform to that definition? A good argument against would be if |
@peterbell10 I agree, but from what I recall scipy is rather conservative when it comes to making changes to the user interface. That's why I "fixed" some scipy functions to only hand shape-0 arrays to numpy. To illustrate, an example would be goal functionals like def f(x):
return np.array([x ** 2 - 1.0]) This works in scipy without warning now. It would have to be changed to def f(x):
return x ** 2 - 1.0 to avoid the warning. This PR makes sure both versions pass without warning. |
Yes, I know. I would like to see evidence that array-scalar conversion is a documented part of the current API, not just a coincidence due to NumPy's behavior. If it's not documented, then I see no reason to continue supporting it with an ugly workaround. |
Just to be sure I understand correctly: You'd like to know if SciPy actually documents that you can do def f(x):
return np.array([x ** 2 - 1.0]) and if it's not documented, it'd be okay to just emit a warning like numpy does? |
Perhaps an argument in favor of suppressing the warning: from scipy import optimize
import numpy as np
def f(x):
out = -np.exp(-(x - 0.7)**2)
return out
result = optimize.minimize(f, x0=0.3)
from scipy import optimize
import numpy as np
def f(x):
out = -np.exp(-(x - 0.7)**2)
return out[0]
result = optimize.minimize(f, x0=0.3) Not sure if that's desirable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, although the minimize
documentation doesn't explicitly support non-scalars. It does work for all methods currently, and consolidating handling into fewer places would make any future deprecation easier if we go down that route.
Co-authored-by: peterbell10 <peterbell10@live.co.uk>
Indeed, that's what this PR is does, too (-> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I'll leave this open for a bit in case an optimize
expert wants to comment.
@peterbell10 Perhaps now that 1.7.0 is released is a good time to merge? |
Are you sure |
@eric-wieser Good point. I've checked the use of |
|
Many of the
It's faster indeed:
We're talking about saving a few hundred nanoseconds here though which is less than the product of an integer with an object scalar:
A stronger argument for |
By "object scalar" I mean |
Hehe. – I would argue they are scalars because they small, taste, and look like scalars. You can't tell the difference. In numerical computation, they behave exactly the same. How the data is stored in memory is just an implementational detail. Edit: The only difference I can think of right now are Python-list computations which fail for Python floats, |
Scalars are immutable and 0d arrays are mutable. That's a pretty big difference. |
At least this is the case for python |
With a view on numpy/numpy#10615, I checked where in SciPy there are implicit array-to-float conversions. In all cases I've checked so far, there was some slight carelessness in the past that we probably have to maintain for backwards compatibility. For example, we allow return values from optimization objective function to be of any shape, as long as they are size 1. (The strict -- some would argue more correct -- approach would be to enforce true scalar return values.)
Anyway, here is a PR that fixes some of the implicit array-to-float conversions by making them explicit. These fix ~30 of the ~90 test warnings when the deprecation in numpy/numpy#10615 is enabled. They also give good error messages if the user returns something other than a size-1 array from an objective function rather than failing at an assignment, so I think that's a win, too.
Let me know what you think.