Vectorized version of numpy.linspace

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Vectorized version of numpy.linspace

Stephan Hoyer-2
It recently came up on GitHub (at part of the discussion in https://github.com/numpy/numpy/issues/12379) that numpy.linspace could, at least in principle, be modified to support array inputs:

It looks like this has been requested on StackOverflow, too:

My tentative proposal:
- "start" and "stop" are broadcast against each other to form start/stop arrays. (Or we could require that start/stop have matching shape.)
- A new dimension of size "num" is inserted into the result, either along the first or last axis.
- A new keyword argument "axis" could control where the axis is inserted in the result.
- Vectorization support should be added in the same way to geomspace and logspace.

Does this seem like a good idea? It's a relatively simple generalization, and one that I, at least, would find useful (I can think of a use-case in my own code that came up just last week).

I doubt I'll have time to implement this myself in the near future, but I thought I would get the discussion going -- this might be a good project for a new contributor to work on.

Cheers,
Stephan


_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

ralfgommers


On Wed, Nov 14, 2018 at 8:57 AM Stephan Hoyer <[hidden email]> wrote:
It recently came up on GitHub (at part of the discussion in https://github.com/numpy/numpy/issues/12379) that numpy.linspace could, at least in principle, be modified to support array inputs:

It looks like this has been requested on StackOverflow, too:

My tentative proposal:
- "start" and "stop" are broadcast against each other to form start/stop arrays. (Or we could require that start/stop have matching shape.)
- A new dimension of size "num" is inserted into the result, either along the first or last axis.
- A new keyword argument "axis" could control where the axis is inserted in the result.
- Vectorization support should be added in the same way to geomspace and logspace.

Does this seem like a good idea? It's a relatively simple generalization, and one that I, at least, would find useful (I can think of a use-case in my own code that came up just last week).

This feels a bit forced. There's not much relevance to the minor performance gain, and for code clarity it probably also wouldn't help (actually it hurts usability for 99.x% of use cases by making the doc more complicated). Not sure that it really would require a new axis argument, as Marten said on the issue. Also, the num keyword cannot be vectorized, unless one returns a list of arrays, which would actually be more natural here than a 2-D array.

So, at best a don't care for me - I'm -0.5.

Cheers,
Ralf

 

I doubt I'll have time to implement this myself in the near future, but I thought I would get the discussion going -- this might be a good project for a new contributor to work on.

Cheers,
Stephan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Gerrit Holl-2
On Wed, 14 Nov 2018 at 17:29, Ralf Gommers <[hidden email]> wrote:

> On Wed, Nov 14, 2018 at 8:57 AM Stephan Hoyer <[hidden email]> wrote:
>>
>> It recently came up on GitHub (at part of the discussion in https://github.com/numpy/numpy/issues/12379) that numpy.linspace could, at least in principle, be modified to support array inputs:
>>
>> It looks like this has been requested on StackOverflow, too:
>> https://stackoverflow.com/questions/46694167/vectorized-numpy-linspace-across-multi-dimensional-arrays
>>
>> My tentative proposal:
>> - "start" and "stop" are broadcast against each other to form start/stop arrays. (Or we could require that start/stop have matching shape.)
>> - A new dimension of size "num" is inserted into the result, either along the first or last axis.
>> - A new keyword argument "axis" could control where the axis is inserted in the result.
>> - Vectorization support should be added in the same way to geomspace and logspace.
>>
>> Does this seem like a good idea? It's a relatively simple generalization, and one that I, at least, would find useful (I can think of a use-case in my own code that came up just last week).
>
>
> This feels a bit forced. There's not much relevance to the minor performance gain, and for code clarity it probably also wouldn't help (actually it hurts usability for 99.x% of use cases by making the doc more complicated). Not sure that it really would require a new axis argument, as Marten said on the issue. Also, the num keyword cannot be vectorized, unless one returns a list of arrays, which would actually be more natural here than a 2-D array.
>
> So, at best a don't care for me - I'm -0.5.

For what it's worth, I had a use case for this in the past week, when
I needed many simple linear interpolations between two values (thus a
linspace) with only the value of boundary points varying.  However,
this was the first time I've ever needed it, and I found a recipe on
Stack Overflow within minutes
(https://stackoverflow.com/a/42617889/974555) so it wasn't a big deal
that it wasn't available in core numpy.

Gerrit.
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Matthew Harrigan
I put in an issue a while ago, https://github.com/numpy/numpy/issues/8839

My use case was somwhat similar to meshgrid but with a nonrectangular domain.  Not terribly hard to code, but my expectation is that numpy functions should always allow broadcasting if that operation makes sense.

On Nov 14, 2018 12:42 PM, "Gerrit Holl" <[hidden email]> wrote:
On Wed, 14 Nov 2018 at 17:29, Ralf Gommers <[hidden email]> wrote:
> On Wed, Nov 14, 2018 at 8:57 AM Stephan Hoyer <[hidden email]> wrote:
>>
>> It recently came up on GitHub (at part of the discussion in https://github.com/numpy/numpy/issues/12379) that numpy.linspace could, at least in principle, be modified to support array inputs:
>>
>> It looks like this has been requested on StackOverflow, too:
>> https://stackoverflow.com/questions/46694167/vectorized-numpy-linspace-across-multi-dimensional-arrays
>>
>> My tentative proposal:
>> - "start" and "stop" are broadcast against each other to form start/stop arrays. (Or we could require that start/stop have matching shape.)
>> - A new dimension of size "num" is inserted into the result, either along the first or last axis.
>> - A new keyword argument "axis" could control where the axis is inserted in the result.
>> - Vectorization support should be added in the same way to geomspace and logspace.
>>
>> Does this seem like a good idea? It's a relatively simple generalization, and one that I, at least, would find useful (I can think of a use-case in my own code that came up just last week).
>
>
> This feels a bit forced. There's not much relevance to the minor performance gain, and for code clarity it probably also wouldn't help (actually it hurts usability for 99.x% of use cases by making the doc more complicated). Not sure that it really would require a new axis argument, as Marten said on the issue. Also, the num keyword cannot be vectorized, unless one returns a list of arrays, which would actually be more natural here than a 2-D array.
>
> So, at best a don't care for me - I'm -0.5.

For what it's worth, I had a use case for this in the past week, when
I needed many simple linear interpolations between two values (thus a
linspace) with only the value of boundary points varying.  However,
this was the first time I've ever needed it, and I found a recipe on
Stack Overflow within minutes
(https://stackoverflow.com/a/42617889/974555) so it wasn't a big deal
that it wasn't available in core numpy.


Gerrit.

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion


_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Marten van Kerkwijk
In reply to this post by ralfgommers
Just to add: nothing conceptually is strange for start and end to be arrays. Indeed, the code would work for arrays as is if it didn't check the `step == 0` case to handle denormals (arguably an even less common case than array-like inputs...), and made a trivial change to get the new axis to be at the start.

(I guess I'm agreeing with Matthew here that if conceptually things make sense for arrays, then it should just work; there are of course counterexample, such as `np.arange`, for which array-valued input makes even less sense than allowing float and complex).

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Lars Grüter
In reply to this post by Stephan Hoyer-2
On 14.11.18 17:57, Stephan Hoyer wrote:

> It recently came up on GitHub (at part of the discussion
> in https://github.com/numpy/numpy/issues/12379) that numpy.linspace
> could, at least in principle, be modified to support array inputs:
>
> It looks like this has been requested on StackOverflow, too:
> https://stackoverflow.com/questions/46694167/vectorized-numpy-linspace-across-multi-dimensional-arrays
>
> My tentative proposal:
> - "start" and "stop" are broadcast against each other to form start/stop
> arrays. (Or we could require that start/stop have matching shape.)
> - A new dimension of size "num" is inserted into the result, either
> along the first or last axis.
> - A new keyword argument "axis" could control where the axis is inserted
> in the result.
> - Vectorization support should be added in the same way to geomspace and
> logspace.

This reminds me of a function [1] I wrote which I think has a lot of
similarities to what Stephan describes here. It is currently part of a
PR to rewrite numpy.pad [2].

Maybe that's helpful to know depending on how this discussion resolves. :)

Best regards,
Lars

[1]
https://github.com/lagru/numpy/blob/605fc1d7f871b1c8cf2783f594dee88cdf96d7ec/numpy/lib/arraypad.py#L14-L67
[2] https://github.com/numpy/numpy/pull/11358
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Marten van Kerkwijk
Code being better than words: see https://github.com/numpy/numpy/pull/12388 for an implementation. The change in the code proper is very small, though it is worrying that it causes two rather unrelated tests too fail (even if arguably both tests were wrong).

Note that this does not give flexibility to put the axis where one wants; as written, the code made putting it at the start the obvious solution, as it avoids doing anything with the shapes of start and stop.

-- Marten

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Marten van Kerkwijk
In reply to this post by Lars Grüter


On Wed, Nov 14, 2018 at 1:21 PM Lars Grüter <[hidden email]> wrote:
<snip>

This reminds me of a function [1] I wrote which I think has a lot of
similarities to what Stephan describes here. It is currently part of a
PR to rewrite numpy.pad [2].

If we start to write the equivalent internally, then perhaps we should indeed expose it!
Would my trial indeed help, or is it insufficient? (Sorry for not checking myself in detail; it is not immediately obvious.)
-- Marten

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Sebastian Berg
In reply to this post by Marten van Kerkwijk
On Wed, 2018-11-14 at 14:32 -0500, Marten van Kerkwijk wrote:

> Code being better than words: see
> https://github.com/numpy/numpy/pull/12388 for an implementation. The
> change in the code proper is very small, though it is worrying that
> it causes two rather unrelated tests too fail (even if arguably both
> tests were wrong).
>
> Note that this does not give flexibility to put the axis where one
> wants; as written, the code made putting it at the start the obvious
> solution, as it avoids doing anything with the shapes of start and
> stop.
Hehe, my first gut feeling was the last axis to be the obvious one ;).
This has been discussed before (but what hasn't) I believe, probably
some old issue or even PR somewhere.
I am mildly in favor, just because there is probably not much reason
against an easy vectorization. Doesn't need to be advertised much in
the docs anyway.
Although it might be good to settle the "obvious" part in case I am not
alone in first thinking of -1 being the obvious default. I would
probably skip the axis argument for now, unless someone actually has a
use case.

I think this used to half work at some point, but it was probably so
broken that we can just make it well defined?

- Sebastian


>
> -- Marten
> _______________________________________________
> NumPy-Discussion mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/numpy-discussion

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Stephan Hoyer-2


On Wed, Nov 14, 2018 at 2:35 PM Sebastian Berg <[hidden email]> wrote:
On Wed, 2018-11-14 at 14:32 -0500, Marten van Kerkwijk wrote:
> Code being better than words: see
> https://github.com/numpy/numpy/pull/12388 for an implementation. The
> change in the code proper is very small, though it is worrying that
> it causes two rather unrelated tests too fail (even if arguably both
> tests were wrong).
>
> Note that this does not give flexibility to put the axis where one
> wants; as written, the code made putting it at the start the obvious
> solution, as it avoids doing anything with the shapes of start and
> stop.

Hehe, my first gut feeling was the last axis to be the obvious one ;).
This has been discussed before (but what hasn't) I believe, probably
some old issue or even PR somewhere.
I am mildly in favor, just because there is probably not much reason
against an easy vectorization. Doesn't need to be advertised much in
the docs anyway.
Although it might be good to settle the "obvious" part in case I am not
alone in first thinking of -1 being the obvious default. I would
probably skip the axis argument for now, unless someone actually has a
use case.

Indeed -- I think the best argument for adding an "axis" argument is that it allows people to be explicit about where the axis ends up, e.g., both np.linspace(start, stop, num=5, axis=0) and np.linspace(start, stop, num=5, axis=-1) make their intent quite clear.

To me, axis=0 feels like the right default, matching np.concatenate and np.stack. But NumPy already has split conventions for this sort of thing (e.g., gufuncs add axes at the end), so I like the explicit option.

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Vectorized version of numpy.linspace

einstein.edison
On Wednesday, Nov 14, 2018 at 11:46 PM, Stephan Hoyer <[hidden email]> wrote:


On Wed, Nov 14, 2018 at 2:35 PM Sebastian Berg <[hidden email]> wrote:
On Wed, 2018-11-14 at 14:32 -0500, Marten van Kerkwijk wrote:
> Code being better than words: see
> https://github.com/numpy/numpy/pull/12388 for an implementation. The
> change in the code proper is very small, though it is worrying that
> it causes two rather unrelated tests too fail (even if arguably both
> tests were wrong).
>
> Note that this does not give flexibility to put the axis where one
> wants; as written, the code made putting it at the start the obvious
> solution, as it avoids doing anything with the shapes of start and
> stop.

Hehe, my first gut feeling was the last axis to be the obvious one ;).
This has been discussed before (but what hasn't) I believe, probably
some old issue or even PR somewhere.
I am mildly in favor, just because there is probably not much reason
against an easy vectorization. Doesn't need to be advertised much in
the docs anyway.
Although it might be good to settle the "obvious" part in case I am not
alone in first thinking of -1 being the obvious default. I would
probably skip the axis argument for now, unless someone actually has a
use case.

Indeed -- I think the best argument for adding an "axis" argument is that it allows people to be explicit about where the axis ends up, e.g., both np.linspace(start, stop, num=5, axis=0) and np.linspace(start, stop, num=5, axis=-1) make their intent quite clear.

To me, axis=0 feels like the right default, matching np.concatenate and np.stack. But NumPy already has split conventions for this sort of thing (e.g., gufuncs add axes at the end), so I like the explicit option.

I’d like to have another vote for axis=-1 by default. Stack and concatenate are different because we are concatenating/stacking complete arrays, so it makes sense to “compose” them along the first axis to maintain C-contiguous-ness.

I actually think of this as the reverse, we are “composing/combining” lots of 1D arrays over all the other dimensions, so to preserve C-contiguous-ness, it’s better to have axis=-1.

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion

Best Regards,
Hameer Abbasi

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Marten van Kerkwijk
I see the logic in having the linear space be last, but one non-negligible advantage of the default being the first axis is that whatever is produced broadcasts properly against start and stop.
-- Marten

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Stephan Hoyer-2
On Wed, Nov 14, 2018 at 3:16 PM Marten van Kerkwijk <[hidden email]> wrote:
I see the logic in having the linear space be last, but one non-negligible advantage of the default being the first axis is that whatever is produced broadcasts properly against start and stop.
-- Marten

Yes, this is exactly why I needed to insert the new axis at the start.

That said, either default axis position is fine by me as long as we have the explicit option.

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Eric Wieser

I too buy into axis=0 being the better default here for broadcasting reasons. Having it possible to specify explicitly would be handy though, for something like:

x_ramped = np.linspace(x.min(axis=2), x.max(axis=2), 100, axis=2)

On Wed, 14 Nov 2018 at 15:20 Stephan Hoyer <[hidden email]> wrote:
On Wed, Nov 14, 2018 at 3:16 PM Marten van Kerkwijk <[hidden email]> wrote:
I see the logic in having the linear space be last, but one non-negligible advantage of the default being the first axis is that whatever is produced broadcasts properly against start and stop.
-- Marten

Yes, this is exactly why I needed to insert the new axis at the start.

That said, either default axis position is fine by me as long as we have the explicit option.
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Vectorized version of numpy.linspace

Sebastian Berg
In reply to this post by Stephan Hoyer-2
On Wed, 2018-11-14 at 14:46 -0800, Stephan Hoyer wrote:
>
>
> On Wed, Nov 14, 2018 at 2:35 PM Sebastian Berg <
> [hidden email]> wrote:
> > On Wed, 2018-11-14 at 14:32 -0500, Marten van Kerkwijk wrote:
<snip>

> > some old issue or even PR somewhere.
> > I am mildly in favor, just because there is probably not much
> > reason
> > against an easy vectorization. Doesn't need to be advertised much
> > in
> > the docs anyway.
> > Although it might be good to settle the "obvious" part in case I am
> > not
> > alone in first thinking of -1 being the obvious default. I would
> > probably skip the axis argument for now, unless someone actually
> > has a
> > use case.
>
> Indeed -- I think the best argument for adding an "axis" argument is
> that it allows people to be explicit about where the axis ends up,
> e.g., both np.linspace(start, stop, num=5, axis=0) and
> np.linspace(start, stop, num=5, axis=-1) make their intent quite
> clear.
>
> To me, axis=0 feels like the right default, matching np.concatenate
> and np.stack. But NumPy already has split conventions for this sort
> of thing (e.g., gufuncs add axes at the end), so I like the explicit
> option.
I think that argument goes both ways. Because linspace with an array
input can be seen as stacking the linear ramps and not stacking some
interpolated intermediate values from start/stop. (Sure, it is more
then one dimension, but I would seriously argue the linear ramps are
the basic building block and not the input start/stop arrays.)

- Sebastian


> _______________________________________________
> NumPy-Discussion mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/numpy-discussion

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion

signature.asc (849 bytes) Download Attachment