Skip to content

Broadcasting does not work with inplace "+=" operator #9031

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

Closed
mratsim opened this issue Apr 30, 2017 · 3 comments
Closed

Broadcasting does not work with inplace "+=" operator #9031

mratsim opened this issue Apr 30, 2017 · 3 comments

Comments

@mratsim
Copy link

mratsim commented Apr 30, 2017

I am implementing Welford's algorithm to compute mean and variance on a series of images.

Broadcasting does not work.

The algorithm for scalars courtesy of Wikipedia

def online_variance(data):
    n = 0
    mean = 0.0
    M2 = 0.0

    for x in data:
        n += 1
        delta = x - mean
        mean += delta/n
        delta2 = x - mean
        M2 += delta*delta2

    if n < 2:
        return float('nan')
    else:
        return M2 / (n - 1)

For numpy arrays I am forced to replace mean += delta/n by mean = mean + delta/n

The error I get is non-broadcastable output operand with shape () doesn't match the broadcast shape (256,256,3). My images have shape 256x256x3 (RGB).

@eric-wieser
Copy link
Member

eric-wieser commented Apr 30, 2017

This is by design, because the inplace operators are intended to operate on the same chunk of memory as the input - but the broadcast result would not find in that memory.

Having said that, it might be reasonable to allow a1d += a2d to decay into a1d = a1d + a2d, especially given a discussion in #9019

In your case, the fix is simple - just allocate the arrays to the correct size first - at a guess, that would be:

mean = np.zeros(data.shape[1:])
M2 = np.zeros(data.shape[1:])

@shoyer
Copy link
Member

shoyer commented Apr 30, 2017

@mratsim Can you give an example of input that triggers this error? When I run your function on NumPy arrays it works properly:

In [19]: online_variance([np.arange(3.0), -np.arange(3.0)])
Out[19]: array([ 0.,  2.,  8.])

In [20]: online_variance([np.array(1.0), np.array(2.0)])
Out[20]: 0.5

@mratsim
Copy link
Author

mratsim commented May 1, 2017

I've found out the issue, I was actually initializing my variables with an empty array due to a mistake.

Screenshot: "os.path.join" missing at initialization:
image

That was catched by the += but was slient otherwise:
image

So that can be closed

While investigating, I uncovered a precedence issue with += however. I will raise an issue about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants