2

I am wondering if it is expected that if I call numpy.sum on a PyTorch tensor I get an error. As an aside, it does work on Pandas DataFrames.

data = [[1.1, 2.2], [1.1, 2.2], [1.1, 2.2]]

a = np.array(data)
d = pd.DataFrame(data)
t = torch.tensor(data)

np.sum(a, axis=1) # works obviously
np.sum(d, axis=1) # works
np.sum(t, axis=1) # fails

If you dig a bit inside, you'll see that's quite simply because numpy.sum tries to call torch.Tensor.sum with keyword argumets which do not belong to it, like in the following (https://github.com/numpy/numpy/blob/main/numpy/_core/fromnumeric.py around line 80)

return reduction(axis=axis, out=out, **passkwargs)

which inevitably results in an error.

This seems quite related: https://github.com/numpy/numpy/issues/28024

Can this be considered a bug in numpy? Why can't we just pass the non null arguments to the sum method of the object we are passing to numpy.sum?

I wanted to post an issue on GitHub/numpy but I am not sure I could define this as a bug, and if i click "question" there, then I am told to post here...

2
  • According to the documentation of numpy.sum, it takes an "array-like". I don't know the definition of "array-like", or if a torch.Tensor is considered as an "array-like". I would only call this a bug if they "officially" support torch.Tensor inputs in this function, i.e. if they do consider tensors as "array-like". Commented Jun 19 at 12:13
  • The python array api standard aims to address issues like this. You can use the library array-api-compat Commented Jun 20 at 4:57

2 Answers 2

5

Yes, it is expected that numpy.sum() fails on a PyTorch tensor.

The reason is that numpy.sum() tries to call the tensor's own .sum() method and passes along its own specific set of keyword arguments (like axis, out, etc.).

  • Why it works with Pandas: The pandas.DataFrame.sum() method is intentionally designed to be compatible with NumPy and accepts these arguments.

  • Why it fails with PyTorch: The torch.Tensor.sum() method has a different signature and does not accept all of NumPy's arguments, which results in a TypeError.

This is not considered a bug in NumPy. Instead, it's an API incompatibility issue. For seamless integration, the external library (PyTorch) would need to align its method with NumPy's.

The standard solution is to explicitly convert the tensor to a NumPy array first:


np.sum(t.numpy(), axis=1)
Sign up to request clarification or add additional context in comments.

1 Comment

I would tend to disagree, let me explain why. I am calling np.sum with axis=1 and that's it. Numpy goes on and calls torch.Tensor.sum not only with axis=1 but also with out=None. Why insisting in changing my call? If that were not the case, the call to np.sum would work.
4

This is not a bug. Pytorch and numpy are separate libraries, they have no obligation to support each other's APIs. While the libraries make a best effort to be interoperable (link, link), there is no guarantee everything will work. The best practice is not to interop different array types. For example np.sum(t.numpy(), axis=1) avoids this error by converting the pytorch tensor to a numpy array.

The underlying issue gets into some real "in the weeds" stuff about pytorch and numpy. Both libraries provide certain operations as both pure function calls and object method calls - ie np.sum vs np.ndarray.sum and torch.sum vs torch.Tensor.sum.

For numpy the function and method variants both support an out= argument, while pytorch only supports out= for pure functions. This means torch.sum(x, 1, out=y) works while x.sum(1, out=y) throws an error. The numpy code is calling the method version with a out=None kwarg, causing the error.

I don't know if there is any documentation on this, but this has been a deliberate design decision in pytorch since 0.4.0 iirc, which I believe was motivated by issues related to autograd and tensor resizing/striding.

As to why you can't pass only the non-null arguments, numpy supports using out as either a positional argument or a keyword argument (I believe this is just a historical backwards compatibility thing). As a result, the _wrapreduction function needs to explicitly place the out argument - ie it cannot be rolled into passkwargs.

1 Comment

Thanks - it kind of makes sense to me now. I ll have to understand a bit better and I ll possibly come back to this answer when I have some time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.