[Numpy-discussion] ENH: Proposal to add atleast_nd function

Ralf Gommers ralf.gommers at gmail.com
Fri Feb 12 15:41:26 EST 2021


On Fri, Feb 12, 2021 at 9:21 PM Robert Kern <robert.kern at gmail.com> wrote:

> On Fri, Feb 12, 2021 at 1:47 PM Ralf Gommers <ralf.gommers at gmail.com>
> wrote:
>
>>
>> On Fri, Feb 12, 2021 at 7:25 PM Sebastian Berg <
>> sebastian at sipsolutions.net> wrote:
>>
>>> On Fri, 2021-02-12 at 10:08 -0500, Robert Kern wrote:
>>> > On Fri, Feb 12, 2021 at 9:45 AM Joseph Fox-Rabinovitz <
>>> > jfoxrabinovitz at gmail.com> wrote:
>>> >
>>> > >
>>> > >
>>> > > On Fri, Feb 12, 2021, 09:32 Robert Kern <robert.kern at gmail.com>
>>> > > wrote:
>>> > >
>>> > > > On Fri, Feb 12, 2021 at 5:15 AM Eric Wieser <
>>> > > > wieser.eric+numpy at gmail.com>
>>> > > > wrote:
>>> > > >
>>> > > > > > There might be some linear algebraic reason why those axis
>>> > > > > > positions
>>> > > > > make sense, but I’m not aware of it...
>>> > > > >
>>> > > > > My guess is that the historical motivation was to allow
>>> > > > > grayscale `(H,
>>> > > > > W)` images to be converted into `(H, W, 1)` images so that they
>>> > > > > can be
>>> > > > > broadcast against `(H, W, 3)` RGB images.
>>> > > > >
>>> > > >
>>> > > > Correct. If you do introduce atleast_nd(), I'm not sure why you'd
>>> > > > deprecate and remove the one existing function that *isn't* made
>>> > > > redundant
>>> > > > thereby.
>>> > > >
>>> > >
>>> > > `atleast_nd` handles the promotion of 2D to 3D correctly. The `pos`
>>> > > argument lets you tell it where to put the new axes. What's
>>> > > unintuitive to
>>> > > my is that the 1D case gets promoted to from shape `(x,)` to shape
>>> > > `(1, x,
>>> > > 1)`. It takes two calls to `atleast_nd` to replicate that behavior.
>>> > >
>>> >
>>> > When thinking about channeled images, the channel axis is not of the
>>> > same
>>> > kind as the H and W axes. Really, you tend to want to think about an
>>> > RGB
>>> > image as a (H, W) array of colors rather than an (H, W, 3) ndarray of
>>> > intensity values. As much as possible, you want to treat RGB images
>>> > similar
>>> > to (H, W)-shaped grayscale images. Let's say I want to make a
>>> > separable
>>> > filter to convolve with my image, that is, we have a 1D filter for
>>> > each of
>>> > the H and W axes, and they are repeated for each channel, if RGB.
>>> > Setting
>>> > up a separable filter for (H, W) grayscale is straightforward with
>>> > broadcasting semantics. I can use (ntaps,)-shaped vector for the W
>>> > axis and
>>> > (ntaps, 1)-shaped filter for the H axis. Now, when I go to the RGB
>>> > case, I
>>> > want the same thing. atleast_3d() adapts those correctly for the (H,
>>> > W,
>>> > nchannels) case.
>>>
>>> Right, my initial feeling it that without such context `atleast_3d` is
>>> pretty surprising.  So I wonder if we can design `atleast_nd` in a way
>>> that it is explicit about this context.
>>>
>>
>> Agreed. I think such a use case is probably too specific to design a
>> single function for, at least in such a hardcoded way.
>>
>
> That might be an argument for not designing a new one (or at least not
> giving it such a name). Not sure it's a good argument for removing a
> long-standing one.
>

I agree. I'm not sure deprecating is best. But introducing new
functionality where `nd(pos=3) != 3d` is also not great.

At the very least, atleast_3d should be better documented. It also is
telling that Juan (a long-time) scikit-image dev doesn't like atleast_3d
and there's very little usage of it in scikit-image.

Cheers,
Ralf


> Broadcasting is a very powerful convention that makes coding with arrays
> tolerable. It makes some choices (namely, prepending 1s to the shape) to
> make some common operations with mixed-dimension arrays work "by default".
> But it doesn't cover all of the desired operations conveniently.
> atleast_3d() bridges the gap to an important convention for a major
> use-case of arrays.
>
> There's also "channels first" and "channels last" versions of RGB images
>> as 3-D arrays, and "channels first" is the default in most deep learning
>> frameworks - so the choice atleast_3d makes is a little outdated by now.
>>
>
> DL frameworks do not constitute the majority of image processing code,
> which has a very strong channels-last contingent. But nonetheless, the very
> popular Tensorflow defaults to channels-last.
>
> --
> Robert Kern
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at python.org
> https://mail.python.org/mailman/listinfo/numpy-discussion
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/numpy-discussion/attachments/20210212/9b4a1024/attachment.html>


More information about the NumPy-Discussion mailing list