pythonnumpypytorchcompatibility

Numpy function sum does not work on PyTorch tensors


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...


Solution

  • 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.