[Numpy-discussion] Incrementing with advanced indexing: why don't repeated indexes repeatedly increment?
njs at pobox.com
Wed Jun 6 11:06:28 EDT 2012
On Wed, Jun 6, 2012 at 9:48 AM, John Salvatier
<jsalvati at u.washington.edu> wrote:
> I've noticed that If you try to increment elements of an array with advanced
> indexing, repeated indexes don't get repeatedly incremented. For example:
> In : x = zeros(5)
> In : idx = array([1,1,1,3,4])
> In : x[idx] += [2,4,8,10,30]
> In : x
> Out: array([ 0., 8., 0., 10., 30.])
> I would intuitively expect the output to be array([0,14, 0,10,30]) since
> index 1 is incremented by 2+4+8=14, but instead it seems to only increment
> by 8. What is numpy actually doing here?
> The authors of Theano noticed this behavior a while ago so they python loop
> through the values in idx (this kind of calculation is necessary for
> calculating gradients), but this is a bit slow for my purposes, so I'd like
> to figure out how to get the behavior I expected, but faster.
> I'm also not sure how to navigate the numpy codebase, where would I look for
> the code responsible for this behavior?
Strictly speaking, it isn't actually in the numpy codebase at all --
what's happening is that the Python interpreter sees this code:
x[idx] += vals
and then it translates it into this code before running it:
tmp = x.__getitem__(idx)
tmp = tmp.__iadd__(vals)
So you can find the implementations of the ndarray methods
__getitem__, __iadd__, __setitem__ (they're called
array_subscript_nice, array_inplace_add, and array_ass_sub in the C
code), but there's no way to fix them so that this works the way you
want it to, because there's no way for __iadd__ to know that the
temporary values that it's working with are really duplicate copies of
"the same" value in the original array.
It would be nice if numpy had some sort of standard API for doing what
you want, but not sure what a good API would look like, and someone
would have to implement it.
More information about the NumPy-Discussion