[Numpy-discussion] Is this a bug?
Eric Moore
ewm at redtetrahedron.org
Tue Sep 16 19:03:27 EDT 2014
On Tuesday, September 16, 2014, Jaime Fernández del Río <
jaime.frio at gmail.com> wrote:
> On Tue, Sep 16, 2014 at 3:26 PM, Charles R Harris <
> charlesr.harris at gmail.com
> <javascript:_e(%7B%7D,'cvml','charlesr.harris at gmail.com');>> wrote:
>
>>
>>
>> On Tue, Sep 16, 2014 at 2:51 PM, Nathaniel Smith <njs at pobox.com
>> <javascript:_e(%7B%7D,'cvml','njs at pobox.com');>> wrote:
>>
>>> On Tue, Sep 16, 2014 at 4:31 PM, Jaime Fernández del Río
>>> <jaime.frio at gmail.com
>>> <javascript:_e(%7B%7D,'cvml','jaime.frio at gmail.com');>> wrote:
>>> > If it is a bug, it is an extended one, because it is the same behavior
>>> of
>>> > einsum:
>>> >
>>> >>>> np.einsum('i,i', [1,1,1], [1])
>>> > 3
>>> >>>> np.einsum('i,i', [1,1,1], [1,1])
>>> > Traceback (most recent call last):
>>> > File "<stdin>", line 1, in <module>
>>> > ValueError: operands could not be broadcast together with remapped
>>> shapes
>>> > [origi
>>> > nal->remapped]: (3,)->(3,) (2,)->(2,)
>>> >
>>> > And I think it is a conscious design decision, there is a comment about
>>> > broadcasting missing core dimensions here:
>>> >
>>> >
>>> https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/ufunc_object.c#L1940
>>>
>>> "intentional" and "sensible" are not always the same thing :-). That
>>> said, it isn't totally obvious to me what the correct behaviour for
>>> einsum is in this case.
>>>
>>> > and the code makes it very explicit that input argument dimensions
>>> with the
>>> > same label are broadcast to a common shape, see here:
>>> >
>>> >
>>> https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/ufunc_object.c#L1956
>>> >
>>> > I kind of expect numpy to broadcast whenever possible, so this doesn't
>>> feel
>>> > wrong to me.
>>>
>>> The case Chuck is talking about is like if we allowed matrix
>>> multiplication between an array with shape (n, 1) with an array with
>>> (k, m), because (n, 1) can be broadcast to (n, k). This feels VERY
>>> wrong to me, will certainly hide many bugs, and is definitely not how
>>> it works right now (for np.dot, anyway; apparently it does work that
>>> way for the brand-new gufunc np.linalg.matrix_multiply, but this must
>>> be an accident).
>>>
>>> > That said, it is hard to come up with convincing examples of how this
>>> > behavior would be useful in any practical context. But changing
>>> something
>>> > that has been working like that for so long seems like a risky thing.
>>> And I
>>> > cannot come with a convincing example of why it would be harmful
>>> either.
>>>
>>> gufuncs are very new.
>>>
>>>
>> Or at least newly used. They've been sitting around for years with little
>> use and less testing. This is probably (easily?) fixable as the shape of
>> the operands is available.
>>
>> In [22]: [d.shape for d in nditer([[1,1,1], [[1,1,1]]*3]).operands]
>> Out[22]: [(3,), (3, 3)]
>>
>> In [23]: [d.shape for d in nditer([[[1,1,1]], [[1,1,1]]*3]).operands]
>> Out[23]: [(1, 3), (3, 3)]
>>
>>
> If we agree that it is broken, which I still am not fully sure of, then
> yes, it is very easy to fix. I have been looking into that code quite a bit
> lately, so I could patch something up pretty quick.
>
> Are we OK with the appending of size 1 dimensions to complete the core
> dimensions? That is, should matrix_multiply([1,1,1], [[1],[1],[1]]) work,
> or should it complain about the first argument having less dimensions than
> the core dimensions in the signature?
>
> Lastly, there is an interesting side effect of the way this broadcasting
> is handled: if a gufunc specifies a core dimension in an output argument
> only, and an `out` kwarg is not passed in, then the output array will have
> that core dimension set to be of size 1, e.g. if the signature of `f` is
> '(),()->(a)', then f(1, 2).shape is (1,). This has always felt funny to me,
> and I think that an unspecified dimension in an output array should either
> be specified by a passed out array, or raise an error about an unspecified
> core dimension or something like that. Does this sound right?
>
> Jaime
>
> --
> (\__/)
> ( O.o)
> ( > <) Este es Conejo. Copia a Conejo en tu firma y ayúdale en sus planes
> de dominación mundial.
>
Given this and the earlier discussion about improvements to this code, I
wonder if it wouldn't be worth implemented the logic in python first. This
way there is something to test against, and something to play while all of
the cases are sorted out.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20140916/6e70c541/attachment.html>
More information about the NumPy-Discussion
mailing list